/[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 2626 by schoenebeck, Thu Jun 12 15:12:00 2014 UTC revision 3286 by schoenebeck, Thu Jun 22 10:54:10 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 "global.h"
21    #include <gtkmm/box.h>
22  #include "dimregionchooser.h"  #include "dimregionchooser.h"
23  #include <cairomm/context.h>  #include <cairomm/context.h>
24    #include <cairomm/surface.h>
25  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
26  #include <gdkmm/general.h>  #include <gdkmm/general.h>
27  #include <glibmm/stringutils.h>  #include <glibmm/stringutils.h>
28  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
29  #include <glibmm/ustring.h>  #include <glibmm/ustring.h>
30  #include <gtkmm/messagedialog.h>  #include <gtkmm/messagedialog.h>
31    #include <assert.h>
32    
33  #include "global.h"  #include "gfx/builtinpix.h"
   
 // taken from gdk/gdkkeysyms.h  
 // (define on demand, to avoid unnecessary dev lib package build dependency)  
 #ifndef GDK_KEY_Control_L  
 # define GDK_KEY_Control_L 0xffe3  
 #endif  
 #ifndef GDK_KEY_Control_R  
 # define GDK_KEY_Control_R 0xffe4  
 #endif  
34    
35  static std::map<gig::dimension_t,int> caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {  //TODO: this function and dimensionCaseOf() from global.h are duplicates, eliminate either one of them!
36      std::map<gig::dimension_t,int> dimCase;  static DimensionCase caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
37        DimensionCase dimCase;
38      if (!dr) {      if (!dr) {
39          *isValidZone = false;          *isValidZone = false;
40          return dimCase;          return dimCase;
# Line 56  static std::map<gig::dimension_t,int> ca Line 52  static std::map<gig::dimension_t,int> ca
52      if (drIndex == 256) {      if (drIndex == 256) {
53          fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");          fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");
54          *isValidZone = false;          *isValidZone = false;
55          return std::map<gig::dimension_t,int>();          return DimensionCase();
56      }      }
57    
58      for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {      for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {
# Line 67  static std::map<gig::dimension_t,int> ca Line 63  static std::map<gig::dimension_t,int> ca
63          // there are also DimensionRegion objects of unused zones, skip them          // there are also DimensionRegion objects of unused zones, skip them
64          if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {          if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {
65              *isValidZone = false;              *isValidZone = false;
66              return std::map<gig::dimension_t,int>();              return DimensionCase();
67          }          }
68      }      }
69    
# Line 76  static std::map<gig::dimension_t,int> ca Line 72  static std::map<gig::dimension_t,int> ca
72  }  }
73    
74  DimRegionChooser::DimRegionChooser(Gtk::Window& window) :  DimRegionChooser::DimRegionChooser(Gtk::Window& window) :
75      red("#8070ff"),      red("#ff476e"),
76        blue("#4796ff"),
77      black("black"),      black("black"),
78      white("white")      white("white")
79  {  {
80        // make sure blue hatched pattern pixmap is loaded
81        loadBuiltInPix();
82    
83        // create blue hatched pattern 1
84        {
85            const int width = blueHatchedPattern->get_width();
86            const int height = blueHatchedPattern->get_height();
87            const int stride = blueHatchedPattern->get_rowstride();
88    
89            // manually convert from RGBA to ARGB
90            this->blueHatchedPatternARGB = blueHatchedPattern->copy();
91            const int pixelSize = stride / width;
92            const int totalPixels = width * height;
93            assert(pixelSize == 4);
94            unsigned char* ptr = this->blueHatchedPatternARGB->get_pixels();
95            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
96                const unsigned char r = ptr[0];
97                const unsigned char g = ptr[1];
98                const unsigned char b = ptr[2];
99                const unsigned char a = ptr[3];
100                ptr[0] = b;
101                ptr[1] = g;
102                ptr[2] = r;
103                ptr[3] = a;
104            }
105    
106            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
107                this->blueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
108            );
109            this->blueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
110            this->blueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
111        }
112    
113        // create blue hatched pattern 2
114        {
115            const int width = blueHatchedPattern2->get_width();
116            const int height = blueHatchedPattern2->get_height();
117            const int stride = blueHatchedPattern2->get_rowstride();
118    
119            // manually convert from RGBA to ARGB
120            this->blueHatchedPattern2ARGB = blueHatchedPattern2->copy();
121            const int pixelSize = stride / width;
122            const int totalPixels = width * height;
123            assert(pixelSize == 4);
124            unsigned char* ptr = this->blueHatchedPattern2ARGB->get_pixels();
125            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
126                const unsigned char r = ptr[0];
127                const unsigned char g = ptr[1];
128                const unsigned char b = ptr[2];
129                const unsigned char a = ptr[3];
130                ptr[0] = b;
131                ptr[1] = g;
132                ptr[2] = r;
133                ptr[3] = a;
134            }
135    
136            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
137                this->blueHatchedPattern2ARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
138            );
139            this->blueHatchedSurfacePattern2 = Cairo::SurfacePattern::create(imageSurface);
140            this->blueHatchedSurfacePattern2->set_extend(Cairo::EXTEND_REPEAT);
141        }
142    
143        // create gray blue hatched pattern
144        {
145            const int width = grayBlueHatchedPattern->get_width();
146            const int height = grayBlueHatchedPattern->get_height();
147            const int stride = grayBlueHatchedPattern->get_rowstride();
148    
149            // manually convert from RGBA to ARGB
150            this->grayBlueHatchedPatternARGB = grayBlueHatchedPattern->copy();
151            const int pixelSize = stride / width;
152            const int totalPixels = width * height;
153            assert(pixelSize == 4);
154            unsigned char* ptr = this->grayBlueHatchedPatternARGB->get_pixels();
155            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
156                const unsigned char r = ptr[0];
157                const unsigned char g = ptr[1];
158                const unsigned char b = ptr[2];
159                const unsigned char a = ptr[3];
160                ptr[0] = b;
161                ptr[1] = g;
162                ptr[2] = r;
163                ptr[3] = a;
164            }
165    
166            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
167                this->grayBlueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
168            );
169            this->grayBlueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
170            this->grayBlueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
171        }
172    
173      instrument = 0;      instrument = 0;
174      region = 0;      region = 0;
175      maindimregno = -1;      maindimregno = -1;
176        maindimtype = gig::dimension_none; // initialize with invalid dimension type
177      focus_line = 0;      focus_line = 0;
178      resize.active = false;      resize.active = false;
179      cursor_is_resize = false;      cursor_is_resize = false;
180      h = 20;      h = 24;
181      multiSelectKeyDown = false;      multiSelectKeyDown = false;
182        primaryKeyDown = false;
183        shiftKeyDown = false;
184        modifybothchannels = modifyalldimregs = modifybothchannels = false;
185      set_can_focus();      set_can_focus();
186    
187        const Glib::ustring txtUseCheckBoxAllRegions =
188            _("Use checkbox 'all regions' to control whether this should apply to all regions.");
189    
190      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
191        actionSplitDimZone = Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone"), txtUseCheckBoxAllRegions);
192        actionSplitDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
193      actionGroup->add(      actionGroup->add(
194          Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone")),          actionSplitDimZone,
195          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
196      );      );
197        actionDeleteDimZone = Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone"), txtUseCheckBoxAllRegions);
198        actionDeleteDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
199      actionGroup->add(      actionGroup->add(
200          Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone")),          actionDeleteDimZone,
201          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
202      );      );
203    
# Line 141  DimRegionChooser::~DimRegionChooser() Line 242  DimRegionChooser::~DimRegionChooser()
242  {  {
243  }  }
244    
245    void DimRegionChooser::setModifyBothChannels(bool b) {
246        modifybothchannels = b;
247        // redraw required parts
248        queue_draw();
249    }
250    
251    void DimRegionChooser::setModifyAllDimensionRegions(bool b) {
252        modifyalldimregs = b;
253        // redraw required parts
254        queue_draw();
255    }
256    
257    void DimRegionChooser::setModifyAllRegions(bool b) {
258        modifyallregions = b;
259    
260        actionDeleteDimZone->set_label(b ? _("Delete Dimension Zone [ALL REGIONS]") : _("Delete Dimension Zone"));
261        actionSplitDimZone->set_label(b ? _("Split Dimensions Zone [ALL REGIONS]") : _("Split Dimensions Zone"));
262    
263        // redraw required parts
264        queue_draw();
265    }
266    
267  #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
268  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
269  {  {
# Line 229  bool DimRegionChooser::on_draw(const Cai Line 352  bool DimRegionChooser::on_draw(const Cai
352                      dstr = dstrbuf;                      dstr = dstrbuf;
353                      break;                      break;
354                  }                  }
                 layout->set_text(dstr);  
355    
356                    // Since bold font yields in larger label width, we first always
357                    // set the bold text variant, retrieve its dimensions (as worst
358                    // case dimensions of the label) ...
359                    layout->set_markup("<b>" + Glib::ustring(dstr) + "</b>");
360                  Pango::Rectangle rectangle = layout->get_logical_extents();                  Pango::Rectangle rectangle = layout->get_logical_extents();
361                    // ... and then reset the label to regular font style in case
362                    // the line is not selected. Otherwise the right hand side
363                    // actual dimension zones would jump around on selection change.
364                    bool isSelectedLine = (focus_line == i);
365                    if (!isSelectedLine)
366                        layout->set_markup(dstr);
367    
368                  double text_w = double(rectangle.get_width()) / Pango::SCALE;                  double text_w = double(rectangle.get_width()) / Pango::SCALE;
369                  if (text_w > maxwidth) maxwidth = text_w;                  if (text_w > maxwidth) maxwidth = text_w;
370    
# Line 273  bool DimRegionChooser::on_draw(const Cai Line 406  bool DimRegionChooser::on_draw(const Cai
406                  // draw focus rectangle around dimension's label and zones                  // draw focus rectangle around dimension's label and zones
407                  if (has_focus() && focus_line == i) {                  if (has_focus() && focus_line == i) {
408  #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
409                      Gdk::Rectangle farea(0, y, 150, 20);                      Gdk::Rectangle farea(0, y, 150, h);
410                      get_style()->paint_focus(get_window(), get_state(), farea,                      get_style()->paint_focus(get_window(), get_state(), farea,
411                                               *this, "",                                               *this, "",
412                                               0, y, label_width, 20);                                               0, y, label_width, h);
413  #else  #else
414                      get_style_context()->render_focus(cr,                      get_style_context()->render_focus(cr,
415                                                        0, y, label_width, 20);                                                        0, y, label_width, h);
416  #endif  #endif
417                  }                  }
418    
# Line 318  bool DimRegionChooser::on_draw(const Cai Line 451  bool DimRegionChooser::on_draw(const Cai
451                      cr->move_to(label_width + 0.5, y + 1);                      cr->move_to(label_width + 0.5, y + 1);
452                      cr->line_to(label_width + 0.5, y + h - 1);                      cr->line_to(label_width + 0.5, y + h - 1);
453                      int prevX = label_width;                      int prevX = label_width;
454                      int prevUpperLimit = 0;                      int prevUpperLimit = -1;
455    
456                      for (int j = 0 ; j < nbZones ; j++) {                      for (int j = 0 ; j < nbZones ; j++) {
457                          // draw dimension zone's borders for custom splits                          // draw dimension zone's borders for custom splits
# Line 338  bool DimRegionChooser::on_draw(const Cai Line 471  bool DimRegionChooser::on_draw(const Cai
471    
472                          // draw fill for zone                          // draw fill for zone
473                          bool isSelectedZone = this->dimzones[dimension].count(j);                          bool isSelectedZone = this->dimzones[dimension].count(j);
474                          Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);                          bool isMainSelection =
475                                this->maindimcase.find(dimension) != this->maindimcase.end() &&
476                                this->maindimcase[dimension] == j;
477                            bool isCheckBoxSelected =
478                                modifyalldimregs ||
479                                (modifybothchannels &&
480                                    dimension == gig::dimension_samplechannel);
481                            if (isMainSelection)
482                                Gdk::Cairo::set_source_rgba(cr, blue);
483                            else if (isSelectedZone)
484                                cr->set_source(blueHatchedSurfacePattern2);
485                            else if (isCheckBoxSelected)
486                                cr->set_source(blueHatchedSurfacePattern);
487                            else
488                                Gdk::Cairo::set_source_rgba(cr, white);
489    
490                          cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);                          cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
491                          cr->fill();                          cr->fill();
492    
# Line 346  bool DimRegionChooser::on_draw(const Cai Line 494  bool DimRegionChooser::on_draw(const Cai
494                          // as numeric value to the user                          // as numeric value to the user
495                          {                          {
496                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
497                              layout->set_text(Glib::Ascii::dtostr(prevUpperLimit));                              layout->set_text(Glib::Ascii::dtostr(prevUpperLimit+1));
498                              Gdk::Cairo::set_source_rgba(cr, black);                              Gdk::Cairo::set_source_rgba(cr, black);
                             Pango::Rectangle rect = layout->get_logical_extents();  
499                              // get the text dimensions                              // get the text dimensions
500                              int text_width, text_height;                              int text_width, text_height;
501                              layout->get_pixel_size(text_width, text_height);                              layout->get_pixel_size(text_width, text_height);
502                              // move text to the left end of the dimension zone                              // move text to the left end of the dimension zone
503                              cr->move_to(prevX + 3, y + 1);                              cr->move_to(prevX + 3, y + (h - text_height) / 2);
504  #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
505                              pango_cairo_show_layout(cr->cobj(), layout->gobj());                              pango_cairo_show_layout(cr->cobj(), layout->gobj());
506  #else  #else
# Line 366  bool DimRegionChooser::on_draw(const Cai Line 513  bool DimRegionChooser::on_draw(const Cai
513                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
514                              layout->set_text(Glib::Ascii::dtostr(upperLimit));                              layout->set_text(Glib::Ascii::dtostr(upperLimit));
515                              Gdk::Cairo::set_source_rgba(cr, black);                              Gdk::Cairo::set_source_rgba(cr, black);
                             Pango::Rectangle rect = layout->get_logical_extents();  
516                              // get the text dimensions                              // get the text dimensions
517                              int text_width, text_height;                              int text_width, text_height;
518                              layout->get_pixel_size(text_width, text_height);                              layout->get_pixel_size(text_width, text_height);
519                              // move text to the left end of the dimension zone                              // move text to the left end of the dimension zone
520                              cr->move_to(x - 3 - text_width, y + 1);                              cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
521  #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
522                              pango_cairo_show_layout(cr->cobj(), layout->gobj());                              pango_cairo_show_layout(cr->cobj(), layout->gobj());
523  #else  #else
# Line 398  bool DimRegionChooser::on_draw(const Cai Line 544  bool DimRegionChooser::on_draw(const Cai
544                          if (j != 0) {                          if (j != 0) {
545                              // draw fill for zone                              // draw fill for zone
546                              bool isSelectedZone = this->dimzones[dimension].count(j-1);                              bool isSelectedZone = this->dimzones[dimension].count(j-1);
547                              Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);                              bool isMainSelection =
548                                    this->maindimcase.find(dimension) != this->maindimcase.end() &&
549                                    this->maindimcase[dimension] == (j-1);
550                                bool isCheckBoxSelected =
551                                    modifyalldimregs ||
552                                    (modifybothchannels &&
553                                        dimension == gig::dimension_samplechannel);
554                                if (isMainSelection)
555                                    Gdk::Cairo::set_source_rgba(cr, blue);
556                                else if (isSelectedZone)
557                                    cr->set_source(blueHatchedSurfacePattern2);
558                                else if (isCheckBoxSelected)
559                                    cr->set_source(blueHatchedSurfacePattern);
560                                else
561                                    Gdk::Cairo::set_source_rgba(cr, white);
562                              cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);                              cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
563                              cr->fill();                              cr->fill();
564    
# Line 408  bool DimRegionChooser::on_draw(const Cai Line 568  bool DimRegionChooser::on_draw(const Cai
568                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
569                                  layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));                                  layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));
570                                  Gdk::Cairo::set_source_rgba(cr, black);                                  Gdk::Cairo::set_source_rgba(cr, black);
                                 Pango::Rectangle rect = layout->get_logical_extents();  
571                                  // get the text dimensions                                  // get the text dimensions
572                                  int text_width, text_height;                                  int text_width, text_height;
573                                  layout->get_pixel_size(text_width, text_height);                                  layout->get_pixel_size(text_width, text_height);
574                                  // move text to the left end of the dimension zone                                  // move text to the left end of the dimension zone
575                                  cr->move_to(prevX + 3, y + 1);                                  cr->move_to(prevX + 3, y + (h - text_height) / 2);
576  #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
577                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
578  #else  #else
# Line 426  bool DimRegionChooser::on_draw(const Cai Line 585  bool DimRegionChooser::on_draw(const Cai
585                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
586                                  layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));                                  layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));
587                                  Gdk::Cairo::set_source_rgba(cr, black);                                  Gdk::Cairo::set_source_rgba(cr, black);
                                 Pango::Rectangle rect = layout->get_logical_extents();  
588                                  // get the text dimensions                                  // get the text dimensions
589                                  int text_width, text_height;                                  int text_width, text_height;
590                                  layout->get_pixel_size(text_width, text_height);                                  layout->get_pixel_size(text_width, text_height);
591                                  // move text to the left end of the dimension zone                                  // move text to the left end of the dimension zone
592                                  cr->move_to(x - 3 - text_width, y + 1);                                  cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
593  #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
594                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
595  #else  #else
# Line 469  void DimRegionChooser::set_region(gig::R Line 627  void DimRegionChooser::set_region(gig::R
627          }          }
628      }      }
629      dimregion_selected();      dimregion_selected();
630      set_size_request(800, region ? nbDimensions * 20 : 0);      set_size_request(800, region ? nbDimensions * h : 0);
631    
632      labels_changed = true;      labels_changed = true;
633      queue_resize();      queue_resize();
# Line 511  void DimRegionChooser::get_dimregions(co Line 669  void DimRegionChooser::get_dimregions(co
669    
670  void DimRegionChooser::update_after_resize()  void DimRegionChooser::update_after_resize()
671  {  {
672      if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {      const uint8_t upperLimit = resize.pos - 1;
673        gig::Instrument* instr = (gig::Instrument*)region->GetParent();
674    
675          int bitpos = 0;      int bitpos = 0;
676          for (int j = 0 ; j < resize.dimension ; j++) {      for (int j = 0 ; j < resize.dimension ; j++) {
677              bitpos += region->pDimensionDefinitions[j].bits;          bitpos += region->pDimensionDefinitions[j].bits;
678          }      }
679    
680        const int stereobitpos =
681            (modifybothchannels) ? baseBits(gig::dimension_samplechannel, region) : -1;
682    
683        // the velocity dimension must be handled differently than all other
684        // dimension types, because
685        // 1. it is currently the only dimension type which allows different zone
686        //    sizes for different cases
687        // 2. for v2 format VelocityUpperLimit has to be set, DimensionUpperLimits for v3
688        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
689          int mask =          int mask =
690              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
691          int c = maindimregno & mask; // mask away this dimension          int c = maindimregno & mask; // mask away this dimension
# Line 542  void DimRegionChooser::update_after_resi Line 711  void DimRegionChooser::update_after_resi
711              }              }
712          }          }
713    
714          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];          int index = c + (resize.zone << bitpos);
715            gig::DimensionRegion* d = region->pDimensionRegions[index];
716          // update both v2 and v3 values          // update both v2 and v3 values
717          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;          d->DimensionUpperLimits[resize.dimension] = upperLimit;
718          d->VelocityUpperLimit = resize.pos - 1;          d->VelocityUpperLimit = upperLimit;
719            if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
720                gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
721                d->DimensionUpperLimits[resize.dimension] = upperLimit;
722                d->VelocityUpperLimit = upperLimit;
723            }
724    
725            if (modifyalldimregs) {
726                gig::Region* rgn = NULL;
727                for (int key = 0; key < 128; ++key) {
728                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
729                    rgn = instr->GetRegion(key);
730                    if (!modifyallregions && rgn != region) continue; // hack to reduce overall code amount a bit
731                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
732                    if (!dimdef) continue;
733                    if (dimdef->zones != resize.dimensionDef.zones) continue;
734                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
735                    assert(iDim >= 0 && iDim < rgn->Dimensions);
736    
737                    // the dimension layout might be completely different in this
738                    // region, so we have to recalculate bitpos etc for this region
739                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
740                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
741                    const int selection = resize.zone << bitpos;
742    
743                    // primitive and inefficient loop implementation, however due to
744                    // this circumstance the loop code is much simpler, and its lack
745                    // of runtime efficiency should not be notable in practice
746                    for (int idr = 0; idr < 256; ++idr) {
747                        const int index = (idr & stencil) | selection;
748                        assert(index >= 0 && index < 256);
749                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
750                        if (!dr) continue;
751                        dr->DimensionUpperLimits[iDim] = upperLimit;
752                        d->VelocityUpperLimit = upperLimit;
753                    }
754                }
755            } else if (modifyallregions) { // implies modifyalldimregs is false ...
756                // resolve the precise case we need to modify for all other regions
757                DimensionCase dimCase = dimensionCaseOf(d);
758                // apply the velocity upper limit change to that resolved dim case
759                // of all regions ...
760                gig::Region* rgn = NULL;
761                for (int key = 0; key < 128; ++key) {
762                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
763                    rgn = instr->GetRegion(key);
764                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
765                    if (!dimdef) continue;
766                    if (dimdef->zones != resize.dimensionDef.zones) continue;
767                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
768                    assert(iDim >= 0 && iDim < rgn->Dimensions);
769    
770                    std::vector<gig::DimensionRegion*> dimrgns = dimensionRegionsMatching(dimCase, rgn);
771                    for (int i = 0; i < dimrgns.size(); ++i) {
772                        gig::DimensionRegion* dr = dimrgns[i];
773                        dr->DimensionUpperLimits[iDim] = upperLimit;
774                        dr->VelocityUpperLimit = upperLimit;
775                    }
776                }
777            }
778      } else {      } else {
779          for (int i = 0 ; i < region->DimensionRegions ; ) {          for (int i = 0 ; i < region->DimensionRegions ; ) {
   
780              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
781                  // the dimension didn't previously have custom                  // the dimension didn't previously have custom
782                  // limits, so we have to set default limits for                  // limits, so we have to set default limits for
783                  // all the dimension regions                  // all the dimension regions
                 int bitpos = 0;  
                 for (int j = 0 ; j < resize.dimension ; j++) {  
                     bitpos += region->pDimensionDefinitions[j].bits;  
                 }  
784                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
785    
786                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
# Line 565  void DimRegionChooser::update_after_resi Line 788  void DimRegionChooser::update_after_resi
788                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
789                  }                  }
790              }              }
791              gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];              int index = i + (resize.zone << bitpos);
792              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;              gig::DimensionRegion* d = region->pDimensionRegions[index];
793                d->DimensionUpperLimits[resize.dimension] = upperLimit;
794    #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
795                if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
796                    gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
797                    d->DimensionUpperLimits[resize.dimension] = upperLimit;
798                }
799    #endif
800              int bitpos = 0;              int bitpos = 0;
801              int j;              int j;
802              for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
# Line 581  void DimRegionChooser::update_after_resi Line 810  void DimRegionChooser::update_after_resi
810              if (j == region->Dimensions) break;              if (j == region->Dimensions) break;
811              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
812          }          }
813    
814            if (modifyallregions) { // TODO: this code block could be merged with the similar (and more generalized) code block of the velocity dimension above
815                gig::Region* rgn = NULL;
816                for (int key = 0; key < 128; ++key) {
817                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
818                    rgn = instr->GetRegion(key);
819                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
820                    if (!dimdef) continue;
821                    if (dimdef->zones != resize.dimensionDef.zones) continue;
822                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
823                    assert(iDim >= 0 && iDim < rgn->Dimensions);
824    
825                    // the dimension layout might be completely different in this
826                    // region, so we have to recalculate bitpos etc for this region
827                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
828                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
829                    const int selection = resize.zone << bitpos;
830    
831                    // this loop implementation is less efficient than the above's
832                    // loop implementation (which skips unnecessary dimension regions)
833                    // however this code is much simpler, and its lack of runtime
834                    // efficiency should not be notable in practice
835                    for (int idr = 0; idr < 256; ++idr) {
836                        const int index = (idr & stencil) | selection;
837                        assert(index >= 0 && index < 256);
838                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
839                        if (!dr) continue;
840                        dr->DimensionUpperLimits[iDim] = upperLimit;
841                    }
842                }
843            }
844      }      }
845  }  }
846    
# Line 809  bool DimRegionChooser::is_in_resize_zone Line 1069  bool DimRegionChooser::is_in_resize_zone
1069                  if (x <= limitx - 2) break;                  if (x <= limitx - 2) break;
1070                  if (x <= limitx + 2) {                  if (x <= limitx + 2) {
1071                      resize.dimension = dim;                      resize.dimension = dim;
1072                      resize.offset = iZone << bitpos;                      resize.dimensionDef = region->pDimensionDefinitions[dim];
1073                        resize.zone = iZone;
1074                      resize.pos = limit;                      resize.pos = limit;
1075                      resize.min = prev_limit;                      resize.min = prev_limit;
1076    
# Line 850  sigc::signal<void>& DimRegionChooser::si Line 1111  sigc::signal<void>& DimRegionChooser::si
1111    
1112  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
1113  {  {
1114      // 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
1115      // fokus.      // to set focus
1116      if (direction == Gtk::DIR_TAB_FORWARD ||      if (direction == Gtk::DIR_TAB_FORWARD ||
1117          direction == Gtk::DIR_DOWN) {          direction == Gtk::DIR_DOWN) {
1118          if (!has_focus()) {          if (!has_focus()) {
# Line 883  bool DimRegionChooser::on_focus(Gtk::Dir Line 1144  bool DimRegionChooser::on_focus(Gtk::Dir
1144              }              }
1145          }          }
1146      } else if (!has_focus()) {      } else if (!has_focus()) {
1147          // TODO: kolla att focus_line finns!          // TODO: check that focus_line exists
1148          grab_focus();          grab_focus();
1149          return true;          return true;
1150      } else {      } else {
1151          // TODO: öka eller minska värde!          // TODO: increase or decrease value
1152      }      }
1153        return false;
1154  }  }
1155    
1156  void DimRegionChooser::split_dimension_zone() {      void DimRegionChooser::split_dimension_zone() {    
1157      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1158      try {      try {
1159          region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);          if (!modifyallregions) {
1160                region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1161            } else {
1162                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1163                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1164                assert(pMaindimdef != NULL);
1165                // retain structure by value since the original region will be
1166                // modified in the loop below as well
1167                gig::dimension_def_t maindimdef = *pMaindimdef;
1168                std::vector<gig::Region*> ignoredAll;
1169                std::vector<gig::Region*> ignoredMinor;
1170                std::vector<gig::Region*> ignoredCritical;
1171                gig::Region* rgn = NULL;
1172                for (int key = 0; key < 128; ++key) {
1173                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1174                    rgn = instr->GetRegion(key);
1175    
1176                    // ignore all regions which do not exactly match the dimension
1177                    // layout of the selected region where this operation was emitted
1178                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1179                    if (!dimdef) {
1180                        ignoredAll.push_back(rgn);
1181                        ignoredMinor.push_back(rgn);
1182                        continue;
1183                    }
1184                    if (dimdef->zones != maindimdef.zones) {
1185                        ignoredAll.push_back(rgn);
1186                        ignoredCritical.push_back(rgn);
1187                        continue;
1188                    }
1189    
1190                    rgn->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1191                }
1192                if (!ignoredAll.empty()) {
1193                    Glib::ustring txt;
1194                    if (ignoredCritical.empty())
1195                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1196                    else if (ignoredMinor.empty())
1197                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1198                    else
1199                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1200                        ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1201                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1202                    Gtk::MessageDialog msg(txt, false, type);
1203                    msg.run();
1204                }
1205            }
1206      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1207          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1208          msg.run();          msg.run();
# Line 909  void DimRegionChooser::split_dimension_z Line 1217  void DimRegionChooser::split_dimension_z
1217  void DimRegionChooser::delete_dimension_zone() {  void DimRegionChooser::delete_dimension_zone() {
1218      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1219      try {      try {
1220          region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);          if (!modifyallregions) {
1221                region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1222            } else {
1223                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1224                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1225                assert(pMaindimdef != NULL);
1226                // retain structure by value since the original region will be
1227                // modified in the loop below as well
1228                gig::dimension_def_t maindimdef = *pMaindimdef;
1229                std::vector<gig::Region*> ignoredAll;
1230                std::vector<gig::Region*> ignoredMinor;
1231                std::vector<gig::Region*> ignoredCritical;
1232                gig::Region* rgn = NULL;
1233                for (int key = 0; key < 128; ++key) {
1234                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1235                    rgn = instr->GetRegion(key);
1236    
1237                    // ignore all regions which do not exactly match the dimension
1238                    // layout of the selected region where this operation was emitted
1239                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1240                    if (!dimdef) {
1241                        ignoredAll.push_back(rgn);
1242                        ignoredMinor.push_back(rgn);
1243                        continue;
1244                    }
1245                    if (dimdef->zones != maindimdef.zones) {
1246                        ignoredAll.push_back(rgn);
1247                        ignoredCritical.push_back(rgn);
1248                        continue;
1249                    }
1250    
1251                    rgn->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1252                }
1253                if (!ignoredAll.empty()) {
1254                    Glib::ustring txt;
1255                    if (ignoredCritical.empty())
1256                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1257                    else if (ignoredMinor.empty())
1258                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1259                    else
1260                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1261                              ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1262                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1263                    Gtk::MessageDialog msg(txt, false, type);
1264                    msg.run();
1265                }
1266            }
1267      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1268          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1269          msg.run();          msg.run();
# Line 921  void DimRegionChooser::delete_dimension_ Line 1275  void DimRegionChooser::delete_dimension_
1275      refresh_all();      refresh_all();
1276  }  }
1277    
1278    // Cmd key on Mac, Ctrl key on all other OSs
1279    static const guint primaryKeyL =
1280        #if defined(__APPLE__)
1281        GDK_KEY_Meta_L;
1282        #else
1283        GDK_KEY_Control_L;
1284        #endif
1285    
1286    static const guint primaryKeyR =
1287        #if defined(__APPLE__)
1288        GDK_KEY_Meta_R;
1289        #else
1290        GDK_KEY_Control_R;
1291        #endif
1292    
1293  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1294      //printf("key down\n");      //printf("key down 0x%x\n", key->keyval);
1295      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1296          multiSelectKeyDown = true;          multiSelectKeyDown = true;
1297        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1298            primaryKeyDown = true;
1299        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1300            shiftKeyDown = true;
1301    
1302        //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
1303        /*if (key->keyval == GDK_KEY_Left)
1304            select_prev_dimzone();
1305        if (key->keyval == GDK_KEY_Right)
1306            select_next_dimzone();
1307        if (key->keyval == GDK_KEY_Up)
1308            select_prev_dimension();
1309        if (key->keyval == GDK_KEY_Down)
1310            select_next_dimension();*/
1311        return false;
1312  }  }
1313    
1314  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1315      //printf("key up\n");      //printf("key up 0x%x\n", key->keyval);
1316      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1317          multiSelectKeyDown = false;          multiSelectKeyDown = false;
1318        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1319            primaryKeyDown = false;
1320        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1321            shiftKeyDown = false;
1322    
1323        if (!has_focus()) return false;
1324    
1325        // avoid conflict with Ctrl+Left and Ctrl+Right accelerators on mainwindow
1326        // (which is supposed to switch between regions)
1327        if (primaryKeyDown) return false;
1328    
1329        // avoid conflict with Alt+Shift+Left and Alt+Shift+Right accelerators on
1330        // mainwindow
1331        if (shiftKeyDown) return false;
1332    
1333        if (key->keyval == GDK_KEY_Left)
1334            select_prev_dimzone();
1335        if (key->keyval == GDK_KEY_Right)
1336            select_next_dimzone();
1337        if (key->keyval == GDK_KEY_Up)
1338            select_prev_dimension();
1339        if (key->keyval == GDK_KEY_Down)
1340            select_next_dimension();
1341    
1342        return false;
1343    }
1344    
1345    void DimRegionChooser::resetSelectedZones() {
1346        this->dimzones.clear();
1347        if (!region) {
1348            queue_draw(); // redraw required parts
1349            return;
1350        }
1351        if (maindimregno < 0 || maindimregno >= region->DimensionRegions) {
1352            queue_draw(); // redraw required parts
1353            return;
1354        }
1355        if (!region->pDimensionRegions[maindimregno]) {
1356            queue_draw(); // redraw required parts
1357            return;
1358        }
1359        gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1360    
1361        bool isValidZone;
1362        this->maindimcase = dimensionCaseOf(dimrgn);
1363    
1364        for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1365             it != this->maindimcase.end(); ++it)
1366        {
1367            this->dimzones[it->first].insert(it->second);
1368        }
1369    
1370        // redraw required parts
1371        queue_draw();
1372    }
1373    
1374    bool DimRegionChooser::select_dimregion(gig::DimensionRegion* dimrgn) {
1375        if (!region) return false; //.selection failed
1376    
1377        for (int dr = 0; dr < region->DimensionRegions && region->pDimensionRegions[dr]; ++dr) {
1378            if (region->pDimensionRegions[dr] == dimrgn) {
1379                // reset dim region zone selection to the requested specific dim region case
1380                maindimregno = dr;
1381                resetSelectedZones();
1382    
1383                // emit signal that dimregion selection has changed, for external entities
1384                dimregion_selected();
1385    
1386                return true; // selection success
1387            }
1388        }
1389    
1390        return false; //.selection failed
1391    }
1392    
1393    void DimRegionChooser::select_next_dimzone(bool add) {
1394        select_dimzone_by_dir(+1, add);
1395    }
1396    
1397    void DimRegionChooser::select_prev_dimzone(bool add) {
1398        select_dimzone_by_dir(-1, add);
1399    }
1400    
1401    void DimRegionChooser::select_dimzone_by_dir(int dir, bool add) {
1402        if (!region) return;
1403        if (!region->Dimensions) return;
1404        if (focus_line < 0) focus_line = 0;
1405        if (focus_line >= region->Dimensions) focus_line = region->Dimensions - 1;
1406    
1407        maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1408        if (maindimtype == gig::dimension_none) {
1409            printf("maindimtype -> none\n");
1410            return;
1411        }
1412    
1413        if (maindimcase.empty()) {
1414            maindimcase = dimensionCaseOf(region->pDimensionRegions[maindimregno]);
1415            if (maindimcase.empty()) {
1416                printf("caseOfDimregion(%d) -> empty\n", maindimregno);
1417                return;
1418            }
1419        }
1420    
1421        int z = (dir > 0) ? maindimcase[maindimtype] + 1 : maindimcase[maindimtype] - 1;
1422        if (z < 0) z = 0;
1423        if (z >= region->pDimensionDefinitions[focus_line].zones)
1424            z = region->pDimensionDefinitions[focus_line].zones - 1;
1425    
1426        maindimcase[maindimtype] = z;
1427    
1428        ::gig::DimensionRegion* dr = dimensionRegionMatching(maindimcase, region);
1429        if (!dr) {
1430            printf("select_dimzone_by_dir(%d) -> !dr\n", dir);
1431            return;
1432        }
1433    
1434        maindimregno = getDimensionRegionIndex(dr);
1435    
1436        if (!add) {
1437            // reset selected dimregion zones
1438            dimzones.clear();
1439        }
1440        for (DimensionCase::const_iterator it = maindimcase.begin();
1441             it != maindimcase.end(); ++it)
1442        {
1443            dimzones[it->first].insert(it->second);
1444        }
1445    
1446        dimregion_selected();
1447    
1448        // disabled: would overwrite dimregno with wrong value
1449        //refresh_all();
1450        // so requesting just a raw repaint instead:
1451        queue_draw();
1452    }
1453    
1454    void DimRegionChooser::select_next_dimension() {
1455        if (!region) return;
1456        focus_line++;
1457        if (focus_line >= region->Dimensions)
1458            focus_line = region->Dimensions - 1;
1459        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1460        queue_draw();
1461    }
1462    
1463    void DimRegionChooser::select_prev_dimension() {
1464        if (!region) return;
1465        focus_line--;
1466        if (focus_line < 0)
1467            focus_line = 0;
1468        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1469        queue_draw();
1470  }  }
1471    
1472  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {

Legend:
Removed from v.2626  
changed lines
  Added in v.3286

  ViewVC Help
Powered by ViewVC