/[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 2845 by persson, Sun Sep 20 10:18:22 2015 UTC revision 3158 by schoenebeck, Mon May 8 18:05:35 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2015 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 20  Line 20 
20  #include <gtkmm/box.h>  #include <gtkmm/box.h>
21  #include "dimregionchooser.h"  #include "dimregionchooser.h"
22  #include <cairomm/context.h>  #include <cairomm/context.h>
23    #include <cairomm/surface.h>
24  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
25  #include <gdkmm/general.h>  #include <gdkmm/general.h>
26  #include <glibmm/stringutils.h>  #include <glibmm/stringutils.h>
27    #include <gtkmm/stock.h>
28  #include <glibmm/ustring.h>  #include <glibmm/ustring.h>
29  #include <gtkmm/messagedialog.h>  #include <gtkmm/messagedialog.h>
30    #include <assert.h>
31    
32  #include "global.h"  #include "global.h"
33    #include "gfx/builtinpix.h"
34    
35  // taken from gdk/gdkkeysyms.h  //TODO: this function and dimensionCaseOf() from global.h are duplicates, eliminate either one of them!
36  // (define on demand, to avoid unnecessary dev lib package build dependency)  static DimensionCase caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
37  #ifndef GDK_KEY_Control_L      DimensionCase dimCase;
 # define GDK_KEY_Control_L 0xffe3  
 #endif  
 #ifndef GDK_KEY_Control_R  
 # define GDK_KEY_Control_R 0xffe4  
 #endif  
   
 static std::map<gig::dimension_t,int> caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {  
     std::map<gig::dimension_t,int> 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
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 gray blue hatched pattern
114        {
115            const int width = grayBlueHatchedPattern->get_width();
116            const int height = grayBlueHatchedPattern->get_height();
117            const int stride = grayBlueHatchedPattern->get_rowstride();
118    
119            // manually convert from RGBA to ARGB
120            this->grayBlueHatchedPatternARGB = grayBlueHatchedPattern->copy();
121            const int pixelSize = stride / width;
122            const int totalPixels = width * height;
123            assert(pixelSize == 4);
124            unsigned char* ptr = this->grayBlueHatchedPatternARGB->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->grayBlueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
138            );
139            this->grayBlueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
140            this->grayBlueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
141        }
142    
143      instrument = 0;      instrument = 0;
144      region = 0;      region = 0;
145      maindimregno = -1;      maindimregno = -1;
146        maindimtype = gig::dimension_none; // initialize with invalid dimension type
147      focus_line = 0;      focus_line = 0;
148      resize.active = false;      resize.active = false;
149      cursor_is_resize = false;      cursor_is_resize = false;
150      h = 24;      h = 24;
151      multiSelectKeyDown = false;      multiSelectKeyDown = false;
152        primaryKeyDown = false;
153        shiftKeyDown = false;
154        modifybothchannels = modifyalldimregs = modifybothchannels = false;
155      set_can_focus();      set_can_focus();
156    
157        const Glib::ustring txtUseCheckBoxAllRegions =
158            _("Use checkbox 'all regions' to control whether this should apply to all regions.");
159    
160      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
161        actionSplitDimZone = Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone"), txtUseCheckBoxAllRegions);
162        actionSplitDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
163      actionGroup->add(      actionGroup->add(
164          Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone")),          actionSplitDimZone,
165          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
166      );      );
167        actionDeleteDimZone = Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone"), txtUseCheckBoxAllRegions);
168        actionDeleteDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
169      actionGroup->add(      actionGroup->add(
170          Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone")),          actionDeleteDimZone,
171          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
172      );      );
173    
# Line 141  DimRegionChooser::~DimRegionChooser() Line 212  DimRegionChooser::~DimRegionChooser()
212  {  {
213  }  }
214    
215    void DimRegionChooser::setModifyBothChannels(bool b) {
216        modifybothchannels = b;
217        // redraw required parts
218        queue_draw();
219    }
220    
221    void DimRegionChooser::setModifyAllDimensionRegions(bool b) {
222        modifyalldimregs = b;
223        // redraw required parts
224        queue_draw();
225    }
226    
227    void DimRegionChooser::setModifyAllRegions(bool b) {
228        modifyallregions = b;
229    
230        actionDeleteDimZone->set_label(b ? _("Delete Dimension Zone [ALL REGIONS]") : _("Delete Dimension Zone"));
231        actionSplitDimZone->set_label(b ? _("Split Dimensions Zone [ALL REGIONS]") : _("Split Dimensions Zone"));
232    
233        // redraw required parts
234        queue_draw();
235    }
236    
237  #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
238  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
239  {  {
# Line 229  bool DimRegionChooser::on_draw(const Cai Line 322  bool DimRegionChooser::on_draw(const Cai
322                      dstr = dstrbuf;                      dstr = dstrbuf;
323                      break;                      break;
324                  }                  }
                 layout->set_text(dstr);  
325    
326                    // Since bold font yields in larger label width, we first always
327                    // set the bold text variant, retrieve its dimensions (as worst
328                    // case dimensions of the label) ...
329                    layout->set_markup("<b>" + Glib::ustring(dstr) + "</b>");
330                  Pango::Rectangle rectangle = layout->get_logical_extents();                  Pango::Rectangle rectangle = layout->get_logical_extents();
331                    // ... and then reset the label to regular font style in case
332                    // the line is not selected. Otherwise the right hand side
333                    // actual dimension zones would jump around on selection change.
334                    bool isSelectedLine = (focus_line == i);
335                    if (!isSelectedLine)
336                        layout->set_markup(dstr);
337    
338                  double text_w = double(rectangle.get_width()) / Pango::SCALE;                  double text_w = double(rectangle.get_width()) / Pango::SCALE;
339                  if (text_w > maxwidth) maxwidth = text_w;                  if (text_w > maxwidth) maxwidth = text_w;
340    
# Line 338  bool DimRegionChooser::on_draw(const Cai Line 441  bool DimRegionChooser::on_draw(const Cai
441    
442                          // draw fill for zone                          // draw fill for zone
443                          bool isSelectedZone = this->dimzones[dimension].count(j);                          bool isSelectedZone = this->dimzones[dimension].count(j);
444                          Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);                          bool isMainSelection =
445                                this->maindimcase.find(dimension) != this->maindimcase.end() &&
446                                this->maindimcase[dimension] == j;
447                            bool isCheckBoxSelected =
448                                modifyalldimregs ||
449                                (modifybothchannels &&
450                                    dimension == gig::dimension_samplechannel);
451                            if (isMainSelection)
452                                Gdk::Cairo::set_source_rgba(cr, blue);
453                            else if (isSelectedZone)
454                                cr->set_source(blueHatchedSurfacePattern);
455                            else if (isCheckBoxSelected)
456                                cr->set_source(grayBlueHatchedSurfacePattern);
457                            else
458                                Gdk::Cairo::set_source_rgba(cr, white);
459    
460                          cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);                          cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
461                          cr->fill();                          cr->fill();
462    
# Line 396  bool DimRegionChooser::on_draw(const Cai Line 514  bool DimRegionChooser::on_draw(const Cai
514                          if (j != 0) {                          if (j != 0) {
515                              // draw fill for zone                              // draw fill for zone
516                              bool isSelectedZone = this->dimzones[dimension].count(j-1);                              bool isSelectedZone = this->dimzones[dimension].count(j-1);
517                              Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);                              bool isMainSelection =
518                                    this->maindimcase.find(dimension) != this->maindimcase.end() &&
519                                    this->maindimcase[dimension] == (j-1);
520                                bool isCheckBoxSelected =
521                                    modifyalldimregs ||
522                                    (modifybothchannels &&
523                                        dimension == gig::dimension_samplechannel);
524                                if (isMainSelection)
525                                    Gdk::Cairo::set_source_rgba(cr, blue);
526                                else if (isSelectedZone)
527                                    cr->set_source(blueHatchedSurfacePattern);
528                                else if (isCheckBoxSelected)
529                                    cr->set_source(grayBlueHatchedSurfacePattern);
530                                else
531                                    Gdk::Cairo::set_source_rgba(cr, white);
532                              cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);                              cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
533                              cr->fill();                              cr->fill();
534    
# Line 507  void DimRegionChooser::get_dimregions(co Line 639  void DimRegionChooser::get_dimregions(co
639    
640  void DimRegionChooser::update_after_resize()  void DimRegionChooser::update_after_resize()
641  {  {
642      if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {      const uint8_t upperLimit = resize.pos - 1;
643        gig::Instrument* instr = (gig::Instrument*)region->GetParent();
644    
645          int bitpos = 0;      int bitpos = 0;
646          for (int j = 0 ; j < resize.dimension ; j++) {      for (int j = 0 ; j < resize.dimension ; j++) {
647              bitpos += region->pDimensionDefinitions[j].bits;          bitpos += region->pDimensionDefinitions[j].bits;
648          }      }
649    
650        const int stereobitpos =
651            (modifybothchannels) ? baseBits(gig::dimension_samplechannel, region) : -1;
652    
653        // the velocity dimension must be handled differently than all other
654        // dimension types, because
655        // 1. it is currently the only dimension type which allows different zone
656        //    sizes for different cases
657        // 2. for v2 format VelocityUpperLimit has to be set, DimensionUpperLimits for v3
658        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
659          int mask =          int mask =
660              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
661          int c = maindimregno & mask; // mask away this dimension          int c = maindimregno & mask; // mask away this dimension
# Line 538  void DimRegionChooser::update_after_resi Line 681  void DimRegionChooser::update_after_resi
681              }              }
682          }          }
683    
684          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];          int index = c + (resize.zone << bitpos);
685            gig::DimensionRegion* d = region->pDimensionRegions[index];
686          // update both v2 and v3 values          // update both v2 and v3 values
687          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;          d->DimensionUpperLimits[resize.dimension] = upperLimit;
688          d->VelocityUpperLimit = resize.pos - 1;          d->VelocityUpperLimit = upperLimit;
689            if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
690                gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
691                d->DimensionUpperLimits[resize.dimension] = upperLimit;
692                d->VelocityUpperLimit = upperLimit;
693            }
694    
695            if (modifyalldimregs) {
696                gig::Region* rgn = NULL;
697                for (int key = 0; key < 128; ++key) {
698                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
699                    rgn = instr->GetRegion(key);
700                    if (!modifyallregions && rgn != region) continue; // hack to reduce overall code amount a bit
701                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
702                    if (!dimdef) continue;
703                    if (dimdef->zones != resize.dimensionDef.zones) continue;
704                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
705                    assert(iDim >= 0 && iDim < rgn->Dimensions);
706    
707                    // the dimension layout might be completely different in this
708                    // region, so we have to recalculate bitpos etc for this region
709                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
710                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
711                    const int selection = resize.zone << bitpos;
712    
713                    // primitive and inefficient loop implementation, however due to
714                    // this circumstance the loop code is much simpler, and its lack
715                    // of runtime efficiency should not be notable in practice
716                    for (int idr = 0; idr < 256; ++idr) {
717                        const int index = (idr & stencil) | selection;
718                        assert(index >= 0 && index < 256);
719                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
720                        if (!dr) continue;
721                        dr->DimensionUpperLimits[iDim] = upperLimit;
722                        d->VelocityUpperLimit = upperLimit;
723                    }
724                }
725            } else if (modifyallregions) { // implies modifyalldimregs is false ...
726                // resolve the precise case we need to modify for all other regions
727                DimensionCase dimCase = dimensionCaseOf(d);
728                // apply the velocity upper limit change to that resolved dim case
729                // of all regions ...
730                gig::Region* rgn = NULL;
731                for (int key = 0; key < 128; ++key) {
732                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
733                    rgn = instr->GetRegion(key);
734                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
735                    if (!dimdef) continue;
736                    if (dimdef->zones != resize.dimensionDef.zones) continue;
737                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
738                    assert(iDim >= 0 && iDim < rgn->Dimensions);
739    
740                    std::vector<gig::DimensionRegion*> dimrgns = dimensionRegionsMatching(dimCase, rgn);
741                    for (int i = 0; i < dimrgns.size(); ++i) {
742                        gig::DimensionRegion* dr = dimrgns[i];
743                        dr->DimensionUpperLimits[iDim] = upperLimit;
744                        dr->VelocityUpperLimit = upperLimit;
745                    }
746                }
747            }
748      } else {      } else {
749          for (int i = 0 ; i < region->DimensionRegions ; ) {          for (int i = 0 ; i < region->DimensionRegions ; ) {
   
750              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
751                  // the dimension didn't previously have custom                  // the dimension didn't previously have custom
752                  // limits, so we have to set default limits for                  // limits, so we have to set default limits for
753                  // all the dimension regions                  // all the dimension regions
                 int bitpos = 0;  
                 for (int j = 0 ; j < resize.dimension ; j++) {  
                     bitpos += region->pDimensionDefinitions[j].bits;  
                 }  
754                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
755    
756                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
# Line 561  void DimRegionChooser::update_after_resi Line 758  void DimRegionChooser::update_after_resi
758                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
759                  }                  }
760              }              }
761              gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];              int index = i + (resize.zone << bitpos);
762              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;              gig::DimensionRegion* d = region->pDimensionRegions[index];
763                d->DimensionUpperLimits[resize.dimension] = upperLimit;
764    #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
765                if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
766                    gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
767                    d->DimensionUpperLimits[resize.dimension] = upperLimit;
768                }
769    #endif
770              int bitpos = 0;              int bitpos = 0;
771              int j;              int j;
772              for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
# Line 577  void DimRegionChooser::update_after_resi Line 780  void DimRegionChooser::update_after_resi
780              if (j == region->Dimensions) break;              if (j == region->Dimensions) break;
781              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
782          }          }
783    
784            if (modifyallregions) { // TODO: this code block could be merged with the similar (and more generalized) code block of the velocity dimension above
785                gig::Region* rgn = NULL;
786                for (int key = 0; key < 128; ++key) {
787                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
788                    rgn = instr->GetRegion(key);
789                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
790                    if (!dimdef) continue;
791                    if (dimdef->zones != resize.dimensionDef.zones) continue;
792                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
793                    assert(iDim >= 0 && iDim < rgn->Dimensions);
794    
795                    // the dimension layout might be completely different in this
796                    // region, so we have to recalculate bitpos etc for this region
797                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
798                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
799                    const int selection = resize.zone << bitpos;
800    
801                    // this loop implementation is less efficient than the above's
802                    // loop implementation (which skips unnecessary dimension regions)
803                    // however this code is much simpler, and its lack of runtime
804                    // efficiency should not be notable in practice
805                    for (int idr = 0; idr < 256; ++idr) {
806                        const int index = (idr & stencil) | selection;
807                        assert(index >= 0 && index < 256);
808                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
809                        if (!dr) continue;
810                        dr->DimensionUpperLimits[iDim] = upperLimit;
811                    }
812                }
813            }
814      }      }
815  }  }
816    
# Line 805  bool DimRegionChooser::is_in_resize_zone Line 1039  bool DimRegionChooser::is_in_resize_zone
1039                  if (x <= limitx - 2) break;                  if (x <= limitx - 2) break;
1040                  if (x <= limitx + 2) {                  if (x <= limitx + 2) {
1041                      resize.dimension = dim;                      resize.dimension = dim;
1042                      resize.offset = iZone << bitpos;                      resize.dimensionDef = region->pDimensionDefinitions[dim];
1043                        resize.zone = iZone;
1044                      resize.pos = limit;                      resize.pos = limit;
1045                      resize.min = prev_limit;                      resize.min = prev_limit;
1046    
# Line 891  bool DimRegionChooser::on_focus(Gtk::Dir Line 1126  bool DimRegionChooser::on_focus(Gtk::Dir
1126  void DimRegionChooser::split_dimension_zone() {      void DimRegionChooser::split_dimension_zone() {    
1127      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1128      try {      try {
1129          region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);          if (!modifyallregions) {
1130                region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1131            } else {
1132                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1133                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1134                assert(pMaindimdef != NULL);
1135                // retain structure by value since the original region will be
1136                // modified in the loop below as well
1137                gig::dimension_def_t maindimdef = *pMaindimdef;
1138                std::vector<gig::Region*> ignoredAll;
1139                std::vector<gig::Region*> ignoredMinor;
1140                std::vector<gig::Region*> ignoredCritical;
1141                gig::Region* rgn = NULL;
1142                for (int key = 0; key < 128; ++key) {
1143                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1144                    rgn = instr->GetRegion(key);
1145    
1146                    // ignore all regions which do not exactly match the dimension
1147                    // layout of the selected region where this operation was emitted
1148                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1149                    if (!dimdef) {
1150                        ignoredAll.push_back(rgn);
1151                        ignoredMinor.push_back(rgn);
1152                        continue;
1153                    }
1154                    if (dimdef->zones != maindimdef.zones) {
1155                        ignoredAll.push_back(rgn);
1156                        ignoredCritical.push_back(rgn);
1157                        continue;
1158                    }
1159    
1160                    rgn->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1161                }
1162                if (!ignoredAll.empty()) {
1163                    Glib::ustring txt;
1164                    if (ignoredCritical.empty())
1165                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1166                    else if (ignoredMinor.empty())
1167                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1168                    else
1169                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1170                        ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1171                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1172                    Gtk::MessageDialog msg(txt, false, type);
1173                    msg.run();
1174                }
1175            }
1176      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1177          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1178          msg.run();          msg.run();
# Line 906  void DimRegionChooser::split_dimension_z Line 1187  void DimRegionChooser::split_dimension_z
1187  void DimRegionChooser::delete_dimension_zone() {  void DimRegionChooser::delete_dimension_zone() {
1188      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1189      try {      try {
1190          region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);          if (!modifyallregions) {
1191                region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1192            } else {
1193                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1194                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1195                assert(pMaindimdef != NULL);
1196                // retain structure by value since the original region will be
1197                // modified in the loop below as well
1198                gig::dimension_def_t maindimdef = *pMaindimdef;
1199                std::vector<gig::Region*> ignoredAll;
1200                std::vector<gig::Region*> ignoredMinor;
1201                std::vector<gig::Region*> ignoredCritical;
1202                gig::Region* rgn = NULL;
1203                for (int key = 0; key < 128; ++key) {
1204                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1205                    rgn = instr->GetRegion(key);
1206    
1207                    // ignore all regions which do not exactly match the dimension
1208                    // layout of the selected region where this operation was emitted
1209                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1210                    if (!dimdef) {
1211                        ignoredAll.push_back(rgn);
1212                        ignoredMinor.push_back(rgn);
1213                        continue;
1214                    }
1215                    if (dimdef->zones != maindimdef.zones) {
1216                        ignoredAll.push_back(rgn);
1217                        ignoredCritical.push_back(rgn);
1218                        continue;
1219                    }
1220    
1221                    rgn->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1222                }
1223                if (!ignoredAll.empty()) {
1224                    Glib::ustring txt;
1225                    if (ignoredCritical.empty())
1226                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1227                    else if (ignoredMinor.empty())
1228                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1229                    else
1230                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1231                              ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1232                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1233                    Gtk::MessageDialog msg(txt, false, type);
1234                    msg.run();
1235                }
1236            }
1237      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1238          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1239          msg.run();          msg.run();
# Line 918  void DimRegionChooser::delete_dimension_ Line 1245  void DimRegionChooser::delete_dimension_
1245      refresh_all();      refresh_all();
1246  }  }
1247    
1248    // Cmd key on Mac, Ctrl key on all other OSs
1249    static const guint primaryKeyL =
1250        #if defined(__APPLE__)
1251        GDK_KEY_Meta_L;
1252        #else
1253        GDK_KEY_Control_L;
1254        #endif
1255    
1256    static const guint primaryKeyR =
1257        #if defined(__APPLE__)
1258        GDK_KEY_Meta_R;
1259        #else
1260        GDK_KEY_Control_R;
1261        #endif
1262    
1263  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1264      //printf("key down\n");      //printf("key down 0x%x\n", key->keyval);
1265      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)
1266          multiSelectKeyDown = true;          multiSelectKeyDown = true;
1267        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1268            primaryKeyDown = true;
1269        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1270            shiftKeyDown = true;
1271    
1272        //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
1273        /*if (key->keyval == GDK_KEY_Left)
1274            select_prev_dimzone();
1275        if (key->keyval == GDK_KEY_Right)
1276            select_next_dimzone();
1277        if (key->keyval == GDK_KEY_Up)
1278            select_prev_dimension();
1279        if (key->keyval == GDK_KEY_Down)
1280            select_next_dimension();*/
1281      return false;      return false;
1282  }  }
1283    
1284  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1285      //printf("key up\n");      //printf("key up 0x%x\n", key->keyval);
1286      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)
1287          multiSelectKeyDown = false;          multiSelectKeyDown = false;
1288        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1289            primaryKeyDown = false;
1290        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1291            shiftKeyDown = false;
1292    
1293        if (!has_focus()) return false;
1294    
1295        // avoid conflict with Ctrl+Left and Ctrl+Right accelerators on mainwindow
1296        // (which is supposed to switch between regions)
1297        if (primaryKeyDown) return false;
1298    
1299        // avoid conflict with Alt+Shift+Left and Alt+Shift+Right accelerators on
1300        // mainwindow
1301        if (shiftKeyDown) return false;
1302    
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    
1312      return false;      return false;
1313  }  }
1314    
# Line 949  void DimRegionChooser::resetSelectedZone Line 1329  void DimRegionChooser::resetSelectedZone
1329      gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];      gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1330    
1331      bool isValidZone;      bool isValidZone;
1332      this->maindimcase = caseOfDimRegion(dimrgn, &isValidZone);      this->maindimcase = dimensionCaseOf(dimrgn);
     if (!isValidZone) {  
         queue_draw(); // redraw required parts  
         return;  
     }  
1333    
1334      for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();      for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1335           it != this->maindimcase.end(); ++it)           it != this->maindimcase.end(); ++it)
# Line 984  bool DimRegionChooser::select_dimregion( Line 1360  bool DimRegionChooser::select_dimregion(
1360      return false; //.selection failed      return false; //.selection failed
1361  }  }
1362    
1363    void DimRegionChooser::select_next_dimzone(bool add) {
1364        select_dimzone_by_dir(+1, add);
1365    }
1366    
1367    void DimRegionChooser::select_prev_dimzone(bool add) {
1368        select_dimzone_by_dir(-1, add);
1369    }
1370    
1371    void DimRegionChooser::select_dimzone_by_dir(int dir, bool add) {
1372        if (!region) return;
1373        if (!region->Dimensions) return;
1374        if (focus_line < 0) focus_line = 0;
1375        if (focus_line >= region->Dimensions) focus_line = region->Dimensions - 1;
1376    
1377        maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1378        if (maindimtype == gig::dimension_none) {
1379            printf("maindimtype -> none\n");
1380            return;
1381        }
1382    
1383        if (maindimcase.empty()) {
1384            maindimcase = dimensionCaseOf(region->pDimensionRegions[maindimregno]);
1385            if (maindimcase.empty()) {
1386                printf("caseOfDimregion(%d) -> empty\n", maindimregno);
1387                return;
1388            }
1389        }
1390    
1391        int z = (dir > 0) ? maindimcase[maindimtype] + 1 : maindimcase[maindimtype] - 1;
1392        if (z < 0) z = 0;
1393        if (z >= region->pDimensionDefinitions[focus_line].zones)
1394            z = region->pDimensionDefinitions[focus_line].zones - 1;
1395    
1396        maindimcase[maindimtype] = z;
1397    
1398        ::gig::DimensionRegion* dr = dimensionRegionMatching(maindimcase, region);
1399        if (!dr) {
1400            printf("select_dimzone_by_dir(%d) -> !dr\n", dir);
1401            return;
1402        }
1403    
1404        maindimregno = getDimensionRegionIndex(dr);
1405    
1406        if (!add) {
1407            // reset selected dimregion zones
1408            dimzones.clear();
1409        }
1410        for (DimensionCase::const_iterator it = maindimcase.begin();
1411             it != maindimcase.end(); ++it)
1412        {
1413            dimzones[it->first].insert(it->second);
1414        }
1415    
1416        dimregion_selected();
1417    
1418        // disabled: would overwrite dimregno with wrong value
1419        //refresh_all();
1420        // so requesting just a raw repaint instead:
1421        queue_draw();
1422    }
1423    
1424    void DimRegionChooser::select_next_dimension() {
1425        if (!region) return;
1426        focus_line++;
1427        if (focus_line >= region->Dimensions)
1428            focus_line = region->Dimensions - 1;
1429        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1430        queue_draw();
1431    }
1432    
1433    void DimRegionChooser::select_prev_dimension() {
1434        if (!region) return;
1435        focus_line--;
1436        if (focus_line < 0)
1437            focus_line = 0;
1438        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1439        queue_draw();
1440    }
1441    
1442  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {
1443      if (!region) return NULL;      if (!region) return NULL;
1444      return region->pDimensionRegions[maindimregno];      return region->pDimensionRegions[maindimregno];

Legend:
Removed from v.2845  
changed lines
  Added in v.3158

  ViewVC Help
Powered by ViewVC