/[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 3123 by schoenebeck, Tue Apr 25 20:45:54 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2014 Andreas Persson   * Copyright (C) 2006-2017 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
20    #include <gtkmm/box.h>
21  #include "dimregionchooser.h"  #include "dimregionchooser.h"
22  #include <cairomm/context.h>  #include <cairomm/context.h>
23  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
24  #include <gdkmm/general.h>  #include <gdkmm/general.h>
25  #include <glibmm/stringutils.h>  #include <glibmm/stringutils.h>
 #include <gtkmm/stock.h>  
26  #include <glibmm/ustring.h>  #include <glibmm/ustring.h>
27  #include <gtkmm/messagedialog.h>  #include <gtkmm/messagedialog.h>
28    #include <assert.h>
29    
30  #include "global.h"  #include "global.h"
31    
32  // taken from gdk/gdkkeysyms.h  //TODO: this function and dimensionCaseOf() from global.h are duplicates, eliminate either one of them!
33  // (define on demand, to avoid unnecessary dev lib package build dependency)  static DimensionCase caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
34  #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;  
35      if (!dr) {      if (!dr) {
36          *isValidZone = false;          *isValidZone = false;
37          return dimCase;          return dimCase;
# Line 56  static std::map<gig::dimension_t,int> ca Line 49  static std::map<gig::dimension_t,int> ca
49      if (drIndex == 256) {      if (drIndex == 256) {
50          fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");          fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");
51          *isValidZone = false;          *isValidZone = false;
52          return std::map<gig::dimension_t,int>();          return DimensionCase();
53      }      }
54    
55      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 60  static std::map<gig::dimension_t,int> ca
60          // there are also DimensionRegion objects of unused zones, skip them          // there are also DimensionRegion objects of unused zones, skip them
61          if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {          if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {
62              *isValidZone = false;              *isValidZone = false;
63              return std::map<gig::dimension_t,int>();              return DimensionCase();
64          }          }
65      }      }
66    
# Line 83  DimRegionChooser::DimRegionChooser(Gtk:: Line 76  DimRegionChooser::DimRegionChooser(Gtk::
76      instrument = 0;      instrument = 0;
77      region = 0;      region = 0;
78      maindimregno = -1;      maindimregno = -1;
79        maindimtype = gig::dimension_none; // initialize with invalid dimension type
80      focus_line = 0;      focus_line = 0;
81      resize.active = false;      resize.active = false;
82      cursor_is_resize = false;      cursor_is_resize = false;
83      h = 20;      h = 24;
84      multiSelectKeyDown = false;      multiSelectKeyDown = false;
85        modifybothchannels = modifyalldimregs = modifybothchannels = false;
86      set_can_focus();      set_can_focus();
87    
88        const Glib::ustring txtUseCheckBoxAllRegions =
89            _("Use checkbox 'all regions' to control whether this should apply to all regions.");
90    
91      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
92        actionSplitDimZone = Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone"), txtUseCheckBoxAllRegions);
93        actionSplitDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
94      actionGroup->add(      actionGroup->add(
95          Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone")),          actionSplitDimZone,
96          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
97      );      );
98        actionDeleteDimZone = Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone"), txtUseCheckBoxAllRegions);
99        actionDeleteDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
100      actionGroup->add(      actionGroup->add(
101          Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone")),          actionDeleteDimZone,
102          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)          sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
103      );      );
104    
# Line 141  DimRegionChooser::~DimRegionChooser() Line 143  DimRegionChooser::~DimRegionChooser()
143  {  {
144  }  }
145    
146    void DimRegionChooser::setModifyBothChannels(bool b) {
147        modifybothchannels = b;
148    }
149    
150    void DimRegionChooser::setModifyAllDimensionRegions(bool b) {
151        modifyalldimregs = b;
152    }
153    
154    void DimRegionChooser::setModifyAllRegions(bool b) {
155        modifyallregions = b;
156    
157        actionDeleteDimZone->set_label(b ? _("Delete Dimension Zone [ALL REGIONS]") : _("Delete Dimension Zone"));
158        actionSplitDimZone->set_label(b ? _("Split Dimensions Zone [ALL REGIONS]") : _("Split Dimensions Zone"));
159    }
160    
161  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
162  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
163  {  {
# Line 273  bool DimRegionChooser::on_draw(const Cai Line 290  bool DimRegionChooser::on_draw(const Cai
290                  // draw focus rectangle around dimension's label and zones                  // draw focus rectangle around dimension's label and zones
291                  if (has_focus() && focus_line == i) {                  if (has_focus() && focus_line == i) {
292  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
293                      Gdk::Rectangle farea(0, y, 150, 20);                      Gdk::Rectangle farea(0, y, 150, h);
294                      get_style()->paint_focus(get_window(), get_state(), farea,                      get_style()->paint_focus(get_window(), get_state(), farea,
295                                               *this, "",                                               *this, "",
296                                               0, y, label_width, 20);                                               0, y, label_width, h);
297  #else  #else
298                      get_style_context()->render_focus(cr,                      get_style_context()->render_focus(cr,
299                                                        0, y, label_width, 20);                                                        0, y, label_width, h);
300  #endif  #endif
301                  }                  }
302    
# Line 318  bool DimRegionChooser::on_draw(const Cai Line 335  bool DimRegionChooser::on_draw(const Cai
335                      cr->move_to(label_width + 0.5, y + 1);                      cr->move_to(label_width + 0.5, y + 1);
336                      cr->line_to(label_width + 0.5, y + h - 1);                      cr->line_to(label_width + 0.5, y + h - 1);
337                      int prevX = label_width;                      int prevX = label_width;
338                      int prevUpperLimit = 0;                      int prevUpperLimit = -1;
339    
340                      for (int j = 0 ; j < nbZones ; j++) {                      for (int j = 0 ; j < nbZones ; j++) {
341                          // draw dimension zone's borders for custom splits                          // draw dimension zone's borders for custom splits
# Line 346  bool DimRegionChooser::on_draw(const Cai Line 363  bool DimRegionChooser::on_draw(const Cai
363                          // as numeric value to the user                          // as numeric value to the user
364                          {                          {
365                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
366                              layout->set_text(Glib::Ascii::dtostr(prevUpperLimit));                              layout->set_text(Glib::Ascii::dtostr(prevUpperLimit+1));
367                              Gdk::Cairo::set_source_rgba(cr, black);                              Gdk::Cairo::set_source_rgba(cr, black);
                             Pango::Rectangle rect = layout->get_logical_extents();  
368                              // get the text dimensions                              // get the text dimensions
369                              int text_width, text_height;                              int text_width, text_height;
370                              layout->get_pixel_size(text_width, text_height);                              layout->get_pixel_size(text_width, text_height);
371                              // move text to the left end of the dimension zone                              // move text to the left end of the dimension zone
372                              cr->move_to(prevX + 3, y + 1);                              cr->move_to(prevX + 3, y + (h - text_height) / 2);
373  #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
374                              pango_cairo_show_layout(cr->cobj(), layout->gobj());                              pango_cairo_show_layout(cr->cobj(), layout->gobj());
375  #else  #else
# Line 366  bool DimRegionChooser::on_draw(const Cai Line 382  bool DimRegionChooser::on_draw(const Cai
382                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                              Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
383                              layout->set_text(Glib::Ascii::dtostr(upperLimit));                              layout->set_text(Glib::Ascii::dtostr(upperLimit));
384                              Gdk::Cairo::set_source_rgba(cr, black);                              Gdk::Cairo::set_source_rgba(cr, black);
                             Pango::Rectangle rect = layout->get_logical_extents();  
385                              // get the text dimensions                              // get the text dimensions
386                              int text_width, text_height;                              int text_width, text_height;
387                              layout->get_pixel_size(text_width, text_height);                              layout->get_pixel_size(text_width, text_height);
388                              // move text to the left end of the dimension zone                              // move text to the left end of the dimension zone
389                              cr->move_to(x - 3 - text_width, y + 1);                              cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
390  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
391                              pango_cairo_show_layout(cr->cobj(), layout->gobj());                              pango_cairo_show_layout(cr->cobj(), layout->gobj());
392  #else  #else
# Line 408  bool DimRegionChooser::on_draw(const Cai Line 423  bool DimRegionChooser::on_draw(const Cai
423                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
424                                  layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));                                  layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));
425                                  Gdk::Cairo::set_source_rgba(cr, black);                                  Gdk::Cairo::set_source_rgba(cr, black);
                                 Pango::Rectangle rect = layout->get_logical_extents();  
426                                  // get the text dimensions                                  // get the text dimensions
427                                  int text_width, text_height;                                  int text_width, text_height;
428                                  layout->get_pixel_size(text_width, text_height);                                  layout->get_pixel_size(text_width, text_height);
429                                  // move text to the left end of the dimension zone                                  // move text to the left end of the dimension zone
430                                  cr->move_to(prevX + 3, y + 1);                                  cr->move_to(prevX + 3, y + (h - text_height) / 2);
431  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
432                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
433  #else  #else
# Line 426  bool DimRegionChooser::on_draw(const Cai Line 440  bool DimRegionChooser::on_draw(const Cai
440                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
441                                  layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));                                  layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));
442                                  Gdk::Cairo::set_source_rgba(cr, black);                                  Gdk::Cairo::set_source_rgba(cr, black);
                                 Pango::Rectangle rect = layout->get_logical_extents();  
443                                  // get the text dimensions                                  // get the text dimensions
444                                  int text_width, text_height;                                  int text_width, text_height;
445                                  layout->get_pixel_size(text_width, text_height);                                  layout->get_pixel_size(text_width, text_height);
446                                  // move text to the left end of the dimension zone                                  // move text to the left end of the dimension zone
447                                  cr->move_to(x - 3 - text_width, y + 1);                                  cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
448  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
449                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
450  #else  #else
# Line 469  void DimRegionChooser::set_region(gig::R Line 482  void DimRegionChooser::set_region(gig::R
482          }          }
483      }      }
484      dimregion_selected();      dimregion_selected();
485      set_size_request(800, region ? nbDimensions * 20 : 0);      set_size_request(800, region ? nbDimensions * h : 0);
486    
487      labels_changed = true;      labels_changed = true;
488      queue_resize();      queue_resize();
# Line 511  void DimRegionChooser::get_dimregions(co Line 524  void DimRegionChooser::get_dimregions(co
524    
525  void DimRegionChooser::update_after_resize()  void DimRegionChooser::update_after_resize()
526  {  {
527      if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {      const uint8_t upperLimit = resize.pos - 1;
528        gig::Instrument* instr = (gig::Instrument*)region->GetParent();
529    
530          int bitpos = 0;      int bitpos = 0;
531          for (int j = 0 ; j < resize.dimension ; j++) {      for (int j = 0 ; j < resize.dimension ; j++) {
532              bitpos += region->pDimensionDefinitions[j].bits;          bitpos += region->pDimensionDefinitions[j].bits;
533          }      }
534    
535        const int stereobitpos =
536            (modifybothchannels) ? baseBits(gig::dimension_samplechannel, region) : -1;
537    
538        // the velocity dimension must be handled differently than all other
539        // dimension types, because
540        // 1. it is currently the only dimension type which allows different zone
541        //    sizes for different cases
542        // 2. for v2 format VelocityUpperLimit has to be set, DimensionUpperLimits for v3
543        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
544          int mask =          int mask =
545              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
546          int c = maindimregno & mask; // mask away this dimension          int c = maindimregno & mask; // mask away this dimension
# Line 542  void DimRegionChooser::update_after_resi Line 566  void DimRegionChooser::update_after_resi
566              }              }
567          }          }
568    
569          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];          int index = c + (resize.zone << bitpos);
570            gig::DimensionRegion* d = region->pDimensionRegions[index];
571          // update both v2 and v3 values          // update both v2 and v3 values
572          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;          d->DimensionUpperLimits[resize.dimension] = upperLimit;
573          d->VelocityUpperLimit = resize.pos - 1;          d->VelocityUpperLimit = upperLimit;
574            if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
575                gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
576                d->DimensionUpperLimits[resize.dimension] = upperLimit;
577                d->VelocityUpperLimit = upperLimit;
578            }
579    
580            if (modifyalldimregs) {
581                gig::Region* rgn = NULL;
582                for (int key = 0; key < 128; ++key) {
583                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
584                    rgn = instr->GetRegion(key);
585                    if (!modifyallregions && rgn != region) continue; // hack to reduce overall code amount a bit
586                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
587                    if (!dimdef) continue;
588                    if (dimdef->zones != resize.dimensionDef.zones) continue;
589                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
590                    assert(iDim >= 0 && iDim < rgn->Dimensions);
591    
592                    // the dimension layout might be completely different in this
593                    // region, so we have to recalculate bitpos etc for this region
594                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
595                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
596                    const int selection = resize.zone << bitpos;
597    
598                    // primitive and inefficient loop implementation, however due to
599                    // this circumstance the loop code is much simpler, and its lack
600                    // of runtime efficiency should not be notable in practice
601                    for (int idr = 0; idr < 256; ++idr) {
602                        const int index = (idr & stencil) | selection;
603                        assert(index >= 0 && index < 256);
604                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
605                        if (!dr) continue;
606                        dr->DimensionUpperLimits[iDim] = upperLimit;
607                        d->VelocityUpperLimit = upperLimit;
608                    }
609                }
610            } else if (modifyallregions) { // implies modifyalldimregs is false ...
611                // resolve the precise case we need to modify for all other regions
612                DimensionCase dimCase = dimensionCaseOf(d);
613                // apply the velocity upper limit change to that resolved dim case
614                // of all regions ...
615                gig::Region* rgn = NULL;
616                for (int key = 0; key < 128; ++key) {
617                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
618                    rgn = instr->GetRegion(key);
619                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
620                    if (!dimdef) continue;
621                    if (dimdef->zones != resize.dimensionDef.zones) continue;
622                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
623                    assert(iDim >= 0 && iDim < rgn->Dimensions);
624    
625                    std::vector<gig::DimensionRegion*> dimrgns = dimensionRegionsMatching(dimCase, rgn);
626                    for (int i = 0; i < dimrgns.size(); ++i) {
627                        gig::DimensionRegion* dr = dimrgns[i];
628                        dr->DimensionUpperLimits[iDim] = upperLimit;
629                        dr->VelocityUpperLimit = upperLimit;
630                    }
631                }
632            }
633      } else {      } else {
634          for (int i = 0 ; i < region->DimensionRegions ; ) {          for (int i = 0 ; i < region->DimensionRegions ; ) {
   
635              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
636                  // the dimension didn't previously have custom                  // the dimension didn't previously have custom
637                  // limits, so we have to set default limits for                  // limits, so we have to set default limits for
638                  // all the dimension regions                  // all the dimension regions
                 int bitpos = 0;  
                 for (int j = 0 ; j < resize.dimension ; j++) {  
                     bitpos += region->pDimensionDefinitions[j].bits;  
                 }  
639                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
640    
641                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
# Line 565  void DimRegionChooser::update_after_resi Line 643  void DimRegionChooser::update_after_resi
643                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
644                  }                  }
645              }              }
646              gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];              int index = i + (resize.zone << bitpos);
647              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;              gig::DimensionRegion* d = region->pDimensionRegions[index];
648                d->DimensionUpperLimits[resize.dimension] = upperLimit;
649    #if 0       // the following is currently not necessary, because ATM the gig format uses for all dimension types except of the veleocity dimension the same zone sizes for all cases
650                if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
651                    gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
652                    d->DimensionUpperLimits[resize.dimension] = upperLimit;
653                }
654    #endif
655              int bitpos = 0;              int bitpos = 0;
656              int j;              int j;
657              for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
# Line 581  void DimRegionChooser::update_after_resi Line 665  void DimRegionChooser::update_after_resi
665              if (j == region->Dimensions) break;              if (j == region->Dimensions) break;
666              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
667          }          }
668    
669            if (modifyallregions) { // TODO: this code block could be merged with the similar (and more generalized) code block of the velocity dimension above
670                gig::Region* rgn = NULL;
671                for (int key = 0; key < 128; ++key) {
672                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
673                    rgn = instr->GetRegion(key);
674                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
675                    if (!dimdef) continue;
676                    if (dimdef->zones != resize.dimensionDef.zones) continue;
677                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
678                    assert(iDim >= 0 && iDim < rgn->Dimensions);
679    
680                    // the dimension layout might be completely different in this
681                    // region, so we have to recalculate bitpos etc for this region
682                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
683                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
684                    const int selection = resize.zone << bitpos;
685    
686                    // this loop implementation is less efficient than the above's
687                    // loop implementation (which skips unnecessary dimension regions)
688                    // however this code is much simpler, and its lack of runtime
689                    // efficiency should not be notable in practice
690                    for (int idr = 0; idr < 256; ++idr) {
691                        const int index = (idr & stencil) | selection;
692                        assert(index >= 0 && index < 256);
693                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
694                        if (!dr) continue;
695                        dr->DimensionUpperLimits[iDim] = upperLimit;
696                    }
697                }
698            }
699      }      }
700  }  }
701    
# Line 809  bool DimRegionChooser::is_in_resize_zone Line 924  bool DimRegionChooser::is_in_resize_zone
924                  if (x <= limitx - 2) break;                  if (x <= limitx - 2) break;
925                  if (x <= limitx + 2) {                  if (x <= limitx + 2) {
926                      resize.dimension = dim;                      resize.dimension = dim;
927                      resize.offset = iZone << bitpos;                      resize.dimensionDef = region->pDimensionDefinitions[dim];
928                        resize.zone = iZone;
929                      resize.pos = limit;                      resize.pos = limit;
930                      resize.min = prev_limit;                      resize.min = prev_limit;
931    
# Line 850  sigc::signal<void>& DimRegionChooser::si Line 966  sigc::signal<void>& DimRegionChooser::si
966    
967  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
968  {  {
969      // TODO: kolla att region finns osv, dvs att det går att sätta      // TODO: check that region exists etc, that is, that it's possible
970      // fokus.      // to set focus
971      if (direction == Gtk::DIR_TAB_FORWARD ||      if (direction == Gtk::DIR_TAB_FORWARD ||
972          direction == Gtk::DIR_DOWN) {          direction == Gtk::DIR_DOWN) {
973          if (!has_focus()) {          if (!has_focus()) {
# Line 883  bool DimRegionChooser::on_focus(Gtk::Dir Line 999  bool DimRegionChooser::on_focus(Gtk::Dir
999              }              }
1000          }          }
1001      } else if (!has_focus()) {      } else if (!has_focus()) {
1002          // TODO: kolla att focus_line finns!          // TODO: check that focus_line exists
1003          grab_focus();          grab_focus();
1004          return true;          return true;
1005      } else {      } else {
1006          // TODO: öka eller minska värde!          // TODO: increase or decrease value
1007      }      }
1008        return false;
1009  }  }
1010    
1011  void DimRegionChooser::split_dimension_zone() {      void DimRegionChooser::split_dimension_zone() {    
1012      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);      printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1013      try {      try {
1014          region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);          if (!modifyallregions) {
1015                region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1016            } else {
1017                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1018                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1019                assert(pMaindimdef != NULL);
1020                // retain structure by value since the original region will be
1021                // modified in the loop below as well
1022                gig::dimension_def_t maindimdef = *pMaindimdef;
1023                std::vector<gig::Region*> ignoredAll;
1024                std::vector<gig::Region*> ignoredMinor;
1025                std::vector<gig::Region*> ignoredCritical;
1026                gig::Region* rgn = NULL;
1027                for (int key = 0; key < 128; ++key) {
1028                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1029                    rgn = instr->GetRegion(key);
1030    
1031                    // ignore all regions which do not exactly match the dimension
1032                    // layout of the selected region where this operation was emitted
1033                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1034                    if (!dimdef) {
1035                        ignoredAll.push_back(rgn);
1036                        ignoredMinor.push_back(rgn);
1037                        continue;
1038                    }
1039                    if (dimdef->zones != maindimdef.zones) {
1040                        ignoredAll.push_back(rgn);
1041                        ignoredCritical.push_back(rgn);
1042                        continue;
1043                    }
1044    
1045                    rgn->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1046                }
1047                if (!ignoredAll.empty()) {
1048                    Glib::ustring txt;
1049                    if (ignoredCritical.empty())
1050                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1051                    else if (ignoredMinor.empty())
1052                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1053                    else
1054                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1055                        ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1056                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1057                    Gtk::MessageDialog msg(txt, false, type);
1058                    msg.run();
1059                }
1060            }
1061      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1062          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1063          msg.run();          msg.run();
# Line 909  void DimRegionChooser::split_dimension_z Line 1072  void DimRegionChooser::split_dimension_z
1072  void DimRegionChooser::delete_dimension_zone() {  void DimRegionChooser::delete_dimension_zone() {
1073      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);      printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1074      try {      try {
1075          region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);          if (!modifyallregions) {
1076                region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1077            } else {
1078                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1079                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1080                assert(pMaindimdef != NULL);
1081                // retain structure by value since the original region will be
1082                // modified in the loop below as well
1083                gig::dimension_def_t maindimdef = *pMaindimdef;
1084                std::vector<gig::Region*> ignoredAll;
1085                std::vector<gig::Region*> ignoredMinor;
1086                std::vector<gig::Region*> ignoredCritical;
1087                gig::Region* rgn = NULL;
1088                for (int key = 0; key < 128; ++key) {
1089                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1090                    rgn = instr->GetRegion(key);
1091    
1092                    // ignore all regions which do not exactly match the dimension
1093                    // layout of the selected region where this operation was emitted
1094                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1095                    if (!dimdef) {
1096                        ignoredAll.push_back(rgn);
1097                        ignoredMinor.push_back(rgn);
1098                        continue;
1099                    }
1100                    if (dimdef->zones != maindimdef.zones) {
1101                        ignoredAll.push_back(rgn);
1102                        ignoredCritical.push_back(rgn);
1103                        continue;
1104                    }
1105    
1106                    rgn->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1107                }
1108                if (!ignoredAll.empty()) {
1109                    Glib::ustring txt;
1110                    if (ignoredCritical.empty())
1111                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1112                    else if (ignoredMinor.empty())
1113                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1114                    else
1115                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1116                              ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1117                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1118                    Gtk::MessageDialog msg(txt, false, type);
1119                    msg.run();
1120                }
1121            }
1122      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
1123          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1124          msg.run();          msg.run();
# Line 922  void DimRegionChooser::delete_dimension_ Line 1131  void DimRegionChooser::delete_dimension_
1131  }  }
1132    
1133  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1134      //printf("key down\n");      //printf("key down 0x%x\n", key->keyval);
1135      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)
1136          multiSelectKeyDown = true;          multiSelectKeyDown = true;
1137        //FIXME: hmm, for some reason GDKMM does not fire arrow key down events, so we are doing those handlers in the key up handler instead for now
1138        /*if (key->keyval == GDK_KEY_Left)
1139            select_prev_dimzone();
1140        if (key->keyval == GDK_KEY_Right)
1141            select_next_dimzone();
1142        if (key->keyval == GDK_KEY_Up)
1143            select_prev_dimension();
1144        if (key->keyval == GDK_KEY_Down)
1145            select_next_dimension();*/
1146        return false;
1147  }  }
1148    
1149  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1150      //printf("key up\n");      //printf("key up 0x%x\n", key->keyval);
1151      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)
1152          multiSelectKeyDown = false;          multiSelectKeyDown = false;
1153    
1154        if (!has_focus()) return false;
1155    
1156        if (key->keyval == GDK_KEY_Left)
1157            select_prev_dimzone();
1158        if (key->keyval == GDK_KEY_Right)
1159            select_next_dimzone();
1160        if (key->keyval == GDK_KEY_Up)
1161            select_prev_dimension();
1162        if (key->keyval == GDK_KEY_Down)
1163            select_next_dimension();
1164    
1165        return false;
1166    }
1167    
1168    void DimRegionChooser::resetSelectedZones() {
1169        this->dimzones.clear();
1170        if (!region) {
1171            queue_draw(); // redraw required parts
1172            return;
1173        }
1174        if (maindimregno < 0 || maindimregno >= region->DimensionRegions) {
1175            queue_draw(); // redraw required parts
1176            return;
1177        }
1178        if (!region->pDimensionRegions[maindimregno]) {
1179            queue_draw(); // redraw required parts
1180            return;
1181        }
1182        gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1183    
1184        bool isValidZone;
1185        this->maindimcase = dimensionCaseOf(dimrgn);
1186    
1187        for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1188             it != this->maindimcase.end(); ++it)
1189        {
1190            this->dimzones[it->first].insert(it->second);
1191        }
1192    
1193        // redraw required parts
1194        queue_draw();
1195    }
1196    
1197    bool DimRegionChooser::select_dimregion(gig::DimensionRegion* dimrgn) {
1198        if (!region) return false; //.selection failed
1199    
1200        for (int dr = 0; dr < region->DimensionRegions && region->pDimensionRegions[dr]; ++dr) {
1201            if (region->pDimensionRegions[dr] == dimrgn) {
1202                // reset dim region zone selection to the requested specific dim region case
1203                maindimregno = dr;
1204                resetSelectedZones();
1205    
1206                // emit signal that dimregion selection has changed, for external entities
1207                dimregion_selected();
1208    
1209                return true; // selection success
1210            }
1211        }
1212    
1213        return false; //.selection failed
1214    }
1215    
1216    void DimRegionChooser::select_next_dimzone() {
1217        select_dimzone_by_dir(+1);
1218    }
1219    
1220    void DimRegionChooser::select_prev_dimzone() {
1221        select_dimzone_by_dir(-1);
1222    }
1223    
1224    void DimRegionChooser::select_dimzone_by_dir(int dir) {
1225        if (!region) return;
1226        if (!region->Dimensions) return;
1227        if (focus_line < 0) focus_line = 0;
1228        if (focus_line >= region->Dimensions) focus_line = region->Dimensions - 1;
1229    
1230        maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1231        if (maindimtype == gig::dimension_none) {
1232            printf("maindimtype -> none\n");
1233            return;
1234        }
1235    
1236        if (maindimcase.empty()) {
1237            maindimcase = dimensionCaseOf(region->pDimensionRegions[maindimregno]);
1238            if (maindimcase.empty()) {
1239                printf("caseOfDimregion(%d) -> empty\n", maindimregno);
1240                return;
1241            }
1242        }
1243    
1244        int z = (dir > 0) ? maindimcase[maindimtype] + 1 : maindimcase[maindimtype] - 1;
1245        if (z < 0) z = 0;
1246        if (z >= region->pDimensionDefinitions[focus_line].zones)
1247            z = region->pDimensionDefinitions[focus_line].zones - 1;
1248    
1249        maindimcase[maindimtype] = z;
1250    
1251        ::gig::DimensionRegion* dr = dimensionRegionMatching(maindimcase, region);
1252        if (!dr) {
1253            printf("select_dimzone_by_dir(%d) -> !dr\n", dir);
1254            return;
1255        }
1256    
1257        maindimregno = getDimensionRegionIndex(dr);
1258    
1259        // reset selected dimregion zones
1260        dimzones.clear();
1261        for (DimensionCase::const_iterator it = maindimcase.begin();
1262             it != maindimcase.end(); ++it)
1263        {
1264            dimzones[it->first].insert(it->second);
1265        }
1266    
1267        dimregion_selected();
1268    
1269        // disabled: would overwrite dimregno with wrong value
1270        //refresh_all();
1271        // so requesting just a raw repaint instead:
1272        queue_draw();
1273    }
1274    
1275    void DimRegionChooser::select_next_dimension() {
1276        if (!region) return;
1277        focus_line++;
1278        if (focus_line >= region->Dimensions)
1279            focus_line = region->Dimensions - 1;
1280        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1281        queue_draw();
1282    }
1283    
1284    void DimRegionChooser::select_prev_dimension() {
1285        if (!region) return;
1286        focus_line--;
1287        if (focus_line < 0)
1288            focus_line = 0;
1289        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1290        queue_draw();
1291  }  }
1292    
1293  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {

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

  ViewVC Help
Powered by ViewVC