/[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 3123 by schoenebeck, Tue Apr 25 20:45:54 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() :  //TODO: this function and dimensionCaseOf() from global.h are duplicates, eliminate either one of them!
33    static DimensionCase caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
34        DimensionCase dimCase;
35        if (!dr) {
36            *isValidZone = false;
37            return dimCase;
38        }
39    
40        gig::Region* rgn = (gig::Region*) dr->GetParent();
41    
42        // find the dimension region index of the passed dimension region
43        int drIndex;
44        for (drIndex = 0; drIndex < 256; ++drIndex)
45            if (rgn->pDimensionRegions[drIndex] == dr)
46                break;
47    
48        // not found in region, something's horribly wrong
49        if (drIndex == 256) {
50            fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");
51            *isValidZone = false;
52            return DimensionCase();
53        }
54    
55        for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {
56            const int bits = rgn->pDimensionDefinitions[d].bits;
57            dimCase[rgn->pDimensionDefinitions[d].dimension] =
58                (drIndex >> baseBits) & ((1 << bits) - 1);
59            baseBits += bits;
60            // there are also DimensionRegion objects of unused zones, skip them
61            if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {
62                *isValidZone = false;
63                return DimensionCase();
64            }
65        }
66    
67        *isValidZone = true;
68        return dimCase;
69    }
70    
71    DimRegionChooser::DimRegionChooser(Gtk::Window& window) :
72      red("#8070ff"),      red("#8070ff"),
73      black("black"),      black("black"),
74      white("white")      white("white")
75  {  {
76      instrument = 0;      instrument = 0;
77      region = 0;      region = 0;
78      dimregno = -1;      maindimregno = -1;
79        maindimtype = gig::dimension_none; // initialize with invalid dimension type
80      focus_line = 0;      focus_line = 0;
81      resize.active = false;      resize.active = false;
82      cursor_is_resize = false;      cursor_is_resize = false;
83      h = 20;      h = 24;
84        multiSelectKeyDown = false;
85        modifybothchannels = modifyalldimregs = modifybothchannels = false;
86      set_can_focus();      set_can_focus();
87    
88        const Glib::ustring txtUseCheckBoxAllRegions =
89            _("Use checkbox 'all regions' to control whether this should apply to all regions.");
90    
91      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
92        actionSplitDimZone = Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone"), txtUseCheckBoxAllRegions);
93        actionSplitDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
94      actionGroup->add(      actionGroup->add(
95          Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone")),          actionSplitDimZone,
96          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
97      );      );
98        actionDeleteDimZone = Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone"), txtUseCheckBoxAllRegions);
99        actionDeleteDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
100      actionGroup->add(      actionGroup->add(
101          Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone")),          actionDeleteDimZone,
102          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
103      );      );
104    
# 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        actionDeleteDimZone->set_label(b ? _("Delete Dimension Zone [ALL REGIONS]") : _("Delete Dimension Zone"));
158        actionSplitDimZone->set_label(b ? _("Split Dimensions Zone [ALL REGIONS]") : _("Split Dimensions Zone"));
159    }
160    
161  #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
162  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
163  {  {
# Line 94  bool DimRegionChooser::on_expose_event(G Line 168  bool DimRegionChooser::on_expose_event(G
168    
169      const Cairo::RefPtr<Cairo::Context>& cr =      const Cairo::RefPtr<Cairo::Context>& cr =
170          get_window()->create_cairo_context();          get_window()->create_cairo_context();
 #if 0  
 }  
 #endif  
171  #else  #else
172  bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)  bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
173  {  {
# Line 212  bool DimRegionChooser::on_draw(const Cai Line 283  bool DimRegionChooser::on_draw(const Cai
283      for (int i = 0 ; i < region->Dimensions ; i++) {      for (int i = 0 ; i < region->Dimensions ; i++) {
284          int nbZones = region->pDimensionDefinitions[i].zones;          int nbZones = region->pDimensionDefinitions[i].zones;
285          if (nbZones) {          if (nbZones) {
286                const gig::dimension_t dimension = region->pDimensionDefinitions[i].dimension;
287    
288              if (y >= clipy2) break;              if (y >= clipy2) break;
289              if (y + h > clipy1) {              if (y + h > clipy1) {
290                  // draw focus rectangle around dimension's label and zones                  // draw focus rectangle around dimension's label and zones
291                  if (has_focus() && focus_line == i) {                  if (has_focus() && focus_line == i) {
292  #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
293                      Gdk::Rectangle farea(0, y, 150, 20);                      Gdk::Rectangle farea(0, y, 150, h);
294                      get_style()->paint_focus(get_window(), get_state(), farea,                      get_style()->paint_focus(get_window(), get_state(), farea,
295                                               *this, "",                                               *this, "",
296                                               0, y, label_width, 20);                                               0, y, label_width, h);
297  #else  #else
298                      get_style_context()->render_focus(cr,                      get_style_context()->render_focus(cr,
299                                                        0, y, label_width, 20);                                                        0, y, label_width, h);
300  #endif  #endif
301                  }                  }
302    
# Line 242  bool DimRegionChooser::on_draw(const Cai Line 315  bool DimRegionChooser::on_draw(const Cai
315                  cr->fill();                  cr->fill();
316    
317                  int c = 0;                  int c = 0;
318                  if (dimregno >= 0) {                  if (maindimregno >= 0) {
319                      int mask =                      int mask =
320                          ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<                          ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<
321                            bitpos);                            bitpos);
322                      c = dimregno & mask; // mask away this dimension                      c = maindimregno & mask; // mask away this dimension
323                  }                  }
324                  bool customsplits =                  bool customsplits =
325                      ((region->pDimensionDefinitions[i].split_type ==                      ((region->pDimensionDefinitions[i].split_type ==
# Line 256  bool DimRegionChooser::on_draw(const Cai Line 329  bool DimRegionChooser::on_draw(const Cai
329                        gig::dimension_velocity &&                        gig::dimension_velocity &&
330                        region->pDimensionRegions[c]->VelocityUpperLimit));                        region->pDimensionRegions[c]->VelocityUpperLimit));
331    
332                  // draw dimension's zone borders                  // draw dimension zones
333                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
334                  if (customsplits) {                  if (customsplits) {
335                      cr->move_to(label_width + 0.5, y + 1);                      cr->move_to(label_width + 0.5, y + 1);
336                      cr->line_to(label_width + 0.5, y + h - 1);                      cr->line_to(label_width + 0.5, y + h - 1);
337                        int prevX = label_width;
338                        int prevUpperLimit = -1;
339    
340                      for (int j = 0 ; j < nbZones ; j++) {                      for (int j = 0 ; j < nbZones ; j++) {
341                            // draw dimension zone's borders for custom splits
342                          gig::DimensionRegion* d =                          gig::DimensionRegion* d =
343                              region->pDimensionRegions[c + (j << bitpos)];                              region->pDimensionRegions[c + (j << bitpos)];
344                          int upperLimit = d->DimensionUpperLimits[i];                          int upperLimit = d->DimensionUpperLimits[i];
# Line 272  bool DimRegionChooser::on_draw(const Cai Line 348  bool DimRegionChooser::on_draw(const Cai
348                              label_width;                              label_width;
349                          if (x >= clipx2) break;                          if (x >= clipx2) break;
350                          if (x < clipx1) continue;                          if (x < clipx1) continue;
351                            Gdk::Cairo::set_source_rgba(cr, black);
352                          cr->move_to(x + 0.5, y + 1);                          cr->move_to(x + 0.5, y + 1);
353                          cr->line_to(x + 0.5, y + h - 1);                          cr->line_to(x + 0.5, y + h - 1);
354                            cr->stroke();
355    
356                            // draw fill for zone
357                            bool isSelectedZone = this->dimzones[dimension].count(j);
358                            Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);
359                            cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
360                            cr->fill();
361    
362                            // draw text showing the beginning of the dimension zone
363                            // as numeric value to the user
364                            {
365                                Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
366                                layout->set_text(Glib::Ascii::dtostr(prevUpperLimit+1));
367                                Gdk::Cairo::set_source_rgba(cr, black);
368                                // get the text dimensions
369                                int text_width, text_height;
370                                layout->get_pixel_size(text_width, text_height);
371                                // move text to the left end of the dimension zone
372                                cr->move_to(prevX + 3, y + (h - text_height) / 2);
373    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
374                                pango_cairo_show_layout(cr->cobj(), layout->gobj());
375    #else
376                                layout->show_in_cairo_context(cr);
377    #endif
378                            }
379                            // draw text showing the end of the dimension zone
380                            // as numeric value to the user
381                            {
382                                Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
383                                layout->set_text(Glib::Ascii::dtostr(upperLimit));
384                                Gdk::Cairo::set_source_rgba(cr, black);
385                                // get the text dimensions
386                                int text_width, text_height;
387                                layout->get_pixel_size(text_width, text_height);
388                                // move text to the left end of the dimension zone
389                                cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
390    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
391                                pango_cairo_show_layout(cr->cobj(), layout->gobj());
392    #else
393                                layout->show_in_cairo_context(cr);
394    #endif
395                            }
396    
397                            prevX = x;
398                            prevUpperLimit = upperLimit;
399                      }                      }
400                  } else {                  } else {
401                        int prevX = 0;
402                      for (int j = 0 ; j <= nbZones ; j++) {                      for (int j = 0 ; j <= nbZones ; j++) {
403                            // draw dimension zone's borders for normal splits
404                          int x = int((w - label_width - 1) * j /                          int x = int((w - label_width - 1) * j /
405                                      double(nbZones) + 0.5) + label_width;                                      double(nbZones) + 0.5) + label_width;
406                          if (x >= clipx2) break;                          if (x >= clipx2) break;
407                          if (x < clipx1) continue;                          if (x < clipx1) continue;
408                            Gdk::Cairo::set_source_rgba(cr, black);
409                          cr->move_to(x + 0.5, y + 1);                          cr->move_to(x + 0.5, y + 1);
410                          cr->line_to(x + 0.5, y + h - 1);                          cr->line_to(x + 0.5, y + h - 1);
411                      }                          cr->stroke();
                 }  
                 cr->stroke();  
412    
413                  // draw fill for currently selected zone                          if (j != 0) {
414                  if (dimregno >= 0) {                              // draw fill for zone
415                      Gdk::Cairo::set_source_rgba(cr, red);                              bool isSelectedZone = this->dimzones[dimension].count(j-1);
416                      int dr = (dimregno >> bitpos) &                              Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);
417                          ((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);  
418                              cr->fill();                              cr->fill();
                         }  
                     }  
419    
420                      // draw text showing the beginning of the dimension zone                              // draw text showing the beginning of the dimension zone
421                      // as numeric value to the user                              // as numeric value to the user
422                      if (x1 >= 0) {                              {
423                          Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
424                          int v = roundf(float(x1 - label_width) / float(w - label_width) * 127.f);                                  layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));
425                          if (dr > 0) v++;                                  Gdk::Cairo::set_source_rgba(cr, black);
426                          layout->set_text(Glib::Ascii::dtostr(v));                                  // get the text dimensions
427                          Gdk::Cairo::set_source_rgba(cr, black);                                  int text_width, text_height;
428                          Pango::Rectangle rect = layout->get_logical_extents();                                  layout->get_pixel_size(text_width, text_height);
429                                                            // move text to the left end of the dimension zone
430                          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);  
431  #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
432                          pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
433  #else  #else
434                          layout->show_in_cairo_context(cr);                                  layout->show_in_cairo_context(cr);
435  #endif  #endif
436                      }                              }
437                      // draw text showing the end of the dimension zone                              // draw text showing the end of the dimension zone
438                      // as numeric value to the user                              // as numeric value to the user
439                      if (x2 >= 0) {                              {
440                          Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
441                          const int v = roundf(float(x2 - label_width) / float(w - label_width) * 127.f);                                  layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));
442                          layout->set_text(Glib::Ascii::dtostr(v));                                  Gdk::Cairo::set_source_rgba(cr, black);
443                          Gdk::Cairo::set_source_rgba(cr, black);                                  // get the text dimensions
444                          Pango::Rectangle rect = layout->get_logical_extents();                                  int text_width, text_height;
445                                                            layout->get_pixel_size(text_width, text_height);
446                          int text_width, text_height;                                  // move text to the left end of the dimension zone
447                          // 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);  
448  #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
449                          pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
450  #else  #else
451                          layout->show_in_cairo_context(cr);                                  layout->show_in_cairo_context(cr);
452  #endif  #endif
453                      }                              }
454                            }
455                            prevX = x;
456                        }      
457                  }                  }
458              }              }
   
459              y += h;              y += h;
460          }          }
461          bitpos += region->pDimensionDefinitions[i].bits;          bitpos += region->pDimensionDefinitions[i].bits;
# Line 381  bool DimRegionChooser::on_draw(const Cai Line 467  bool DimRegionChooser::on_draw(const Cai
467  void DimRegionChooser::set_region(gig::Region* region)  void DimRegionChooser::set_region(gig::Region* region)
468  {  {
469      this->region = region;      this->region = region;
470      dimregno = 0;      maindimregno = 0;
471      nbDimensions = 0;      nbDimensions = 0;
472      if (region) {      if (region) {
473          int bitcount = 0;          int bitcount = 0;
# Line 389  void DimRegionChooser::set_region(gig::R Line 475  void DimRegionChooser::set_region(gig::R
475              if (region->pDimensionDefinitions[dim].bits == 0) continue;              if (region->pDimensionDefinitions[dim].bits == 0) continue;
476              nbDimensions++;              nbDimensions++;
477    
478              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              int z = std::min(maindimcase[region->pDimensionDefinitions[dim].dimension],
479                               region->pDimensionDefinitions[dim].zones - 1);                               region->pDimensionDefinitions[dim].zones - 1);
480              dimregno |= (z << bitcount);              maindimregno |= (z << bitcount);
481              bitcount += region->pDimensionDefinitions[dim].bits;              bitcount += region->pDimensionDefinitions[dim].bits;
482          }          }
         dimreg = region->pDimensionRegions[dimregno];  
     } else {  
         dimreg = 0;  
483      }      }
484      dimregion_selected();      dimregion_selected();
485      set_size_request(800, region ? nbDimensions * 20 : 0);      set_size_request(800, region ? nbDimensions * h : 0);
486    
487      labels_changed = true;      labels_changed = true;
488      queue_resize();      queue_resize();
489        queue_draw();
490  }  }
491    
492  void DimRegionChooser::refresh_all() {  void DimRegionChooser::refresh_all() {
# Line 412  void DimRegionChooser::refresh_all() { Line 496  void DimRegionChooser::refresh_all() {
496  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
497                                        std::set<gig::DimensionRegion*>& dimregs) const                                        std::set<gig::DimensionRegion*>& dimregs) const
498  {  {
499      int dimregno = 0;      for (int iDimRgn = 0; iDimRgn < 256; ++iDimRgn) {
500      int bitcount = 0;          gig::DimensionRegion* dimRgn = region->pDimensionRegions[iDimRgn];
501      int stereo_bit = 0;          if (!dimRgn) continue;
502      for (int dim = 0 ; dim < region->Dimensions ; dim++) {          bool isValidZone;
503          if (region->pDimensionDefinitions[dim].bits == 0) continue;          std::map<gig::dimension_t,int> dimCase = caseOfDimRegion(dimRgn, &isValidZone);
504          if (stereo &&          if (!isValidZone) continue;
505              region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {          for (std::map<gig::dimension_t,int>::const_iterator it = dimCase.begin();
506              stereo_bit = (1 << bitcount);               it != dimCase.end(); ++it)
507          } else {          {
508              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              if (stereo && it->first == gig::dimension_samplechannel) continue; // is selected
509                               region->pDimensionDefinitions[dim].zones - 1);  
510              dimregno |= (z << bitcount);              std::map<gig::dimension_t, std::set<int> >::const_iterator itSelectedDimension =
511                    this->dimzones.find(it->first);
512                if (itSelectedDimension != this->dimzones.end() &&
513                    itSelectedDimension->second.count(it->second)) continue; // is selected
514    
515                goto notSelected;
516          }          }
517          bitcount += region->pDimensionDefinitions[dim].bits;  
518            dimregs.insert(dimRgn);
519    
520            notSelected:
521            ;
522      }      }
     dimregs.insert(region->pDimensionRegions[dimregno]);  
     if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);  
523  }  }
524    
525  void DimRegionChooser::update_after_resize()  void DimRegionChooser::update_after_resize()
526  {  {
527      if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {      const uint8_t upperLimit = resize.pos - 1;
528        gig::Instrument* instr = (gig::Instrument*)region->GetParent();
529    
530          int bitpos = 0;      int bitpos = 0;
531          for (int j = 0 ; j < resize.dimension ; j++) {      for (int j = 0 ; j < resize.dimension ; j++) {
532              bitpos += region->pDimensionDefinitions[j].bits;          bitpos += region->pDimensionDefinitions[j].bits;
533          }      }
534    
535        const int stereobitpos =
536            (modifybothchannels) ? baseBits(gig::dimension_samplechannel, region) : -1;
537    
538        // the velocity dimension must be handled differently than all other
539        // dimension types, because
540        // 1. it is currently the only dimension type which allows different zone
541        //    sizes for different cases
542        // 2. for v2 format VelocityUpperLimit has to be set, DimensionUpperLimits for v3
543        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
544          int mask =          int mask =
545              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
546          int c = dimregno & mask; // mask away this dimension          int c = maindimregno & mask; // mask away this dimension
547    
548          if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {          if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
549              // the velocity dimension didn't previously have              // the velocity dimension didn't previously have
# Line 464  void DimRegionChooser::update_after_resi Line 566  void DimRegionChooser::update_after_resi
566              }              }
567          }          }
568    
569          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];          int index = c + (resize.zone << bitpos);
570            gig::DimensionRegion* d = region->pDimensionRegions[index];
571          // update both v2 and v3 values          // update both v2 and v3 values
572          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;          d->DimensionUpperLimits[resize.dimension] = upperLimit;
573          d->VelocityUpperLimit = resize.pos - 1;          d->VelocityUpperLimit = upperLimit;
574            if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
575                gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
576                d->DimensionUpperLimits[resize.dimension] = upperLimit;
577                d->VelocityUpperLimit = upperLimit;
578            }
579    
580            if (modifyalldimregs) {
581                gig::Region* rgn = NULL;
582                for (int key = 0; key < 128; ++key) {
583                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
584                    rgn = instr->GetRegion(key);
585                    if (!modifyallregions && rgn != region) continue; // hack to reduce overall code amount a bit
586                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
587                    if (!dimdef) continue;
588                    if (dimdef->zones != resize.dimensionDef.zones) continue;
589                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
590                    assert(iDim >= 0 && iDim < rgn->Dimensions);
591    
592                    // the dimension layout might be completely different in this
593                    // region, so we have to recalculate bitpos etc for this region
594                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
595                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
596                    const int selection = resize.zone << bitpos;
597    
598                    // primitive and inefficient loop implementation, however due to
599                    // this circumstance the loop code is much simpler, and its lack
600                    // of runtime efficiency should not be notable in practice
601                    for (int idr = 0; idr < 256; ++idr) {
602                        const int index = (idr & stencil) | selection;
603                        assert(index >= 0 && index < 256);
604                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
605                        if (!dr) continue;
606                        dr->DimensionUpperLimits[iDim] = upperLimit;
607                        d->VelocityUpperLimit = upperLimit;
608                    }
609                }
610            } else if (modifyallregions) { // implies modifyalldimregs is false ...
611                // resolve the precise case we need to modify for all other regions
612                DimensionCase dimCase = dimensionCaseOf(d);
613                // apply the velocity upper limit change to that resolved dim case
614                // of all regions ...
615                gig::Region* rgn = NULL;
616                for (int key = 0; key < 128; ++key) {
617                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
618                    rgn = instr->GetRegion(key);
619                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
620                    if (!dimdef) continue;
621                    if (dimdef->zones != resize.dimensionDef.zones) continue;
622                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
623                    assert(iDim >= 0 && iDim < rgn->Dimensions);
624    
625                    std::vector<gig::DimensionRegion*> dimrgns = dimensionRegionsMatching(dimCase, rgn);
626                    for (int i = 0; i < dimrgns.size(); ++i) {
627                        gig::DimensionRegion* dr = dimrgns[i];
628                        dr->DimensionUpperLimits[iDim] = upperLimit;
629                        dr->VelocityUpperLimit = upperLimit;
630                    }
631                }
632            }
633      } else {      } else {
634          for (int i = 0 ; i < region->DimensionRegions ; ) {          for (int i = 0 ; i < region->DimensionRegions ; ) {
   
635              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
636                  // the dimension didn't previously have custom                  // the dimension didn't previously have custom
637                  // limits, so we have to set default limits for                  // limits, so we have to set default limits for
638                  // all the dimension regions                  // all the dimension regions
                 int bitpos = 0;  
                 for (int j = 0 ; j < resize.dimension ; j++) {  
                     bitpos += region->pDimensionDefinitions[j].bits;  
                 }  
639                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
640    
641                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
# Line 487  void DimRegionChooser::update_after_resi Line 643  void DimRegionChooser::update_after_resi
643                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
644                  }                  }
645              }              }
646              gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];              int index = i + (resize.zone << bitpos);
647              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;              gig::DimensionRegion* d = region->pDimensionRegions[index];
648                d->DimensionUpperLimits[resize.dimension] = upperLimit;
649    #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
650                if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
651                    gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
652                    d->DimensionUpperLimits[resize.dimension] = upperLimit;
653                }
654    #endif
655              int bitpos = 0;              int bitpos = 0;
656              int j;              int j;
657              for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
# Line 503  void DimRegionChooser::update_after_resi Line 665  void DimRegionChooser::update_after_resi
665              if (j == region->Dimensions) break;              if (j == region->Dimensions) break;
666              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
667          }          }
668    
669            if (modifyallregions) { // TODO: this code block could be merged with the similar (and more generalized) code block of the velocity dimension above
670                gig::Region* rgn = NULL;
671                for (int key = 0; key < 128; ++key) {
672                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
673                    rgn = instr->GetRegion(key);
674                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
675                    if (!dimdef) continue;
676                    if (dimdef->zones != resize.dimensionDef.zones) continue;
677                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
678                    assert(iDim >= 0 && iDim < rgn->Dimensions);
679    
680                    // the dimension layout might be completely different in this
681                    // region, so we have to recalculate bitpos etc for this region
682                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
683                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
684                    const int selection = resize.zone << bitpos;
685    
686                    // this loop implementation is less efficient than the above's
687                    // loop implementation (which skips unnecessary dimension regions)
688                    // however this code is much simpler, and its lack of runtime
689                    // efficiency should not be notable in practice
690                    for (int idr = 0; idr < 256; ++idr) {
691                        const int index = (idr & stencil) | selection;
692                        assert(index >= 0 && index < 256);
693                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
694                        if (!dr) continue;
695                        dr->DimensionUpperLimits[iDim] = upperLimit;
696                    }
697                }
698            }
699      }      }
700  }  }
701    
# Line 568  bool DimRegionChooser::on_button_press_e Line 761  bool DimRegionChooser::on_button_press_e
761              }              }
762    
763              int i = dim;              int i = dim;
764              if (dimregno < 0) dimregno = 0;              if (maindimregno < 0) maindimregno = 0;
765              int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);              int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
766              int c = dimregno & mask; // mask away this dimension              int c = this->maindimregno & mask; // mask away this dimension
767    
768              bool customsplits =              bool customsplits =
769                  ((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 793  bool DimRegionChooser::on_button_press_e
793                     region->pDimensionDefinitions[dim].split_type,                     region->pDimensionDefinitions[dim].split_type,
794                     region->pDimensionDefinitions[dim].zones,                     region->pDimensionDefinitions[dim].zones,
795                     region->pDimensionDefinitions[dim].zone_size);                     region->pDimensionDefinitions[dim].zone_size);
796              dimvalue[region->pDimensionDefinitions[dim].dimension] = z;              this->maindimcase[region->pDimensionDefinitions[dim].dimension] = z;
797                this->maindimregno = c | (z << bitpos);
798              dimregno = c | (z << bitpos);              this->maindimtype = region->pDimensionDefinitions[dim].dimension;
799    
800              this->dimtype = dim;              if (multiSelectKeyDown) {
801              this->dimzone = z;                  if (dimzones[this->maindimtype].count(z)) {
802                        if (dimzones[this->maindimtype].size() > 1) {
803                            dimzones[this->maindimtype].erase(z);
804                        }
805                    } else {
806                        dimzones[this->maindimtype].insert(z);
807                    }
808                } else {
809                    this->dimzones.clear();
810                    for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
811                         it != this->maindimcase.end(); ++it)
812                    {
813                        this->dimzones[it->first].insert(it->second);
814                    }
815                }
816    
817              focus_line = dim;              focus_line = dim;
818              if (has_focus()) queue_draw();              if (has_focus()) queue_draw();
819              else grab_focus();              else grab_focus();
             dimreg = region->pDimensionRegions[dimregno];  
820              dimregion_selected();              dimregion_selected();
821    
822              if (event->button == 3) {              if (event->button == 3) {
823                  printf("dimregion right click\n");                  printf("dimregion right click\n");
824                  popup_menu_inside_dimregion->popup(event->button, event->time);                  popup_menu_inside_dimregion->popup(event->button, event->time);
825              }              }
826    
827                queue_draw();
828          }          }
829      }      }
830      return true;      return true;
# Line 654  bool DimRegionChooser::on_motion_notify_ Line 862  bool DimRegionChooser::on_motion_notify_
862    
863              resize.pos = k;              resize.pos = k;
864              update_after_resize();              update_after_resize();
865              get_window()->invalidate_rect(rect, false);              get_window()->invalidate_rect(rect, false); // not sufficient ...
866                queue_draw(); // ... so do a complete redraw instead.
867          }          }
868      } else {      } else {
869          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
# Line 690  bool DimRegionChooser::is_in_resize_zone Line 899  bool DimRegionChooser::is_in_resize_zone
899          int nbZones = region->pDimensionDefinitions[dim].zones;          int nbZones = region->pDimensionDefinitions[dim].zones;
900    
901          int c = 0;          int c = 0;
902          if (dimregno >= 0) {          if (maindimregno >= 0) {
903              int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);              int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
904              c = dimregno & mask; // mask away this dimension              c = maindimregno & mask; // mask away this dimension
905          }          }
906          const bool customsplits =          const bool customsplits =
907              ((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 924  bool DimRegionChooser::is_in_resize_zone
924                  if (x <= limitx - 2) break;                  if (x <= limitx - 2) break;
925                  if (x <= limitx + 2) {                  if (x <= limitx + 2) {
926                      resize.dimension = dim;                      resize.dimension = dim;
927                      resize.offset = iZone << bitpos;                      resize.dimensionDef = region->pDimensionDefinitions[dim];
928                        resize.zone = iZone;
929                      resize.pos = limit;                      resize.pos = limit;
930                      resize.min = prev_limit;                      resize.min = prev_limit;
931    
932                      int dr = (dimregno >> bitpos) &                      int dr = (maindimregno >> bitpos) &
933                          ((1 << region->pDimensionDefinitions[dim].bits) - 1);                          ((1 << region->pDimensionDefinitions[dim].bits) - 1);
934                      resize.selected = dr == iZone ? resize.left :                      resize.selected = dr == iZone ? resize.left :
935                          dr == iZone + 1 ? resize.right : resize.none;                          dr == iZone + 1 ? resize.right : resize.none;
# Line 756  sigc::signal<void>& DimRegionChooser::si Line 966  sigc::signal<void>& DimRegionChooser::si
966    
967  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
968  {  {
969      // 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
970      // fokus.      // to set focus
971      if (direction == Gtk::DIR_TAB_FORWARD ||      if (direction == Gtk::DIR_TAB_FORWARD ||
972          direction == Gtk::DIR_DOWN) {          direction == Gtk::DIR_DOWN) {
973          if (!has_focus()) {          if (!has_focus()) {
# Line 789  bool DimRegionChooser::on_focus(Gtk::Dir Line 999  bool DimRegionChooser::on_focus(Gtk::Dir
999              }              }
1000          }          }
1001      } else if (!has_focus()) {      } else if (!has_focus()) {
1002          // TODO: kolla att focus_line finns!          // TODO: check that focus_line exists
1003          grab_focus();          grab_focus();
1004          return true;          return true;
1005      } else {      } else {
1006          // TODO: öka eller minska värde!          // TODO: increase or decrease value
1007      }      }
1008        return false;
1009  }  }
1010    
1011  void DimRegionChooser::split_dimension_zone() {  void DimRegionChooser::split_dimension_zone() {    
1012      printf("split_dimension_zone() type=%d, zone=%d\n", dimtype, dimzone);      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1013      try {      try {
1014          region->SplitDimensionZone(          if (!modifyallregions) {
1015              region->pDimensionDefinitions[dimtype].dimension,              region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1016              dimzone          } else {
1017          );              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1018                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1019                assert(pMaindimdef != NULL);
1020                // retain structure by value since the original region will be
1021                // modified in the loop below as well
1022                gig::dimension_def_t maindimdef = *pMaindimdef;
1023                std::vector<gig::Region*> ignoredAll;
1024                std::vector<gig::Region*> ignoredMinor;
1025                std::vector<gig::Region*> ignoredCritical;
1026                gig::Region* rgn = NULL;
1027                for (int key = 0; key < 128; ++key) {
1028                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1029                    rgn = instr->GetRegion(key);
1030    
1031                    // ignore all regions which do not exactly match the dimension
1032                    // layout of the selected region where this operation was emitted
1033                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1034                    if (!dimdef) {
1035                        ignoredAll.push_back(rgn);
1036                        ignoredMinor.push_back(rgn);
1037                        continue;
1038                    }
1039                    if (dimdef->zones != maindimdef.zones) {
1040                        ignoredAll.push_back(rgn);
1041                        ignoredCritical.push_back(rgn);
1042                        continue;
1043                    }
1044    
1045                    rgn->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1046                }
1047                if (!ignoredAll.empty()) {
1048                    Glib::ustring txt;
1049                    if (ignoredCritical.empty())
1050                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1051                    else if (ignoredMinor.empty())
1052                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1053                    else
1054                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1055                        ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1056                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1057                    Gtk::MessageDialog msg(txt, false, type);
1058                    msg.run();
1059                }
1060            }
1061      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1062          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1063          msg.run();          msg.run();
# Line 816  void DimRegionChooser::split_dimension_z Line 1070  void DimRegionChooser::split_dimension_z
1070  }  }
1071    
1072  void DimRegionChooser::delete_dimension_zone() {  void DimRegionChooser::delete_dimension_zone() {
1073      printf("delete_dimension_zone() type=%d, zone=%d\n", dimtype, dimzone);      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1074      try {      try {
1075          region->DeleteDimensionZone(          if (!modifyallregions) {
1076              region->pDimensionDefinitions[dimtype].dimension,              region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1077              dimzone          } else {
1078          );              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1079                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1080                assert(pMaindimdef != NULL);
1081                // retain structure by value since the original region will be
1082                // modified in the loop below as well
1083                gig::dimension_def_t maindimdef = *pMaindimdef;
1084                std::vector<gig::Region*> ignoredAll;
1085                std::vector<gig::Region*> ignoredMinor;
1086                std::vector<gig::Region*> ignoredCritical;
1087                gig::Region* rgn = NULL;
1088                for (int key = 0; key < 128; ++key) {
1089                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1090                    rgn = instr->GetRegion(key);
1091    
1092                    // ignore all regions which do not exactly match the dimension
1093                    // layout of the selected region where this operation was emitted
1094                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1095                    if (!dimdef) {
1096                        ignoredAll.push_back(rgn);
1097                        ignoredMinor.push_back(rgn);
1098                        continue;
1099                    }
1100                    if (dimdef->zones != maindimdef.zones) {
1101                        ignoredAll.push_back(rgn);
1102                        ignoredCritical.push_back(rgn);
1103                        continue;
1104                    }
1105    
1106                    rgn->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1107                }
1108                if (!ignoredAll.empty()) {
1109                    Glib::ustring txt;
1110                    if (ignoredCritical.empty())
1111                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1112                    else if (ignoredMinor.empty())
1113                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1114                    else
1115                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1116                              ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1117                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1118                    Gtk::MessageDialog msg(txt, false, type);
1119                    msg.run();
1120                }
1121            }
1122      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1123          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1124          msg.run();          msg.run();
# Line 832  void DimRegionChooser::delete_dimension_ Line 1129  void DimRegionChooser::delete_dimension_
1129      }      }
1130      refresh_all();      refresh_all();
1131  }  }
1132    
1133    bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1134        //printf("key down 0x%x\n", key->keyval);
1135        if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1136            multiSelectKeyDown = true;
1137        //FIXME: hmm, for some reason GDKMM does not fire arrow key down events, so we are doing those handlers in the key up handler instead for now
1138        /*if (key->keyval == GDK_KEY_Left)
1139            select_prev_dimzone();
1140        if (key->keyval == GDK_KEY_Right)
1141            select_next_dimzone();
1142        if (key->keyval == GDK_KEY_Up)
1143            select_prev_dimension();
1144        if (key->keyval == GDK_KEY_Down)
1145            select_next_dimension();*/
1146        return false;
1147    }
1148    
1149    bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1150        //printf("key up 0x%x\n", key->keyval);
1151        if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1152            multiSelectKeyDown = false;
1153    
1154        if (!has_focus()) return false;
1155    
1156        if (key->keyval == GDK_KEY_Left)
1157            select_prev_dimzone();
1158        if (key->keyval == GDK_KEY_Right)
1159            select_next_dimzone();
1160        if (key->keyval == GDK_KEY_Up)
1161            select_prev_dimension();
1162        if (key->keyval == GDK_KEY_Down)
1163            select_next_dimension();
1164    
1165        return false;
1166    }
1167    
1168    void DimRegionChooser::resetSelectedZones() {
1169        this->dimzones.clear();
1170        if (!region) {
1171            queue_draw(); // redraw required parts
1172            return;
1173        }
1174        if (maindimregno < 0 || maindimregno >= region->DimensionRegions) {
1175            queue_draw(); // redraw required parts
1176            return;
1177        }
1178        if (!region->pDimensionRegions[maindimregno]) {
1179            queue_draw(); // redraw required parts
1180            return;
1181        }
1182        gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1183    
1184        bool isValidZone;
1185        this->maindimcase = dimensionCaseOf(dimrgn);
1186    
1187        for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1188             it != this->maindimcase.end(); ++it)
1189        {
1190            this->dimzones[it->first].insert(it->second);
1191        }
1192    
1193        // redraw required parts
1194        queue_draw();
1195    }
1196    
1197    bool DimRegionChooser::select_dimregion(gig::DimensionRegion* dimrgn) {
1198        if (!region) return false; //.selection failed
1199    
1200        for (int dr = 0; dr < region->DimensionRegions && region->pDimensionRegions[dr]; ++dr) {
1201            if (region->pDimensionRegions[dr] == dimrgn) {
1202                // reset dim region zone selection to the requested specific dim region case
1203                maindimregno = dr;
1204                resetSelectedZones();
1205    
1206                // emit signal that dimregion selection has changed, for external entities
1207                dimregion_selected();
1208    
1209                return true; // selection success
1210            }
1211        }
1212    
1213        return false; //.selection failed
1214    }
1215    
1216    void DimRegionChooser::select_next_dimzone() {
1217        select_dimzone_by_dir(+1);
1218    }
1219    
1220    void DimRegionChooser::select_prev_dimzone() {
1221        select_dimzone_by_dir(-1);
1222    }
1223    
1224    void DimRegionChooser::select_dimzone_by_dir(int dir) {
1225        if (!region) return;
1226        if (!region->Dimensions) return;
1227        if (focus_line < 0) focus_line = 0;
1228        if (focus_line >= region->Dimensions) focus_line = region->Dimensions - 1;
1229    
1230        maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1231        if (maindimtype == gig::dimension_none) {
1232            printf("maindimtype -> none\n");
1233            return;
1234        }
1235    
1236        if (maindimcase.empty()) {
1237            maindimcase = dimensionCaseOf(region->pDimensionRegions[maindimregno]);
1238            if (maindimcase.empty()) {
1239                printf("caseOfDimregion(%d) -> empty\n", maindimregno);
1240                return;
1241            }
1242        }
1243    
1244        int z = (dir > 0) ? maindimcase[maindimtype] + 1 : maindimcase[maindimtype] - 1;
1245        if (z < 0) z = 0;
1246        if (z >= region->pDimensionDefinitions[focus_line].zones)
1247            z = region->pDimensionDefinitions[focus_line].zones - 1;
1248    
1249        maindimcase[maindimtype] = z;
1250    
1251        ::gig::DimensionRegion* dr = dimensionRegionMatching(maindimcase, region);
1252        if (!dr) {
1253            printf("select_dimzone_by_dir(%d) -> !dr\n", dir);
1254            return;
1255        }
1256    
1257        maindimregno = getDimensionRegionIndex(dr);
1258    
1259        // reset selected dimregion zones
1260        dimzones.clear();
1261        for (DimensionCase::const_iterator it = maindimcase.begin();
1262             it != maindimcase.end(); ++it)
1263        {
1264            dimzones[it->first].insert(it->second);
1265        }
1266    
1267        dimregion_selected();
1268    
1269        // disabled: would overwrite dimregno with wrong value
1270        //refresh_all();
1271        // so requesting just a raw repaint instead:
1272        queue_draw();
1273    }
1274    
1275    void DimRegionChooser::select_next_dimension() {
1276        if (!region) return;
1277        focus_line++;
1278        if (focus_line >= region->Dimensions)
1279            focus_line = region->Dimensions - 1;
1280        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1281        queue_draw();
1282    }
1283    
1284    void DimRegionChooser::select_prev_dimension() {
1285        if (!region) return;
1286        focus_line--;
1287        if (focus_line < 0)
1288            focus_line = 0;
1289        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1290        queue_draw();
1291    }
1292    
1293    gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {
1294        if (!region) return NULL;
1295        return region->pDimensionRegions[maindimregno];
1296    }

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

  ViewVC Help
Powered by ViewVC