/[svn]/gigedit/trunk/src/gigedit/dimregionchooser.cpp
ViewVC logotype

Diff of /gigedit/trunk/src/gigedit/dimregionchooser.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2556 by schoenebeck, Fri May 16 23:19:23 2014 UTC revision 3089 by schoenebeck, Sun Jan 15 19:18:39 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2014 Andreas Persson   * Copyright (C) 2006-2017 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
20    #include <gtkmm/box.h>
21  #include "dimregionchooser.h"  #include "dimregionchooser.h"
22  #include <cairomm/context.h>  #include <cairomm/context.h>
23  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
24  #include <gdkmm/general.h>  #include <gdkmm/general.h>
25  #include <glibmm/stringutils.h>  #include <glibmm/stringutils.h>
 #include <gtkmm/stock.h>  
26  #include <glibmm/ustring.h>  #include <glibmm/ustring.h>
27  #include <gtkmm/messagedialog.h>  #include <gtkmm/messagedialog.h>
28    #include <assert.h>
29    
30  #include "global.h"  #include "global.h"
31    
32  DimRegionChooser::DimRegionChooser() :  // taken from gdk/gdkkeysyms.h
33    // (define on demand, to avoid unnecessary dev lib package build dependency)
34    #ifndef GDK_KEY_Control_L
35    # define GDK_KEY_Control_L 0xffe3
36    #endif
37    #ifndef GDK_KEY_Control_R
38    # define GDK_KEY_Control_R 0xffe4
39    #endif
40    
41    static std::map<gig::dimension_t,int> caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
42        std::map<gig::dimension_t,int> dimCase;
43        if (!dr) {
44            *isValidZone = false;
45            return dimCase;
46        }
47    
48        gig::Region* rgn = (gig::Region*) dr->GetParent();
49    
50        // find the dimension region index of the passed dimension region
51        int drIndex;
52        for (drIndex = 0; drIndex < 256; ++drIndex)
53            if (rgn->pDimensionRegions[drIndex] == dr)
54                break;
55    
56        // not found in region, something's horribly wrong
57        if (drIndex == 256) {
58            fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");
59            *isValidZone = false;
60            return std::map<gig::dimension_t,int>();
61        }
62    
63        for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {
64            const int bits = rgn->pDimensionDefinitions[d].bits;
65            dimCase[rgn->pDimensionDefinitions[d].dimension] =
66                (drIndex >> baseBits) & ((1 << bits) - 1);
67            baseBits += bits;
68            // there are also DimensionRegion objects of unused zones, skip them
69            if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {
70                *isValidZone = false;
71                return std::map<gig::dimension_t,int>();
72            }
73        }
74    
75        *isValidZone = true;
76        return dimCase;
77    }
78    
79    DimRegionChooser::DimRegionChooser(Gtk::Window& window) :
80      red("#8070ff"),      red("#8070ff"),
81      black("black"),      black("black"),
82      white("white")      white("white")
83  {  {
84      instrument = 0;      instrument = 0;
85      region = 0;      region = 0;
86      dimregno = -1;      maindimregno = -1;
87      focus_line = 0;      focus_line = 0;
88      resize.active = false;      resize.active = false;
89      cursor_is_resize = false;      cursor_is_resize = false;
90      h = 20;      h = 24;
91        multiSelectKeyDown = false;
92        modifybothchannels = modifyalldimregs = modifybothchannels = false;
93      set_can_focus();      set_can_focus();
94    
95      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
# Line 74  DimRegionChooser::DimRegionChooser() : Line 124  DimRegionChooser::DimRegionChooser() :
124      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
125                 Gdk::POINTER_MOTION_HINT_MASK);                 Gdk::POINTER_MOTION_HINT_MASK);
126    
     for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;  
127      labels_changed = true;      labels_changed = true;
128    
129      set_tooltip_text(_("Right click here for options on altering dimension zones."));      set_tooltip_text(_(
130            "Right click here for options on altering dimension zones. Press and "
131            "hold CTRL key for selecting multiple dimension zones simultaniously."
132        ));
133        
134        window.signal_key_press_event().connect(
135            sigc::mem_fun(*this, &DimRegionChooser::onKeyPressed)
136        );
137        window.signal_key_release_event().connect(
138            sigc::mem_fun(*this, &DimRegionChooser::onKeyReleased)
139        );
140  }  }
141    
142  DimRegionChooser::~DimRegionChooser()  DimRegionChooser::~DimRegionChooser()
143  {  {
144  }  }
145    
146    void DimRegionChooser::setModifyBothChannels(bool b) {
147        modifybothchannels = b;
148    }
149    
150    void DimRegionChooser::setModifyAllDimensionRegions(bool b) {
151        modifyalldimregs = b;
152    }
153    
154    void DimRegionChooser::setModifyAllRegions(bool b) {
155        modifyallregions = b;
156    }
157    
158  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
159  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
160  {  {
# Line 94  bool DimRegionChooser::on_expose_event(G Line 165  bool DimRegionChooser::on_expose_event(G
165    
166      const Cairo::RefPtr<Cairo::Context>& cr =      const Cairo::RefPtr<Cairo::Context>& cr =
167          get_window()->create_cairo_context();          get_window()->create_cairo_context();
 #if 0  
 }  
 #endif  
168  #else  #else
169  bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)  bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
170  {  {
# Line 212  bool DimRegionChooser::on_draw(const Cai Line 280  bool DimRegionChooser::on_draw(const Cai
280      for (int i = 0 ; i < region->Dimensions ; i++) {      for (int i = 0 ; i < region->Dimensions ; i++) {
281          int nbZones = region->pDimensionDefinitions[i].zones;          int nbZones = region->pDimensionDefinitions[i].zones;
282          if (nbZones) {          if (nbZones) {
283                const gig::dimension_t dimension = region->pDimensionDefinitions[i].dimension;
284    
285              if (y >= clipy2) break;              if (y >= clipy2) break;
286              if (y + h > clipy1) {              if (y + h > clipy1) {
287                  // draw focus rectangle around dimension's label and zones                  // draw focus rectangle around dimension's label and zones
288                  if (has_focus() && focus_line == i) {                  if (has_focus() && focus_line == i) {
289  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
290                      Gdk::Rectangle farea(0, y, 150, 20);                      Gdk::Rectangle farea(0, y, 150, h);
291                      get_style()->paint_focus(get_window(), get_state(), farea,                      get_style()->paint_focus(get_window(), get_state(), farea,
292                                               *this, "",                                               *this, "",
293                                               0, y, label_width, 20);                                               0, y, label_width, h);
294  #else  #else
295                      get_style_context()->render_focus(cr,                      get_style_context()->render_focus(cr,
296                                                        0, y, label_width, 20);                                                        0, y, label_width, h);
297  #endif  #endif
298                  }                  }
299    
# Line 242  bool DimRegionChooser::on_draw(const Cai Line 312  bool DimRegionChooser::on_draw(const Cai
312                  cr->fill();                  cr->fill();
313    
314                  int c = 0;                  int c = 0;
315                  if (dimregno >= 0) {                  if (maindimregno >= 0) {
316                      int mask =                      int mask =
317                          ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<                          ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<
318                            bitpos);                            bitpos);
319                      c = dimregno & mask; // mask away this dimension                      c = maindimregno & mask; // mask away this dimension
320                  }                  }
321                  bool customsplits =                  bool customsplits =
322                      ((region->pDimensionDefinitions[i].split_type ==                      ((region->pDimensionDefinitions[i].split_type ==
# Line 256  bool DimRegionChooser::on_draw(const Cai Line 326  bool DimRegionChooser::on_draw(const Cai
326                        gig::dimension_velocity &&                        gig::dimension_velocity &&
327                        region->pDimensionRegions[c]->VelocityUpperLimit));                        region->pDimensionRegions[c]->VelocityUpperLimit));
328    
329                  // draw dimension's zone borders                  // draw dimension zones
330                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
331                  if (customsplits) {                  if (customsplits) {
332                      cr->move_to(label_width + 0.5, y + 1);                      cr->move_to(label_width + 0.5, y + 1);
333                      cr->line_to(label_width + 0.5, y + h - 1);                      cr->line_to(label_width + 0.5, y + h - 1);
334                        int prevX = label_width;
335                        int prevUpperLimit = -1;
336    
337                      for (int j = 0 ; j < nbZones ; j++) {                      for (int j = 0 ; j < nbZones ; j++) {
338                            // draw dimension zone's borders for custom splits
339                          gig::DimensionRegion* d =                          gig::DimensionRegion* d =
340                              region->pDimensionRegions[c + (j << bitpos)];                              region->pDimensionRegions[c + (j << bitpos)];
341                          int upperLimit = d->DimensionUpperLimits[i];                          int upperLimit = d->DimensionUpperLimits[i];
# Line 272  bool DimRegionChooser::on_draw(const Cai Line 345  bool DimRegionChooser::on_draw(const Cai
345                              label_width;                              label_width;
346                          if (x >= clipx2) break;                          if (x >= clipx2) break;
347                          if (x < clipx1) continue;                          if (x < clipx1) continue;
348                            Gdk::Cairo::set_source_rgba(cr, black);
349                          cr->move_to(x + 0.5, y + 1);                          cr->move_to(x + 0.5, y + 1);
350                          cr->line_to(x + 0.5, y + h - 1);                          cr->line_to(x + 0.5, y + h - 1);
351                            cr->stroke();
352    
353                            // draw fill for zone
354                            bool isSelectedZone = this->dimzones[dimension].count(j);
355                            Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);
356                            cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
357                            cr->fill();
358    
359                            // draw text showing the beginning of the dimension zone
360                            // as numeric value to the user
361                            {
362                                Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
363                                layout->set_text(Glib::Ascii::dtostr(prevUpperLimit+1));
364                                Gdk::Cairo::set_source_rgba(cr, black);
365                                // get the text dimensions
366                                int text_width, text_height;
367                                layout->get_pixel_size(text_width, text_height);
368                                // move text to the left end of the dimension zone
369                                cr->move_to(prevX + 3, y + (h - text_height) / 2);
370    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
371                                pango_cairo_show_layout(cr->cobj(), layout->gobj());
372    #else
373                                layout->show_in_cairo_context(cr);
374    #endif
375                            }
376                            // draw text showing the end of the dimension zone
377                            // as numeric value to the user
378                            {
379                                Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
380                                layout->set_text(Glib::Ascii::dtostr(upperLimit));
381                                Gdk::Cairo::set_source_rgba(cr, black);
382                                // get the text dimensions
383                                int text_width, text_height;
384                                layout->get_pixel_size(text_width, text_height);
385                                // move text to the left end of the dimension zone
386                                cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
387    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
388                                pango_cairo_show_layout(cr->cobj(), layout->gobj());
389    #else
390                                layout->show_in_cairo_context(cr);
391    #endif
392                            }
393    
394                            prevX = x;
395                            prevUpperLimit = upperLimit;
396                      }                      }
397                  } else {                  } else {
398                        int prevX = 0;
399                      for (int j = 0 ; j <= nbZones ; j++) {                      for (int j = 0 ; j <= nbZones ; j++) {
400                            // draw dimension zone's borders for normal splits
401                          int x = int((w - label_width - 1) * j /                          int x = int((w - label_width - 1) * j /
402                                      double(nbZones) + 0.5) + label_width;                                      double(nbZones) + 0.5) + label_width;
403                          if (x >= clipx2) break;                          if (x >= clipx2) break;
404                          if (x < clipx1) continue;                          if (x < clipx1) continue;
405                            Gdk::Cairo::set_source_rgba(cr, black);
406                          cr->move_to(x + 0.5, y + 1);                          cr->move_to(x + 0.5, y + 1);
407                          cr->line_to(x + 0.5, y + h - 1);                          cr->line_to(x + 0.5, y + h - 1);
408                      }                          cr->stroke();
                 }  
                 cr->stroke();  
409    
410                  // draw fill for currently selected zone                          if (j != 0) {
411                  if (dimregno >= 0) {                              // draw fill for zone
412                      Gdk::Cairo::set_source_rgba(cr, red);                              bool isSelectedZone = this->dimzones[dimension].count(j-1);
413                      int dr = (dimregno >> bitpos) &                              Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);
414                          ((1 << region->pDimensionDefinitions[i].bits) - 1);                              cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
                       
                     int x1 = -1, x2 = -1;  
                     if (customsplits) {  
                         x1 = label_width;  
                         for (int j = 0 ; j < nbZones && x1 + 1 < clipx2 ; j++) {  
                             gig::DimensionRegion* d =  
                                 region->pDimensionRegions[c + (j << bitpos)];  
                             int upperLimit = d->DimensionUpperLimits[i];  
                             if (!upperLimit) {  
                                 upperLimit = d->VelocityUpperLimit;  
                             }  
                             int v = upperLimit + 1;  
                             x2 = int((w - label_width - 1) * v / 128.0 +  
                                      0.5) + label_width;  
                             if (j == dr && x1 < x2) {  
                                 cr->rectangle(x1 + 1, y + 1,  
                                               (x2 - x1) - 1, h - 2);  
                                 cr->fill();  
                                 break;  
                             }  
                             x1 = x2;  
                         }  
                     } else {  
                         if (dr < nbZones) {  
                             x1 = int((w - label_width - 1) * dr /  
                                      double(nbZones) + 0.5);  
                             x2 = int((w - label_width - 1) * (dr + 1) /  
                                      double(nbZones) + 0.5);  
                             cr->rectangle(label_width + x1 + 1, y + 1,  
                                           (x2 - x1) - 1, h - 2);  
415                              cr->fill();                              cr->fill();
                         }  
                     }  
416    
417                      // draw text showing the beginning of the dimension zone                              // draw text showing the beginning of the dimension zone
418                      // as numeric value to the user                              // as numeric value to the user
419                      if (x1 >= 0) {                              {
420                          Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
421                          int v = roundf(float(x1 - label_width) / float(w - label_width) * 127.f);                                  layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));
422                          if (dr > 0) v++;                                  Gdk::Cairo::set_source_rgba(cr, black);
423                          layout->set_text(Glib::Ascii::dtostr(v));                                  // get the text dimensions
424                          Gdk::Cairo::set_source_rgba(cr, black);                                  int text_width, text_height;
425                          Pango::Rectangle rect = layout->get_logical_extents();                                  layout->get_pixel_size(text_width, text_height);
426                                                            // move text to the left end of the dimension zone
427                          int text_width, text_height;                                  cr->move_to(prevX + 3, y + (h - text_height) / 2);
                         // get the text dimensions  
                         layout->get_pixel_size(text_width, text_height);  
                         // move text to the right end of the dimension zone  
                         cr->move_to(x1 + 1, y + 1);  
428  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
429                          pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
430  #else  #else
431                          layout->show_in_cairo_context(cr);                                  layout->show_in_cairo_context(cr);
432  #endif  #endif
433                      }                              }
434                      // draw text showing the end of the dimension zone                              // draw text showing the end of the dimension zone
435                      // as numeric value to the user                              // as numeric value to the user
436                      if (x2 >= 0) {                              {
437                          Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
438                          const int v = roundf(float(x2 - label_width) / float(w - label_width) * 127.f);                                  layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));
439                          layout->set_text(Glib::Ascii::dtostr(v));                                  Gdk::Cairo::set_source_rgba(cr, black);
440                          Gdk::Cairo::set_source_rgba(cr, black);                                  // get the text dimensions
441                          Pango::Rectangle rect = layout->get_logical_extents();                                  int text_width, text_height;
442                                                            layout->get_pixel_size(text_width, text_height);
443                          int text_width, text_height;                                  // move text to the left end of the dimension zone
444                          // get the text dimensions                                  cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
                         layout->get_pixel_size(text_width, text_height);  
                         // move text to the right end of the dimension zone  
                         cr->move_to(x2 - text_width - 1, y + 1);  
445  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
446                          pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
447  #else  #else
448                          layout->show_in_cairo_context(cr);                                  layout->show_in_cairo_context(cr);
449  #endif  #endif
450                      }                              }
451                            }
452                            prevX = x;
453                        }      
454                  }                  }
455              }              }
   
456              y += h;              y += h;
457          }          }
458          bitpos += region->pDimensionDefinitions[i].bits;          bitpos += region->pDimensionDefinitions[i].bits;
# Line 381  bool DimRegionChooser::on_draw(const Cai Line 464  bool DimRegionChooser::on_draw(const Cai
464  void DimRegionChooser::set_region(gig::Region* region)  void DimRegionChooser::set_region(gig::Region* region)
465  {  {
466      this->region = region;      this->region = region;
467      dimregno = 0;      maindimregno = 0;
468      nbDimensions = 0;      nbDimensions = 0;
469      if (region) {      if (region) {
470          int bitcount = 0;          int bitcount = 0;
# Line 389  void DimRegionChooser::set_region(gig::R Line 472  void DimRegionChooser::set_region(gig::R
472              if (region->pDimensionDefinitions[dim].bits == 0) continue;              if (region->pDimensionDefinitions[dim].bits == 0) continue;
473              nbDimensions++;              nbDimensions++;
474    
475              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              int z = std::min(maindimcase[region->pDimensionDefinitions[dim].dimension],
476                               region->pDimensionDefinitions[dim].zones - 1);                               region->pDimensionDefinitions[dim].zones - 1);
477              dimregno |= (z << bitcount);              maindimregno |= (z << bitcount);
478              bitcount += region->pDimensionDefinitions[dim].bits;              bitcount += region->pDimensionDefinitions[dim].bits;
479          }          }
         dimreg = region->pDimensionRegions[dimregno];  
     } else {  
         dimreg = 0;  
480      }      }
481      dimregion_selected();      dimregion_selected();
482      set_size_request(800, region ? nbDimensions * 20 : 0);      set_size_request(800, region ? nbDimensions * h : 0);
483    
484      labels_changed = true;      labels_changed = true;
485      queue_resize();      queue_resize();
486        queue_draw();
487  }  }
488    
489  void DimRegionChooser::refresh_all() {  void DimRegionChooser::refresh_all() {
# Line 412  void DimRegionChooser::refresh_all() { Line 493  void DimRegionChooser::refresh_all() {
493  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
494                                        std::set<gig::DimensionRegion*>& dimregs) const                                        std::set<gig::DimensionRegion*>& dimregs) const
495  {  {
496      int dimregno = 0;      for (int iDimRgn = 0; iDimRgn < 256; ++iDimRgn) {
497      int bitcount = 0;          gig::DimensionRegion* dimRgn = region->pDimensionRegions[iDimRgn];
498      int stereo_bit = 0;          if (!dimRgn) continue;
499      for (int dim = 0 ; dim < region->Dimensions ; dim++) {          bool isValidZone;
500          if (region->pDimensionDefinitions[dim].bits == 0) continue;          std::map<gig::dimension_t,int> dimCase = caseOfDimRegion(dimRgn, &isValidZone);
501          if (stereo &&          if (!isValidZone) continue;
502              region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {          for (std::map<gig::dimension_t,int>::const_iterator it = dimCase.begin();
503              stereo_bit = (1 << bitcount);               it != dimCase.end(); ++it)
504          } else {          {
505              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              if (stereo && it->first == gig::dimension_samplechannel) continue; // is selected
506                               region->pDimensionDefinitions[dim].zones - 1);  
507              dimregno |= (z << bitcount);              std::map<gig::dimension_t, std::set<int> >::const_iterator itSelectedDimension =
508                    this->dimzones.find(it->first);
509                if (itSelectedDimension != this->dimzones.end() &&
510                    itSelectedDimension->second.count(it->second)) continue; // is selected
511    
512                goto notSelected;
513          }          }
514          bitcount += region->pDimensionDefinitions[dim].bits;  
515            dimregs.insert(dimRgn);
516    
517            notSelected:
518            ;
519      }      }
     dimregs.insert(region->pDimensionRegions[dimregno]);  
     if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);  
520  }  }
521    
522  void DimRegionChooser::update_after_resize()  void DimRegionChooser::update_after_resize()
523  {  {
524      if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {      const uint8_t upperLimit = resize.pos - 1;
525        gig::Instrument* instr = (gig::Instrument*)region->GetParent();
526    
527          int bitpos = 0;      int bitpos = 0;
528          for (int j = 0 ; j < resize.dimension ; j++) {      for (int j = 0 ; j < resize.dimension ; j++) {
529              bitpos += region->pDimensionDefinitions[j].bits;          bitpos += region->pDimensionDefinitions[j].bits;
530          }      }
531    
532        const int stereobitpos =
533            (modifybothchannels) ? baseBits(gig::dimension_samplechannel, region) : -1;
534    
535        // the velocity dimension must be handled differently than all other
536        // dimension types, because
537        // 1. it is currently the only dimension type which allows different zone
538        //    sizes for different cases
539        // 2. for v2 format VelocityUpperLimit has to be set, DimensionUpperLimits for v3
540        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
541          int mask =          int mask =
542              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
543          int c = dimregno & mask; // mask away this dimension          int c = maindimregno & mask; // mask away this dimension
544    
545          if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {          if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
546              // the velocity dimension didn't previously have              // the velocity dimension didn't previously have
# Line 464  void DimRegionChooser::update_after_resi Line 563  void DimRegionChooser::update_after_resi
563              }              }
564          }          }
565    
566          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];          int index = c + (resize.zone << bitpos);
567            gig::DimensionRegion* d = region->pDimensionRegions[index];
568          // update both v2 and v3 values          // update both v2 and v3 values
569          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;          d->DimensionUpperLimits[resize.dimension] = upperLimit;
570          d->VelocityUpperLimit = resize.pos - 1;          d->VelocityUpperLimit = upperLimit;
571            if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
572                gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
573                d->DimensionUpperLimits[resize.dimension] = upperLimit;
574                d->VelocityUpperLimit = upperLimit;
575            }
576    
577            if (modifyalldimregs) {
578                gig::Region* rgn = NULL;
579                for (int key = 0; key < 128; ++key) {
580                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
581                    rgn = instr->GetRegion(key);
582                    if (!modifyallregions && rgn != region) continue; // hack to reduce overall code amount a bit
583                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
584                    if (!dimdef) continue;
585                    if (dimdef->zones != resize.dimensionDef.zones) continue;
586                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
587                    assert(iDim >= 0 && iDim < rgn->Dimensions);
588    
589                    // the dimension layout might be completely different in this
590                    // region, so we have to recalculate bitpos etc for this region
591                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
592                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
593                    const int selection = resize.zone << bitpos;
594    
595                    // primitive and inefficient loop implementation, however due to
596                    // this circumstance the loop code is much simpler, and its lack
597                    // of runtime efficiency should not be notable in practice
598                    for (int idr = 0; idr < 256; ++idr) {
599                        const int index = (idr & stencil) | selection;
600                        assert(index >= 0 && index < 256);
601                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
602                        if (!dr) continue;
603                        dr->DimensionUpperLimits[iDim] = upperLimit;
604                        d->VelocityUpperLimit = upperLimit;
605                    }
606                }
607            } else if (modifyallregions) { // implies modifyalldimregs is false ...
608                // resolve the precise case we need to modify for all other regions
609                DimensionCase dimCase = dimensionCaseOf(d);
610                // apply the velocity upper limit change to that resolved dim case
611                // of all regions ...
612                gig::Region* rgn = NULL;
613                for (int key = 0; key < 128; ++key) {
614                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
615                    rgn = instr->GetRegion(key);
616                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
617                    if (!dimdef) continue;
618                    if (dimdef->zones != resize.dimensionDef.zones) continue;
619                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
620                    assert(iDim >= 0 && iDim < rgn->Dimensions);
621    
622                    std::vector<gig::DimensionRegion*> dimrgns = dimensionRegionsMatching(dimCase, rgn);
623                    for (int i = 0; i < dimrgns.size(); ++i) {
624                        gig::DimensionRegion* dr = dimrgns[i];
625                        dr->DimensionUpperLimits[iDim] = upperLimit;
626                        dr->VelocityUpperLimit = upperLimit;
627                    }
628                }
629            }
630      } else {      } else {
631          for (int i = 0 ; i < region->DimensionRegions ; ) {          for (int i = 0 ; i < region->DimensionRegions ; ) {
   
632              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
633                  // the dimension didn't previously have custom                  // the dimension didn't previously have custom
634                  // limits, so we have to set default limits for                  // limits, so we have to set default limits for
635                  // all the dimension regions                  // all the dimension regions
                 int bitpos = 0;  
                 for (int j = 0 ; j < resize.dimension ; j++) {  
                     bitpos += region->pDimensionDefinitions[j].bits;  
                 }  
636                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
637    
638                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
# Line 487  void DimRegionChooser::update_after_resi Line 640  void DimRegionChooser::update_after_resi
640                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
641                  }                  }
642              }              }
643              gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];              int index = i + (resize.zone << bitpos);
644              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;              gig::DimensionRegion* d = region->pDimensionRegions[index];
645                d->DimensionUpperLimits[resize.dimension] = upperLimit;
646    #if 0       // the following is currently not necessary, because ATM the gig format uses for all dimension types except of the veleocity dimension the same zone sizes for all cases
647                if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
648                    gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
649                    d->DimensionUpperLimits[resize.dimension] = upperLimit;
650                }
651    #endif
652              int bitpos = 0;              int bitpos = 0;
653              int j;              int j;
654              for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
# Line 503  void DimRegionChooser::update_after_resi Line 662  void DimRegionChooser::update_after_resi
662              if (j == region->Dimensions) break;              if (j == region->Dimensions) break;
663              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
664          }          }
665    
666            if (modifyallregions) { // TODO: this code block could be merged with the similar (and more generalized) code block of the velocity dimension above
667                gig::Region* rgn = NULL;
668                for (int key = 0; key < 128; ++key) {
669                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
670                    rgn = instr->GetRegion(key);
671                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
672                    if (!dimdef) continue;
673                    if (dimdef->zones != resize.dimensionDef.zones) continue;
674                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
675                    assert(iDim >= 0 && iDim < rgn->Dimensions);
676    
677                    // the dimension layout might be completely different in this
678                    // region, so we have to recalculate bitpos etc for this region
679                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
680                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
681                    const int selection = resize.zone << bitpos;
682    
683                    // this loop implementation is less efficient than the above's
684                    // loop implementation (which skips unnecessary dimension regions)
685                    // however this code is much simpler, and its lack of runtime
686                    // efficiency should not be notable in practice
687                    for (int idr = 0; idr < 256; ++idr) {
688                        const int index = (idr & stencil) | selection;
689                        assert(index >= 0 && index < 256);
690                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
691                        if (!dr) continue;
692                        dr->DimensionUpperLimits[iDim] = upperLimit;
693                    }
694                }
695            }
696      }      }
697  }  }
698    
# Line 568  bool DimRegionChooser::on_button_press_e Line 758  bool DimRegionChooser::on_button_press_e
758              }              }
759    
760              int i = dim;              int i = dim;
761              if (dimregno < 0) dimregno = 0;              if (maindimregno < 0) maindimregno = 0;
762              int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);              int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
763              int c = dimregno & mask; // mask away this dimension              int c = this->maindimregno & mask; // mask away this dimension
764    
765              bool customsplits =              bool customsplits =
766                  ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&                  ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
# Line 600  bool DimRegionChooser::on_button_press_e Line 790  bool DimRegionChooser::on_button_press_e
790                     region->pDimensionDefinitions[dim].split_type,                     region->pDimensionDefinitions[dim].split_type,
791                     region->pDimensionDefinitions[dim].zones,                     region->pDimensionDefinitions[dim].zones,
792                     region->pDimensionDefinitions[dim].zone_size);                     region->pDimensionDefinitions[dim].zone_size);
793              dimvalue[region->pDimensionDefinitions[dim].dimension] = z;              this->maindimcase[region->pDimensionDefinitions[dim].dimension] = z;
794                this->maindimregno = c | (z << bitpos);
795              dimregno = c | (z << bitpos);              this->maindimtype = region->pDimensionDefinitions[dim].dimension;
796    
797              this->dimtype = dim;              if (multiSelectKeyDown) {
798              this->dimzone = z;                  if (dimzones[this->maindimtype].count(z)) {
799                        if (dimzones[this->maindimtype].size() > 1) {
800                            dimzones[this->maindimtype].erase(z);
801                        }
802                    } else {
803                        dimzones[this->maindimtype].insert(z);
804                    }
805                } else {
806                    this->dimzones.clear();
807                    for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
808                         it != this->maindimcase.end(); ++it)
809                    {
810                        this->dimzones[it->first].insert(it->second);
811                    }
812                }
813    
814              focus_line = dim;              focus_line = dim;
815              if (has_focus()) queue_draw();              if (has_focus()) queue_draw();
816              else grab_focus();              else grab_focus();
             dimreg = region->pDimensionRegions[dimregno];  
817              dimregion_selected();              dimregion_selected();
818    
819              if (event->button == 3) {              if (event->button == 3) {
820                  printf("dimregion right click\n");                  printf("dimregion right click\n");
821                  popup_menu_inside_dimregion->popup(event->button, event->time);                  popup_menu_inside_dimregion->popup(event->button, event->time);
822              }              }
823    
824                queue_draw();
825          }          }
826      }      }
827      return true;      return true;
# Line 654  bool DimRegionChooser::on_motion_notify_ Line 859  bool DimRegionChooser::on_motion_notify_
859    
860              resize.pos = k;              resize.pos = k;
861              update_after_resize();              update_after_resize();
862              get_window()->invalidate_rect(rect, false);              get_window()->invalidate_rect(rect, false); // not sufficient ...
863                queue_draw(); // ... so do a complete redraw instead.
864          }          }
865      } else {      } else {
866          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
# Line 690  bool DimRegionChooser::is_in_resize_zone Line 896  bool DimRegionChooser::is_in_resize_zone
896          int nbZones = region->pDimensionDefinitions[dim].zones;          int nbZones = region->pDimensionDefinitions[dim].zones;
897    
898          int c = 0;          int c = 0;
899          if (dimregno >= 0) {          if (maindimregno >= 0) {
900              int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);              int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
901              c = dimregno & mask; // mask away this dimension              c = maindimregno & mask; // mask away this dimension
902          }          }
903          const bool customsplits =          const bool customsplits =
904              ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&              ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&
# Line 715  bool DimRegionChooser::is_in_resize_zone Line 921  bool DimRegionChooser::is_in_resize_zone
921                  if (x <= limitx - 2) break;                  if (x <= limitx - 2) break;
922                  if (x <= limitx + 2) {                  if (x <= limitx + 2) {
923                      resize.dimension = dim;                      resize.dimension = dim;
924                      resize.offset = iZone << bitpos;                      resize.dimensionDef = region->pDimensionDefinitions[dim];
925                        resize.zone = iZone;
926                      resize.pos = limit;                      resize.pos = limit;
927                      resize.min = prev_limit;                      resize.min = prev_limit;
928    
929                      int dr = (dimregno >> bitpos) &                      int dr = (maindimregno >> bitpos) &
930                          ((1 << region->pDimensionDefinitions[dim].bits) - 1);                          ((1 << region->pDimensionDefinitions[dim].bits) - 1);
931                      resize.selected = dr == iZone ? resize.left :                      resize.selected = dr == iZone ? resize.left :
932                          dr == iZone + 1 ? resize.right : resize.none;                          dr == iZone + 1 ? resize.right : resize.none;
# Line 756  sigc::signal<void>& DimRegionChooser::si Line 963  sigc::signal<void>& DimRegionChooser::si
963    
964  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
965  {  {
966      // TODO: kolla att region finns osv, dvs att det går att sätta      // TODO: check that region exists etc, that is, that it's possible
967      // fokus.      // to set focus
968      if (direction == Gtk::DIR_TAB_FORWARD ||      if (direction == Gtk::DIR_TAB_FORWARD ||
969          direction == Gtk::DIR_DOWN) {          direction == Gtk::DIR_DOWN) {
970          if (!has_focus()) {          if (!has_focus()) {
# Line 789  bool DimRegionChooser::on_focus(Gtk::Dir Line 996  bool DimRegionChooser::on_focus(Gtk::Dir
996              }              }
997          }          }
998      } else if (!has_focus()) {      } else if (!has_focus()) {
999          // TODO: kolla att focus_line finns!          // TODO: check that focus_line exists
1000          grab_focus();          grab_focus();
1001          return true;          return true;
1002      } else {      } else {
1003          // TODO: öka eller minska värde!          // TODO: increase or decrease value
1004      }      }
1005        return false;
1006  }  }
1007    
1008  void DimRegionChooser::split_dimension_zone() {  void DimRegionChooser::split_dimension_zone() {    
1009      printf("split_dimension_zone() type=%d, zone=%d\n", dimtype, dimzone);      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1010      try {      try {
1011          region->SplitDimensionZone(          region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
             region->pDimensionDefinitions[dimtype].dimension,  
             dimzone  
         );  
1012      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1013          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1014          msg.run();          msg.run();
# Line 816  void DimRegionChooser::split_dimension_z Line 1021  void DimRegionChooser::split_dimension_z
1021  }  }
1022    
1023  void DimRegionChooser::delete_dimension_zone() {  void DimRegionChooser::delete_dimension_zone() {
1024      printf("delete_dimension_zone() type=%d, zone=%d\n", dimtype, dimzone);      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1025      try {      try {
1026          region->DeleteDimensionZone(          region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
             region->pDimensionDefinitions[dimtype].dimension,  
             dimzone  
         );  
1027      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1028          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1029          msg.run();          msg.run();
# Line 832  void DimRegionChooser::delete_dimension_ Line 1034  void DimRegionChooser::delete_dimension_
1034      }      }
1035      refresh_all();      refresh_all();
1036  }  }
1037    
1038    bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1039        //printf("key down\n");
1040        if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1041            multiSelectKeyDown = true;
1042        return false;
1043    }
1044    
1045    bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1046        //printf("key up\n");
1047        if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1048            multiSelectKeyDown = false;
1049        return false;
1050    }
1051    
1052    void DimRegionChooser::resetSelectedZones() {
1053        this->dimzones.clear();
1054        if (!region) {
1055            queue_draw(); // redraw required parts
1056            return;
1057        }
1058        if (maindimregno < 0 || maindimregno >= region->DimensionRegions) {
1059            queue_draw(); // redraw required parts
1060            return;
1061        }
1062        if (!region->pDimensionRegions[maindimregno]) {
1063            queue_draw(); // redraw required parts
1064            return;
1065        }
1066        gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1067    
1068        bool isValidZone;
1069        this->maindimcase = caseOfDimRegion(dimrgn, &isValidZone);
1070        if (!isValidZone) {
1071            queue_draw(); // redraw required parts
1072            return;
1073        }
1074    
1075        for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1076             it != this->maindimcase.end(); ++it)
1077        {
1078            this->dimzones[it->first].insert(it->second);
1079        }
1080    
1081        // redraw required parts
1082        queue_draw();
1083    }
1084    
1085    bool DimRegionChooser::select_dimregion(gig::DimensionRegion* dimrgn) {
1086        if (!region) return false; //.selection failed
1087    
1088        for (int dr = 0; dr < region->DimensionRegions && region->pDimensionRegions[dr]; ++dr) {
1089            if (region->pDimensionRegions[dr] == dimrgn) {
1090                // reset dim region zone selection to the requested specific dim region case
1091                maindimregno = dr;
1092                resetSelectedZones();
1093    
1094                // emit signal that dimregion selection has changed, for external entities
1095                dimregion_selected();
1096    
1097                return true; // selection success
1098            }
1099        }
1100    
1101        return false; //.selection failed
1102    }
1103    
1104    gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {
1105        if (!region) return NULL;
1106        return region->pDimensionRegions[maindimregno];
1107    }

Legend:
Removed from v.2556  
changed lines
  Added in v.3089

  ViewVC Help
Powered by ViewVC