/[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 2246 by persson, Fri Aug 19 10:55:41 2011 UTC revision 3364 by schoenebeck, Tue Nov 14 18:07:25 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2011 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 "compat.h"
22    #include <gtkmm/box.h>
23  #include "dimregionchooser.h"  #include "dimregionchooser.h"
24  #include <cairomm/context.h>  #include <cairomm/context.h>
25    #include <cairomm/surface.h>
26  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
27  #include <gdkmm/general.h>  #include <gdkmm/general.h>
28    #if HAS_GDKMM_SEAT
29    # include <gdkmm/seat.h>
30    #endif
31    #include <glibmm/stringutils.h>
32    #if HAS_GTKMM_STOCK
33    # include <gtkmm/stock.h>
34    #endif
35    #include <glibmm/ustring.h>
36    #include <gtkmm/messagedialog.h>
37    #include <assert.h>
38    
39    #include "gfx/builtinpix.h"
40    
41    //TODO: this function and dimensionCaseOf() from global.h are duplicates, eliminate either one of them!
42    static DimensionCase caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
43        DimensionCase dimCase;
44        if (!dr) {
45            *isValidZone = false;
46            return dimCase;
47        }
48    
49  #include "global.h"      gig::Region* rgn = (gig::Region*) dr->GetParent();
50    
51        // find the dimension region index of the passed dimension region
52        int drIndex;
53        for (drIndex = 0; drIndex < 256; ++drIndex)
54            if (rgn->pDimensionRegions[drIndex] == dr)
55                break;
56    
57        // not found in region, something's horribly wrong
58        if (drIndex == 256) {
59            fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");
60            *isValidZone = false;
61            return DimensionCase();
62        }
63    
64  DimRegionChooser::DimRegionChooser() :      for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {
65      red("#8070ff"),          const int bits = rgn->pDimensionDefinitions[d].bits;
66            dimCase[rgn->pDimensionDefinitions[d].dimension] =
67                (drIndex >> baseBits) & ((1 << bits) - 1);
68            baseBits += bits;
69            // there are also DimensionRegion objects of unused zones, skip them
70            if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {
71                *isValidZone = false;
72                return DimensionCase();
73            }
74        }
75    
76        *isValidZone = true;
77        return dimCase;
78    }
79    
80    DimRegionChooser::DimRegionChooser(Gtk::Window& window) :
81        red("#ff476e"),
82        blue("#4796ff"),
83      black("black"),      black("black"),
84      white("white")      white("white")
85  {  {
86        // make sure blue hatched pattern pixmap is loaded
87        loadBuiltInPix();
88    
89        // create blue hatched pattern 1
90        {
91            const int width = blueHatchedPattern->get_width();
92            const int height = blueHatchedPattern->get_height();
93            const int stride = blueHatchedPattern->get_rowstride();
94    
95            // manually convert from RGBA to ARGB
96            this->blueHatchedPatternARGB = blueHatchedPattern->copy();
97            const int pixelSize = stride / width;
98            const int totalPixels = width * height;
99            assert(pixelSize == 4);
100            unsigned char* ptr = this->blueHatchedPatternARGB->get_pixels();
101            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
102                const unsigned char r = ptr[0];
103                const unsigned char g = ptr[1];
104                const unsigned char b = ptr[2];
105                const unsigned char a = ptr[3];
106                ptr[0] = b;
107                ptr[1] = g;
108                ptr[2] = r;
109                ptr[3] = a;
110            }
111    
112            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
113    #if HAS_CAIROMM_CPP11_ENUMS
114                this->blueHatchedPatternARGB->get_pixels(), Cairo::Surface::Format::ARGB32, width, height, stride
115    #else
116                this->blueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
117    #endif
118            );
119            this->blueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
120    #if HAS_CAIROMM_CPP11_ENUMS
121            this->blueHatchedSurfacePattern->set_extend(Cairo::Pattern::Extend::REPEAT);
122    #else
123            this->blueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
124    #endif
125        }
126    
127        // create blue hatched pattern 2
128        {
129            const int width = blueHatchedPattern2->get_width();
130            const int height = blueHatchedPattern2->get_height();
131            const int stride = blueHatchedPattern2->get_rowstride();
132    
133            // manually convert from RGBA to ARGB
134            this->blueHatchedPattern2ARGB = blueHatchedPattern2->copy();
135            const int pixelSize = stride / width;
136            const int totalPixels = width * height;
137            assert(pixelSize == 4);
138            unsigned char* ptr = this->blueHatchedPattern2ARGB->get_pixels();
139            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
140                const unsigned char r = ptr[0];
141                const unsigned char g = ptr[1];
142                const unsigned char b = ptr[2];
143                const unsigned char a = ptr[3];
144                ptr[0] = b;
145                ptr[1] = g;
146                ptr[2] = r;
147                ptr[3] = a;
148            }
149    
150            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
151    #if HAS_CAIROMM_CPP11_ENUMS
152                this->blueHatchedPattern2ARGB->get_pixels(), Cairo::Surface::Format::ARGB32, width, height, stride
153    #else
154                this->blueHatchedPattern2ARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
155    #endif
156            );
157            this->blueHatchedSurfacePattern2 = Cairo::SurfacePattern::create(imageSurface);
158    #if HAS_CAIROMM_CPP11_ENUMS
159            this->blueHatchedSurfacePattern2->set_extend(Cairo::Pattern::Extend::REPEAT);
160    #else
161            this->blueHatchedSurfacePattern2->set_extend(Cairo::EXTEND_REPEAT);
162    #endif
163        }
164    
165        // create gray blue hatched pattern
166        {
167            const int width = grayBlueHatchedPattern->get_width();
168            const int height = grayBlueHatchedPattern->get_height();
169            const int stride = grayBlueHatchedPattern->get_rowstride();
170    
171            // manually convert from RGBA to ARGB
172            this->grayBlueHatchedPatternARGB = grayBlueHatchedPattern->copy();
173            const int pixelSize = stride / width;
174            const int totalPixels = width * height;
175            assert(pixelSize == 4);
176            unsigned char* ptr = this->grayBlueHatchedPatternARGB->get_pixels();
177            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
178                const unsigned char r = ptr[0];
179                const unsigned char g = ptr[1];
180                const unsigned char b = ptr[2];
181                const unsigned char a = ptr[3];
182                ptr[0] = b;
183                ptr[1] = g;
184                ptr[2] = r;
185                ptr[3] = a;
186            }
187    
188            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
189    #if HAS_CAIROMM_CPP11_ENUMS
190                this->grayBlueHatchedPatternARGB->get_pixels(), Cairo::Surface::Format::ARGB32, width, height, stride
191    #else
192                this->grayBlueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
193    #endif
194            );
195            this->grayBlueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
196    #if HAS_CAIROMM_CPP11_ENUMS
197            this->grayBlueHatchedSurfacePattern->set_extend(Cairo::Pattern::Extend::REPEAT);
198    #else
199            this->grayBlueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
200    #endif
201        }
202    
203      instrument = 0;      instrument = 0;
204      region = 0;      region = 0;
205      dimregno = -1;      maindimregno = -1;
206        maindimtype = gig::dimension_none; // initialize with invalid dimension type
207      focus_line = 0;      focus_line = 0;
208      resize.active = false;      resize.active = false;
209      cursor_is_resize = false;      cursor_is_resize = false;
210      h = 20;      h = 24;
211        multiSelectKeyDown = false;
212        primaryKeyDown = false;
213        shiftKeyDown = false;
214        modifybothchannels = modifyalldimregs = modifybothchannels = false;
215      set_can_focus();      set_can_focus();
216    
217        const Glib::ustring txtUseCheckBoxAllRegions =
218            _("Use checkbox 'all regions' to control whether this should apply to all regions.");
219    
220        actionGroup = ActionGroup::create();
221    #if USE_GLIB_ACTION
222        actionSplitDimZone = actionGroup->add_action(
223            "SplitDimZone", sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
224        );
225        actionDeleteDimZone = actionGroup->add_action(
226             "DeleteDimZone", sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
227         );
228        insert_action_group("PopupMenuInsideDimRegion", actionGroup);
229    #else
230        actionSplitDimZone = Action::create("SplitDimZone", _("Split Dimensions Zone"), txtUseCheckBoxAllRegions);
231        actionSplitDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
232        actionGroup->add(
233            actionSplitDimZone,
234            sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
235        );
236        actionDeleteDimZone = Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone"), txtUseCheckBoxAllRegions);
237        actionDeleteDimZone->set_tooltip(txtUseCheckBoxAllRegions); //FIXME: doesn't work? why???
238        actionGroup->add(
239            actionDeleteDimZone,
240            sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
241        );
242    #endif
243    
244    #if USE_GTKMM_BUILDER
245        uiManager = Gtk::Builder::create();
246        Glib::ustring ui_info =
247            "<interface>"
248            "  <menu id='menu-PopupMenuInsideDimRegion'>"
249            "    <section>"
250            "      <item id='item-split'>"
251            "        <attribute name='label' translatable='yes'>Split Dimensions Zone</attribute>"
252            "        <attribute name='action'>PopupMenuInsideDimRegion.SplitDimZone</attribute>"
253            "      </item>"
254            "      <item id='item-delete'>"
255            "        <attribute name='label' translatable='yes'>Delete Dimension Zone</attribute>"
256            "        <attribute name='action'>PopupMenuInsideDimRegion.DeleteDimZone</attribute>"
257            "      </item>"
258            "    </section>"
259            "  </menu>"
260            "</interface>";
261        uiManager->add_from_string(ui_info);
262    
263        popup_menu_inside_dimregion = new Gtk::Menu(
264            Glib::RefPtr<Gio::Menu>::cast_dynamic(
265                uiManager->get_object("menu-PopupMenuInsideDimRegion")
266            )
267        );
268    #else
269        uiManager = Gtk::UIManager::create();
270        uiManager->insert_action_group(actionGroup);
271        Glib::ustring ui_info =
272            "<ui>"
273            "  <popup name='PopupMenuInsideDimRegion'>"
274            "    <menuitem action='SplitDimZone'/>"
275            "    <menuitem action='DeleteDimZone'/>"
276            "  </popup>"
277    //         "  <popup name='PopupMenuOutsideDimRegion'>"
278    //         "    <menuitem action='Add'/>"
279    //         "  </popup>"
280            "</ui>";
281        uiManager->add_ui_from_string(ui_info);
282    
283        popup_menu_inside_dimregion = dynamic_cast<Gtk::Menu*>(
284            uiManager->get_widget("/PopupMenuInsideDimRegion"));
285    //     popup_menu_outside_dimregion = dynamic_cast<Gtk::Menu*>(
286    //         uiManager->get_widget("/PopupMenuOutsideDimRegion"));
287    
288    #endif // USE_GTKMM_BUILDER
289    
290    
291    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22)
292    # warning GTKMM4 event registration code missing for dimregionchooser!
293        //add_events(Gdk::EventMask::BUTTON_PRESS_MASK);
294    #else
295      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
296                 Gdk::POINTER_MOTION_HINT_MASK);                 Gdk::POINTER_MOTION_HINT_MASK);
297    #endif
298    
     for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;  
299      labels_changed = true;      labels_changed = true;
300    
301        set_tooltip_text(_(
302            "Right click here for options on altering dimension zones. Press and "
303            "hold CTRL key for selecting multiple dimension zones simultaniously."
304        ));
305        
306        window.signal_key_press_event().connect(
307            sigc::mem_fun(*this, &DimRegionChooser::onKeyPressed)
308        );
309        window.signal_key_release_event().connect(
310            sigc::mem_fun(*this, &DimRegionChooser::onKeyReleased)
311        );
312  }  }
313    
314  DimRegionChooser::~DimRegionChooser()  DimRegionChooser::~DimRegionChooser()
315  {  {
316  }  }
317    
318    void DimRegionChooser::setModifyBothChannels(bool b) {
319        modifybothchannels = b;
320        // redraw required parts
321        queue_draw();
322    }
323    
324    void DimRegionChooser::setModifyAllDimensionRegions(bool b) {
325        modifyalldimregs = b;
326        // redraw required parts
327        queue_draw();
328    }
329    
330    void DimRegionChooser::setModifyAllRegions(bool b) {
331        modifyallregions = b;
332    
333    #if USE_GTKMM_BUILDER
334        auto menuItemSplit = Glib::RefPtr<Gio::MenuItem>::cast_dynamic(
335            uiManager->get_object("item-split")
336        );
337        auto menuItemDelete = Glib::RefPtr<Gio::MenuItem>::cast_dynamic(
338            uiManager->get_object("item-delete")
339        );
340        menuItemDelete->set_label(b ? _("Delete Dimension Zone [ALL REGIONS]") : _("Delete Dimension Zone"));
341        menuItemSplit->set_label(b ? _("Split Dimensions Zone [ALL REGIONS]") : _("Split Dimensions Zone"));
342    #else
343        actionDeleteDimZone->set_label(b ? _("Delete Dimension Zone [ALL REGIONS]") : _("Delete Dimension Zone"));
344        actionSplitDimZone->set_label(b ? _("Split Dimensions Zone [ALL REGIONS]") : _("Split Dimensions Zone"));
345    #endif
346    
347        // redraw required parts
348        queue_draw();
349    }
350    
351    void DimRegionChooser::drawIconsFor(
352        gig::dimension_t dimension, uint zone,
353        const Cairo::RefPtr<Cairo::Context>& cr,
354        int x, int y, int w, int h)
355    {
356        DimensionCase dimCase;
357        dimCase[dimension] = zone;
358    
359        std::vector<gig::DimensionRegion*> dimregs =
360            dimensionRegionsMatching(dimCase, region, true);
361    
362        if (dimregs.empty()) return;
363    
364        int iSampleRefs = 0;
365        int iLoops = 0;
366    
367        for (uint i = 0; i < dimregs.size(); ++i) {
368            if (dimregs[i]->pSample) iSampleRefs++;
369            if (dimregs[i]->SampleLoops) iLoops++;
370        }
371    
372        bool bShowLoopSymbol = (iLoops > 0);
373        bool bShowSampleRefSymbol = (iSampleRefs < dimregs.size());
374    
375        if (bShowLoopSymbol || bShowSampleRefSymbol) {
376            const int margin = 1;
377    
378            cr->save();
379            cr->set_line_width(1);
380            cr->rectangle(x, y + margin, w, h - 2*margin);
381            cr->clip();
382            if (bShowSampleRefSymbol) {
383                const int wPic = 8;
384                const int hPic = 8;
385                Gdk::Cairo::set_source_pixbuf(
386                    cr, (iSampleRefs) ? yellowDot : redDot,
387                    x + (w-wPic)/2.f,
388                    y + (
389                        (bShowLoopSymbol) ? margin : (h-hPic)/2.f
390                    )
391                );
392                cr->paint();
393            }
394            if (bShowLoopSymbol) {
395                const int wPic = 12;
396                const int hPic = 14;
397                Gdk::Cairo::set_source_pixbuf(
398                    cr, (iLoops == dimregs.size()) ? blackLoop : grayLoop,
399                    x + (w-wPic)/2.f,
400                    y + (
401                        (bShowSampleRefSymbol) ? h - hPic - margin : (h-hPic)/2.f
402                    )
403                );
404                cr->paint();
405            }
406            cr->restore();
407        }
408    }
409    
410  #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
411  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)  bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
412  {  {
# Line 58  bool DimRegionChooser::on_expose_event(G Line 417  bool DimRegionChooser::on_expose_event(G
417    
418      const Cairo::RefPtr<Cairo::Context>& cr =      const Cairo::RefPtr<Cairo::Context>& cr =
419          get_window()->create_cairo_context();          get_window()->create_cairo_context();
 #if 0  
 }  
 #endif  
420  #else  #else
421  bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)  bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
422  {  {
# Line 139  bool DimRegionChooser::on_draw(const Cai Line 495  bool DimRegionChooser::on_draw(const Cai
495                      dstr = dstrbuf;                      dstr = dstrbuf;
496                      break;                      break;
497                  }                  }
                 layout->set_text(dstr);  
498    
499                    // Since bold font yields in larger label width, we first always
500                    // set the bold text variant, retrieve its dimensions (as worst
501                    // case dimensions of the label) ...
502                    layout->set_markup("<b>" + Glib::ustring(dstr) + "</b>");
503                  Pango::Rectangle rectangle = layout->get_logical_extents();                  Pango::Rectangle rectangle = layout->get_logical_extents();
504                    // ... and then reset the label to regular font style in case
505                    // the line is not selected. Otherwise the right hand side
506                    // actual dimension zones would jump around on selection change.
507                    bool isSelectedLine = (focus_line == i);
508                    if (!isSelectedLine)
509                        layout->set_markup(dstr);
510    
511                  double text_w = double(rectangle.get_width()) / Pango::SCALE;                  double text_w = double(rectangle.get_width()) / Pango::SCALE;
512                  if (text_w > maxwidth) maxwidth = text_w;                  if (text_w > maxwidth) maxwidth = text_w;
513    
# Line 152  bool DimRegionChooser::on_draw(const Cai Line 518  bool DimRegionChooser::on_draw(const Cai
518                      const Gdk::Color fg = get_style()->get_fg(get_state());                      const Gdk::Color fg = get_style()->get_fg(get_state());
519  #else  #else
520                      const Gdk::RGBA fg =                      const Gdk::RGBA fg =
521    # if GTKMM_MAJOR_VERSION >= 3
522                            get_style_context()->get_color();
523    # else
524                          get_style_context()->get_color(get_state_flags());                          get_style_context()->get_color(get_state_flags());
525    # endif
526  #endif  #endif
527                      Gdk::Cairo::set_source_rgba(cr, fg);                      Gdk::Cairo::set_source_rgba(cr, fg);
528                      cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));                      cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));
# Line 176  bool DimRegionChooser::on_draw(const Cai Line 546  bool DimRegionChooser::on_draw(const Cai
546      for (int i = 0 ; i < region->Dimensions ; i++) {      for (int i = 0 ; i < region->Dimensions ; i++) {
547          int nbZones = region->pDimensionDefinitions[i].zones;          int nbZones = region->pDimensionDefinitions[i].zones;
548          if (nbZones) {          if (nbZones) {
549                const gig::dimension_t dimension = region->pDimensionDefinitions[i].dimension;
550    
551              if (y >= clipy2) break;              if (y >= clipy2) break;
552              if (y + h > clipy1) {              if (y + h > clipy1) {
553                  // draw focus rectangle around dimension's label and zones                  // draw focus rectangle around dimension's label and zones
554                  if (has_focus() && focus_line == i) {                  if (has_focus() && focus_line == i) {
555  #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
556                      Gdk::Rectangle farea(0, y, 150, 20);                      Gdk::Rectangle farea(0, y, 150, h);
557                      get_style()->paint_focus(get_window(), get_state(), farea,                      get_style()->paint_focus(get_window(), get_state(), farea,
558                                               *this, "",                                               *this, "",
559                                               0, y, label_width, 20);                                               0, y, label_width, h);
560  #else  #else
561                      get_style_context()->render_focus(cr,                      get_style_context()->render_focus(cr,
562                                                        0, y, label_width, 20);                                                        0, y, label_width, h);
563  #endif  #endif
564                  }                  }
565    
# Line 206  bool DimRegionChooser::on_draw(const Cai Line 578  bool DimRegionChooser::on_draw(const Cai
578                  cr->fill();                  cr->fill();
579    
580                  int c = 0;                  int c = 0;
581                  if (dimregno >= 0) {                  if (maindimregno >= 0) {
582                      int mask =                      int mask =
583                          ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<                          ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<
584                            bitpos);                            bitpos);
585                      c = dimregno & mask; // mask away this dimension                      c = maindimregno & mask; // mask away this dimension
586                  }                  }
587                  bool customsplits =                  bool customsplits =
588                      ((region->pDimensionDefinitions[i].split_type ==                      ((region->pDimensionDefinitions[i].split_type ==
# Line 220  bool DimRegionChooser::on_draw(const Cai Line 592  bool DimRegionChooser::on_draw(const Cai
592                        gig::dimension_velocity &&                        gig::dimension_velocity &&
593                        region->pDimensionRegions[c]->VelocityUpperLimit));                        region->pDimensionRegions[c]->VelocityUpperLimit));
594    
595                  // draw dimension's zone borders                  // draw dimension zones
596                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
597                  if (customsplits) {                  if (customsplits) {
598                      cr->move_to(label_width + 0.5, y + 1);                      cr->move_to(label_width + 0.5, y + 1);
599                      cr->line_to(label_width + 0.5, y + h - 1);                      cr->line_to(label_width + 0.5, y + h - 1);
600                        int prevX = label_width;
601                        int prevUpperLimit = -1;
602    
603                      for (int j = 0 ; j < nbZones ; j++) {                      for (int j = 0 ; j < nbZones ; j++) {
604                            // draw dimension zone's borders for custom splits
605                          gig::DimensionRegion* d =                          gig::DimensionRegion* d =
606                              region->pDimensionRegions[c + (j << bitpos)];                              region->pDimensionRegions[c + (j << bitpos)];
607                          int upperLimit = d->DimensionUpperLimits[i];                          int upperLimit = d->DimensionUpperLimits[i];
# Line 236  bool DimRegionChooser::on_draw(const Cai Line 611  bool DimRegionChooser::on_draw(const Cai
611                              label_width;                              label_width;
612                          if (x >= clipx2) break;                          if (x >= clipx2) break;
613                          if (x < clipx1) continue;                          if (x < clipx1) continue;
614                            Gdk::Cairo::set_source_rgba(cr, black);
615                          cr->move_to(x + 0.5, y + 1);                          cr->move_to(x + 0.5, y + 1);
616                          cr->line_to(x + 0.5, y + h - 1);                          cr->line_to(x + 0.5, y + h - 1);
617                            cr->stroke();
618    
619                            // draw fill for zone
620                            bool isSelectedZone = this->dimzones[dimension].count(j);
621                            bool isMainSelection =
622                                this->maindimcase.find(dimension) != this->maindimcase.end() &&
623                                this->maindimcase[dimension] == j;
624                            bool isCheckBoxSelected =
625                                modifyalldimregs ||
626                                (modifybothchannels &&
627                                    dimension == gig::dimension_samplechannel);
628                            if (isMainSelection)
629                                Gdk::Cairo::set_source_rgba(cr, blue);
630                            else if (isSelectedZone)
631                                cr->set_source(blueHatchedSurfacePattern2);
632                            else if (isCheckBoxSelected)
633                                cr->set_source(blueHatchedSurfacePattern);
634                            else
635                                Gdk::Cairo::set_source_rgba(cr, white);
636    
637                            const int wZone = x - prevX - 1;
638    
639                            cr->rectangle(prevX + 1, y + 1, wZone, h - 1);
640                            cr->fill();
641    
642                            // draw icons
643                            drawIconsFor(dimension, j, cr, prevX, y, wZone, h);
644    
645                            // draw text showing the beginning of the dimension zone
646                            // as numeric value to the user
647                            {
648                                Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
649                                layout->set_text(Glib::Ascii::dtostr(prevUpperLimit+1));
650                                Gdk::Cairo::set_source_rgba(cr, black);
651                                // get the text dimensions
652                                int text_width, text_height;
653                                layout->get_pixel_size(text_width, text_height);
654                                // move text to the left end of the dimension zone
655                                cr->move_to(prevX + 3, y + (h - text_height) / 2);
656    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
657                                pango_cairo_show_layout(cr->cobj(), layout->gobj());
658    #else
659                                layout->show_in_cairo_context(cr);
660    #endif
661                            }
662                            // draw text showing the end of the dimension zone
663                            // as numeric value to the user
664                            {
665                                Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
666                                layout->set_text(Glib::Ascii::dtostr(upperLimit));
667                                Gdk::Cairo::set_source_rgba(cr, black);
668                                // get the text dimensions
669                                int text_width, text_height;
670                                layout->get_pixel_size(text_width, text_height);
671                                // move text to the left end of the dimension zone
672                                cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
673    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
674                                pango_cairo_show_layout(cr->cobj(), layout->gobj());
675    #else
676                                layout->show_in_cairo_context(cr);
677    #endif
678                            }
679    
680                            prevX = x;
681                            prevUpperLimit = upperLimit;
682                      }                      }
683                  } else {                  } else {
684                        int prevX = 0;
685                      for (int j = 0 ; j <= nbZones ; j++) {                      for (int j = 0 ; j <= nbZones ; j++) {
686                            // draw dimension zone's borders for normal splits
687                          int x = int((w - label_width - 1) * j /                          int x = int((w - label_width - 1) * j /
688                                      double(nbZones) + 0.5) + label_width;                                      double(nbZones) + 0.5) + label_width;
689                          if (x >= clipx2) break;                          if (x >= clipx2) break;
690                          if (x < clipx1) continue;                          if (x < clipx1) continue;
691                            Gdk::Cairo::set_source_rgba(cr, black);
692                          cr->move_to(x + 0.5, y + 1);                          cr->move_to(x + 0.5, y + 1);
693                          cr->line_to(x + 0.5, y + h - 1);                          cr->line_to(x + 0.5, y + h - 1);
694                      }                          cr->stroke();
695                  }  
696                  cr->stroke();                          if (j != 0) {
697                                const int wZone = x - prevX - 1;
698    
699                                // draw fill for zone
700                                bool isSelectedZone = this->dimzones[dimension].count(j-1);
701                                bool isMainSelection =
702                                    this->maindimcase.find(dimension) != this->maindimcase.end() &&
703                                    this->maindimcase[dimension] == (j-1);
704                                bool isCheckBoxSelected =
705                                    modifyalldimregs ||
706                                    (modifybothchannels &&
707                                        dimension == gig::dimension_samplechannel);
708                                if (isMainSelection)
709                                    Gdk::Cairo::set_source_rgba(cr, blue);
710                                else if (isSelectedZone)
711                                    cr->set_source(blueHatchedSurfacePattern2);
712                                else if (isCheckBoxSelected)
713                                    cr->set_source(blueHatchedSurfacePattern);
714                                else
715                                    Gdk::Cairo::set_source_rgba(cr, white);
716                                cr->rectangle(prevX + 1, y + 1, wZone, h - 1);
717                                cr->fill();
718    
719                                // draw icons
720                                drawIconsFor(dimension, j - 1, cr, prevX, y, wZone, h);
721    
722                  // draw fill for currently selected zone                              // draw text showing the beginning of the dimension zone
723                  if (dimregno >= 0) {                              // as numeric value to the user
724                      Gdk::Cairo::set_source_rgba(cr, red);                              {
725                      int dr = (dimregno >> bitpos) &                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
726                          ((1 << region->pDimensionDefinitions[i].bits) - 1);                                  layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));
727                      if (customsplits) {                                  Gdk::Cairo::set_source_rgba(cr, black);
728                          int x1 = label_width;                                  // get the text dimensions
729                          for (int j = 0 ; j < nbZones && x1 + 1 < clipx2 ; j++) {                                  int text_width, text_height;
730                              gig::DimensionRegion* d =                                  layout->get_pixel_size(text_width, text_height);
731                                  region->pDimensionRegions[c + (j << bitpos)];                                  // move text to the left end of the dimension zone
732                              int upperLimit = d->DimensionUpperLimits[i];                                  cr->move_to(prevX + 3, y + (h - text_height) / 2);
733                              if (!upperLimit) {  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
734                                  upperLimit = d->VelocityUpperLimit;                                  pango_cairo_show_layout(cr->cobj(), layout->gobj());
735    #else
736                                    layout->show_in_cairo_context(cr);
737    #endif
738                              }                              }
739                              int v = upperLimit + 1;                              // draw text showing the end of the dimension zone
740                              int x2 = int((w - label_width - 1) * v / 128.0 +                              // as numeric value to the user
741                                           0.5) + label_width;                              {
742                              if (j == dr && x1 < x2) {                                  Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
743                                  cr->rectangle(x1 + 1, y + 1,                                  layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));
744                                                (x2 - x1) - 1, h - 2);                                  Gdk::Cairo::set_source_rgba(cr, black);
745                                  cr->fill();                                  // get the text dimensions
746                                  break;                                  int text_width, text_height;
747                                    layout->get_pixel_size(text_width, text_height);
748                                    // move text to the left end of the dimension zone
749                                    cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
750    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
751                                    pango_cairo_show_layout(cr->cobj(), layout->gobj());
752    #else
753                                    layout->show_in_cairo_context(cr);
754    #endif
755                              }                              }
                             x1 = x2;  
                         }  
                     } else {  
                         if (dr < nbZones) {  
                             int x1 = int((w - label_width - 1) * dr /  
                                          double(nbZones) + 0.5);  
                             int x2 = int((w - label_width - 1) * (dr + 1) /  
                                          double(nbZones) + 0.5);  
                             cr->rectangle(label_width + x1 + 1, y + 1,  
                                           (x2 - x1) - 1, h - 2);  
                             cr->fill();  
756                          }                          }
757                      }                          prevX = x;
758                        }      
759                  }                  }
760              }              }
   
761              y += h;              y += h;
762          }          }
763          bitpos += region->pDimensionDefinitions[i].bits;          bitpos += region->pDimensionDefinitions[i].bits;
# Line 301  bool DimRegionChooser::on_draw(const Cai Line 769  bool DimRegionChooser::on_draw(const Cai
769  void DimRegionChooser::set_region(gig::Region* region)  void DimRegionChooser::set_region(gig::Region* region)
770  {  {
771      this->region = region;      this->region = region;
772      dimregno = 0;      maindimregno = 0;
773      nbDimensions = 0;      nbDimensions = 0;
774      if (region) {      if (region) {
775          int bitcount = 0;          int bitcount = 0;
# Line 309  void DimRegionChooser::set_region(gig::R Line 777  void DimRegionChooser::set_region(gig::R
777              if (region->pDimensionDefinitions[dim].bits == 0) continue;              if (region->pDimensionDefinitions[dim].bits == 0) continue;
778              nbDimensions++;              nbDimensions++;
779    
780              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              int z = std::min(maindimcase[region->pDimensionDefinitions[dim].dimension],
781                               region->pDimensionDefinitions[dim].zones - 1);                               region->pDimensionDefinitions[dim].zones - 1);
782              dimregno |= (z << bitcount);              maindimregno |= (z << bitcount);
783              bitcount += region->pDimensionDefinitions[dim].bits;              bitcount += region->pDimensionDefinitions[dim].bits;
784          }          }
         dimreg = region->pDimensionRegions[dimregno];  
     } else {  
         dimreg = 0;  
785      }      }
786      dimregion_selected();      dimregion_selected();
787      set_size_request(800, region ? nbDimensions * 20 : 0);      set_size_request(800, region ? nbDimensions * h : 0);
788    
789      labels_changed = true;      labels_changed = true;
790      queue_resize();      queue_resize();
791        queue_draw();
792  }  }
793    
794    void DimRegionChooser::refresh_all() {
795        set_region(region);
796    }
797    
798  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
799                                        std::set<gig::DimensionRegion*>& dimregs) const                                        std::set<gig::DimensionRegion*>& dimregs) const
800  {  {
801      int dimregno = 0;      for (int iDimRgn = 0; iDimRgn < 256; ++iDimRgn) {
802      int bitcount = 0;          gig::DimensionRegion* dimRgn = region->pDimensionRegions[iDimRgn];
803      int stereo_bit = 0;          if (!dimRgn) continue;
804      for (int dim = 0 ; dim < region->Dimensions ; dim++) {          bool isValidZone;
805          if (region->pDimensionDefinitions[dim].bits == 0) continue;          std::map<gig::dimension_t,int> dimCase = caseOfDimRegion(dimRgn, &isValidZone);
806          if (stereo &&          if (!isValidZone) continue;
807              region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {          for (std::map<gig::dimension_t,int>::const_iterator it = dimCase.begin();
808              stereo_bit = (1 << bitcount);               it != dimCase.end(); ++it)
809          } else {          {
810              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              if (stereo && it->first == gig::dimension_samplechannel) continue; // is selected
811                               region->pDimensionDefinitions[dim].zones - 1);  
812              dimregno |= (z << bitcount);              std::map<gig::dimension_t, std::set<int> >::const_iterator itSelectedDimension =
813                    this->dimzones.find(it->first);
814                if (itSelectedDimension != this->dimzones.end() &&
815                    itSelectedDimension->second.count(it->second)) continue; // is selected
816    
817                goto notSelected;
818          }          }
819          bitcount += region->pDimensionDefinitions[dim].bits;  
820            dimregs.insert(dimRgn);
821    
822            notSelected:
823            ;
824      }      }
     dimregs.insert(region->pDimensionRegions[dimregno]);  
     if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);  
825  }  }
826    
827  void DimRegionChooser::update_after_resize()  void DimRegionChooser::update_after_resize()
828  {  {
829      if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {      const uint8_t upperLimit = resize.pos - 1;
830        gig::Instrument* instr = (gig::Instrument*)region->GetParent();
831    
832          int bitpos = 0;      int bitpos = 0;
833          for (int j = 0 ; j < resize.dimension ; j++) {      for (int j = 0 ; j < resize.dimension ; j++) {
834              bitpos += region->pDimensionDefinitions[j].bits;          bitpos += region->pDimensionDefinitions[j].bits;
835          }      }
836    
837        const int stereobitpos =
838            (modifybothchannels) ? baseBits(gig::dimension_samplechannel, region) : -1;
839    
840        // the velocity dimension must be handled differently than all other
841        // dimension types, because
842        // 1. it is currently the only dimension type which allows different zone
843        //    sizes for different cases
844        // 2. for v2 format VelocityUpperLimit has to be set, DimensionUpperLimits for v3
845        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
846          int mask =          int mask =
847              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);              ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
848          int c = dimregno & mask; // mask away this dimension          int c = maindimregno & mask; // mask away this dimension
849    
850          if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {          if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
851              // the velocity dimension didn't previously have              // the velocity dimension didn't previously have
# Line 381  void DimRegionChooser::update_after_resi Line 868  void DimRegionChooser::update_after_resi
868              }              }
869          }          }
870    
871          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];          int index = c + (resize.zone << bitpos);
872            gig::DimensionRegion* d = region->pDimensionRegions[index];
873          // update both v2 and v3 values          // update both v2 and v3 values
874          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;          d->DimensionUpperLimits[resize.dimension] = upperLimit;
875          d->VelocityUpperLimit = resize.pos - 1;          d->VelocityUpperLimit = upperLimit;
876            if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
877                gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
878                d->DimensionUpperLimits[resize.dimension] = upperLimit;
879                d->VelocityUpperLimit = upperLimit;
880            }
881    
882            if (modifyalldimregs) {
883                gig::Region* rgn = NULL;
884                for (int key = 0; key < 128; ++key) {
885                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
886                    rgn = instr->GetRegion(key);
887                    if (!modifyallregions && rgn != region) continue; // hack to reduce overall code amount a bit
888                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
889                    if (!dimdef) continue;
890                    if (dimdef->zones != resize.dimensionDef.zones) continue;
891                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
892                    assert(iDim >= 0 && iDim < rgn->Dimensions);
893    
894                    // the dimension layout might be completely different in this
895                    // region, so we have to recalculate bitpos etc for this region
896                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
897                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
898                    const int selection = resize.zone << bitpos;
899    
900                    // primitive and inefficient loop implementation, however due to
901                    // this circumstance the loop code is much simpler, and its lack
902                    // of runtime efficiency should not be notable in practice
903                    for (int idr = 0; idr < 256; ++idr) {
904                        const int index = (idr & stencil) | selection;
905                        assert(index >= 0 && index < 256);
906                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
907                        if (!dr) continue;
908                        dr->DimensionUpperLimits[iDim] = upperLimit;
909                        d->VelocityUpperLimit = upperLimit;
910                    }
911                }
912            } else if (modifyallregions) { // implies modifyalldimregs is false ...
913                // resolve the precise case we need to modify for all other regions
914                DimensionCase dimCase = dimensionCaseOf(d);
915                // apply the velocity upper limit change to that resolved dim case
916                // of all regions ...
917                gig::Region* rgn = NULL;
918                for (int key = 0; key < 128; ++key) {
919                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
920                    rgn = instr->GetRegion(key);
921                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
922                    if (!dimdef) continue;
923                    if (dimdef->zones != resize.dimensionDef.zones) continue;
924                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
925                    assert(iDim >= 0 && iDim < rgn->Dimensions);
926    
927                    std::vector<gig::DimensionRegion*> dimrgns = dimensionRegionsMatching(dimCase, rgn);
928                    for (int i = 0; i < dimrgns.size(); ++i) {
929                        gig::DimensionRegion* dr = dimrgns[i];
930                        dr->DimensionUpperLimits[iDim] = upperLimit;
931                        dr->VelocityUpperLimit = upperLimit;
932                    }
933                }
934            }
935      } else {      } else {
936          for (int i = 0 ; i < region->DimensionRegions ; ) {          for (int i = 0 ; i < region->DimensionRegions ; ) {
   
937              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {              if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
938                  // the dimension didn't previously have custom                  // the dimension didn't previously have custom
939                  // limits, so we have to set default limits for                  // limits, so we have to set default limits for
940                  // all the dimension regions                  // all the dimension regions
                 int bitpos = 0;  
                 for (int j = 0 ; j < resize.dimension ; j++) {  
                     bitpos += region->pDimensionDefinitions[j].bits;  
                 }  
941                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
942    
943                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
# Line 404  void DimRegionChooser::update_after_resi Line 945  void DimRegionChooser::update_after_resi
945                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
946                  }                  }
947              }              }
948              gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];              int index = i + (resize.zone << bitpos);
949              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;              gig::DimensionRegion* d = region->pDimensionRegions[index];
950                d->DimensionUpperLimits[resize.dimension] = upperLimit;
951    #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
952                if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
953                    gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
954                    d->DimensionUpperLimits[resize.dimension] = upperLimit;
955                }
956    #endif
957              int bitpos = 0;              int bitpos = 0;
958              int j;              int j;
959              for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
# Line 420  void DimRegionChooser::update_after_resi Line 967  void DimRegionChooser::update_after_resi
967              if (j == region->Dimensions) break;              if (j == region->Dimensions) break;
968              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);              i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
969          }          }
970    
971            if (modifyallregions) { // TODO: this code block could be merged with the similar (and more generalized) code block of the velocity dimension above
972                gig::Region* rgn = NULL;
973                for (int key = 0; key < 128; ++key) {
974                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
975                    rgn = instr->GetRegion(key);
976                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
977                    if (!dimdef) continue;
978                    if (dimdef->zones != resize.dimensionDef.zones) continue;
979                    const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
980                    assert(iDim >= 0 && iDim < rgn->Dimensions);
981    
982                    // the dimension layout might be completely different in this
983                    // region, so we have to recalculate bitpos etc for this region
984                    const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
985                    const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
986                    const int selection = resize.zone << bitpos;
987    
988                    // this loop implementation is less efficient than the above's
989                    // loop implementation (which skips unnecessary dimension regions)
990                    // however this code is much simpler, and its lack of runtime
991                    // efficiency should not be notable in practice
992                    for (int idr = 0; idr < 256; ++idr) {
993                        const int index = (idr & stencil) | selection;
994                        assert(index >= 0 && index < 256);
995                        gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
996                        if (!dr) continue;
997                        dr->DimensionUpperLimits[iDim] = upperLimit;
998                    }
999                }
1000            }
1001      }      }
1002  }  }
1003    
# Line 429  bool DimRegionChooser::on_button_release Line 1007  bool DimRegionChooser::on_button_release
1007  #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
1008          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
1009  #else  #else
1010    # if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20)
1011          Glib::wrap(event->device, true)->ungrab(event->time);          Glib::wrap(event->device, true)->ungrab(event->time);
1012    # else
1013            gdk_device_ungrab(Glib::wrap(event->device, true)->gobj(), event->time);
1014    # endif
1015  #endif  #endif
1016          resize.active = false;          resize.active = false;
1017    
# Line 458  bool DimRegionChooser::on_button_press_e Line 1040  bool DimRegionChooser::on_button_press_e
1040                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
1041                                         event->time);                                         event->time);
1042  #else  #else
1043    # if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20)
1044              Glib::wrap(event->device, true)->grab(get_window(),              Glib::wrap(event->device, true)->grab(get_window(),
1045                                                    Gdk::OWNERSHIP_NONE,                                                    Gdk::OWNERSHIP_NONE,
1046                                                    false,                                                    false,
# Line 466  bool DimRegionChooser::on_button_press_e Line 1049  bool DimRegionChooser::on_button_press_e
1049                                                    Gdk::POINTER_MOTION_HINT_MASK,                                                    Gdk::POINTER_MOTION_HINT_MASK,
1050                                                    Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),                                                    Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
1051                                                    event->time);                                                    event->time);
1052    # else
1053                gdk_device_grab(
1054                    Glib::wrap(event->device, true)->gobj(),
1055                    get_window()->gobj(),
1056                    GDK_OWNERSHIP_NONE,
1057                    false,
1058                    GdkEventMask(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
1059                                 GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK),
1060                    Gdk::Cursor::create(
1061                        Glib::wrap(event->device, true)->get_seat()->get_display(),
1062                        Gdk::SB_H_DOUBLE_ARROW
1063                    )->gobj(),
1064                    event->time
1065                );
1066    # endif
1067  #endif  #endif
1068              resize.active = true;              resize.active = true;
1069          } else {          } else {
# Line 485  bool DimRegionChooser::on_button_press_e Line 1083  bool DimRegionChooser::on_button_press_e
1083              }              }
1084    
1085              int i = dim;              int i = dim;
1086              if (dimregno < 0) dimregno = 0;              if (maindimregno < 0) maindimregno = 0;
1087              int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);              int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
1088              int c = dimregno & mask; // mask away this dimension              int c = this->maindimregno & mask; // mask away this dimension
1089    
1090              bool customsplits =              bool customsplits =
1091                  ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&                  ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
# Line 517  bool DimRegionChooser::on_button_press_e Line 1115  bool DimRegionChooser::on_button_press_e
1115                     region->pDimensionDefinitions[dim].split_type,                     region->pDimensionDefinitions[dim].split_type,
1116                     region->pDimensionDefinitions[dim].zones,                     region->pDimensionDefinitions[dim].zones,
1117                     region->pDimensionDefinitions[dim].zone_size);                     region->pDimensionDefinitions[dim].zone_size);
1118              dimvalue[region->pDimensionDefinitions[dim].dimension] = z;              this->maindimcase[region->pDimensionDefinitions[dim].dimension] = z;
1119                this->maindimregno = c | (z << bitpos);
1120              dimregno = c | (z << bitpos);              this->maindimtype = region->pDimensionDefinitions[dim].dimension;
1121    
1122                if (multiSelectKeyDown) {
1123                    if (dimzones[this->maindimtype].count(z)) {
1124                        if (dimzones[this->maindimtype].size() > 1) {
1125                            dimzones[this->maindimtype].erase(z);
1126                        }
1127                    } else {
1128                        dimzones[this->maindimtype].insert(z);
1129                    }
1130                } else {
1131                    this->dimzones.clear();
1132                    for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1133                         it != this->maindimcase.end(); ++it)
1134                    {
1135                        this->dimzones[it->first].insert(it->second);
1136                    }
1137                }
1138    
1139              focus_line = dim;              focus_line = dim;
1140              if (has_focus()) queue_draw();              if (has_focus()) queue_draw();
1141              else grab_focus();              else grab_focus();
             dimreg = region->pDimensionRegions[dimregno];  
1142              dimregion_selected();              dimregion_selected();
1143    
1144                if (event->button == 3) {
1145                    printf("dimregion right click\n");
1146                    popup_menu_inside_dimregion->popup(event->button, event->time);
1147                }
1148    
1149                queue_draw();
1150          }          }
1151      }      }
1152      return true;      return true;
# Line 535  bool DimRegionChooser::on_motion_notify_ Line 1156  bool DimRegionChooser::on_motion_notify_
1156  {  {
1157      Glib::RefPtr<Gdk::Window> window = get_window();      Glib::RefPtr<Gdk::Window> window = get_window();
1158      int x, y;      int x, y;
1159    #if HAS_GDKMM_SEAT
1160        x = event->x;
1161        y = event->y;
1162        Gdk::ModifierType state = Gdk::ModifierType(event->state);
1163    #else
1164      Gdk::ModifierType state = Gdk::ModifierType(0);      Gdk::ModifierType state = Gdk::ModifierType(0);
1165      window->get_pointer(x, y, state);      window->get_pointer(x, y, state);
1166    #endif
1167    
1168      if (resize.active) {      if (resize.active) {
1169          int w = get_width();          int w = get_width();
# Line 563  bool DimRegionChooser::on_motion_notify_ Line 1190  bool DimRegionChooser::on_motion_notify_
1190    
1191              resize.pos = k;              resize.pos = k;
1192              update_after_resize();              update_after_resize();
1193              get_window()->invalidate_rect(rect, false);              get_window()->invalidate_rect(rect, false); // not sufficient ...
1194                queue_draw(); // ... so do a complete redraw instead.
1195          }          }
1196      } else {      } else {
1197          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
# Line 571  bool DimRegionChooser::on_motion_notify_ Line 1199  bool DimRegionChooser::on_motion_notify_
1199  #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
1200                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
1201  #else  #else
1202                  window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(
1203    # if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20)
1204                        Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW)
1205    # else
1206                        Gdk::Cursor::create(
1207                            Glib::wrap(event->device, true)->get_seat()->get_display(),
1208                            Gdk::SB_H_DOUBLE_ARROW
1209                        )
1210    # endif
1211                    );
1212  #endif  #endif
1213                  cursor_is_resize = true;                  cursor_is_resize = true;
1214              }              }
# Line 599  bool DimRegionChooser::is_in_resize_zone Line 1236  bool DimRegionChooser::is_in_resize_zone
1236          int nbZones = region->pDimensionDefinitions[dim].zones;          int nbZones = region->pDimensionDefinitions[dim].zones;
1237    
1238          int c = 0;          int c = 0;
1239          if (dimregno >= 0) {          if (maindimregno >= 0) {
1240              int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);              int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
1241              c = dimregno & mask; // mask away this dimension              c = maindimregno & mask; // mask away this dimension
1242          }          }
1243          const bool customsplits =          const bool customsplits =
1244              ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&              ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&
# Line 624  bool DimRegionChooser::is_in_resize_zone Line 1261  bool DimRegionChooser::is_in_resize_zone
1261                  if (x <= limitx - 2) break;                  if (x <= limitx - 2) break;
1262                  if (x <= limitx + 2) {                  if (x <= limitx + 2) {
1263                      resize.dimension = dim;                      resize.dimension = dim;
1264                      resize.offset = iZone << bitpos;                      resize.dimensionDef = region->pDimensionDefinitions[dim];
1265                        resize.zone = iZone;
1266                      resize.pos = limit;                      resize.pos = limit;
1267                      resize.min = prev_limit;                      resize.min = prev_limit;
1268    
1269                      int dr = (dimregno >> bitpos) &                      int dr = (maindimregno >> bitpos) &
1270                          ((1 << region->pDimensionDefinitions[dim].bits) - 1);                          ((1 << region->pDimensionDefinitions[dim].bits) - 1);
1271                      resize.selected = dr == iZone ? resize.left :                      resize.selected = dr == iZone ? resize.left :
1272                          dr == iZone + 1 ? resize.right : resize.none;                          dr == iZone + 1 ? resize.right : resize.none;
# Line 665  sigc::signal<void>& DimRegionChooser::si Line 1303  sigc::signal<void>& DimRegionChooser::si
1303    
1304  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)  bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
1305  {  {
1306      // 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
1307      // fokus.      // to set focus
1308      if (direction == Gtk::DIR_TAB_FORWARD ||      if (direction == Gtk::DIR_TAB_FORWARD ||
1309          direction == Gtk::DIR_DOWN) {          direction == Gtk::DIR_DOWN) {
1310          if (!has_focus()) {          if (!has_focus()) {
# Line 698  bool DimRegionChooser::on_focus(Gtk::Dir Line 1336  bool DimRegionChooser::on_focus(Gtk::Dir
1336              }              }
1337          }          }
1338      } else if (!has_focus()) {      } else if (!has_focus()) {
1339          // TODO: kolla att focus_line finns!          // TODO: check that focus_line exists
1340          grab_focus();          grab_focus();
1341          return true;          return true;
1342      } else {      } else {
1343          // TODO: öka eller minska värde!          // TODO: increase or decrease value
1344        }
1345        return false;
1346    }
1347    
1348    void DimRegionChooser::split_dimension_zone() {    
1349        printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1350        try {
1351            if (!modifyallregions) {
1352                region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1353            } else {
1354                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1355                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1356                assert(pMaindimdef != NULL);
1357                // retain structure by value since the original region will be
1358                // modified in the loop below as well
1359                gig::dimension_def_t maindimdef = *pMaindimdef;
1360                std::vector<gig::Region*> ignoredAll;
1361                std::vector<gig::Region*> ignoredMinor;
1362                std::vector<gig::Region*> ignoredCritical;
1363                gig::Region* rgn = NULL;
1364                for (int key = 0; key < 128; ++key) {
1365                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1366                    rgn = instr->GetRegion(key);
1367    
1368                    // ignore all regions which do not exactly match the dimension
1369                    // layout of the selected region where this operation was emitted
1370                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1371                    if (!dimdef) {
1372                        ignoredAll.push_back(rgn);
1373                        ignoredMinor.push_back(rgn);
1374                        continue;
1375                    }
1376                    if (dimdef->zones != maindimdef.zones) {
1377                        ignoredAll.push_back(rgn);
1378                        ignoredCritical.push_back(rgn);
1379                        continue;
1380                    }
1381    
1382                    rgn->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1383                }
1384                if (!ignoredAll.empty()) {
1385                    Glib::ustring txt;
1386                    if (ignoredCritical.empty())
1387                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1388                    else if (ignoredMinor.empty())
1389                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1390                    else
1391                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1392                        ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1393                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1394                    Gtk::MessageDialog msg(txt, false, type);
1395                    msg.run();
1396                }
1397            }
1398        } catch (RIFF::Exception e) {
1399            Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1400            msg.run();
1401        } catch (...) {
1402            Glib::ustring txt = _("An unknown exception occurred!");
1403            Gtk::MessageDialog msg(txt, false, Gtk::MESSAGE_ERROR);
1404            msg.run();
1405        }
1406        refresh_all();
1407    }
1408    
1409    void DimRegionChooser::delete_dimension_zone() {
1410        printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1411        try {
1412            if (!modifyallregions) {
1413                region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1414            } else {
1415                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
1416                gig::dimension_def_t* pMaindimdef = region->GetDimensionDefinition(maindimtype);
1417                assert(pMaindimdef != NULL);
1418                // retain structure by value since the original region will be
1419                // modified in the loop below as well
1420                gig::dimension_def_t maindimdef = *pMaindimdef;
1421                std::vector<gig::Region*> ignoredAll;
1422                std::vector<gig::Region*> ignoredMinor;
1423                std::vector<gig::Region*> ignoredCritical;
1424                gig::Region* rgn = NULL;
1425                for (int key = 0; key < 128; ++key) {
1426                    if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
1427                    rgn = instr->GetRegion(key);
1428    
1429                    // ignore all regions which do not exactly match the dimension
1430                    // layout of the selected region where this operation was emitted
1431                    gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(maindimtype);
1432                    if (!dimdef) {
1433                        ignoredAll.push_back(rgn);
1434                        ignoredMinor.push_back(rgn);
1435                        continue;
1436                    }
1437                    if (dimdef->zones != maindimdef.zones) {
1438                        ignoredAll.push_back(rgn);
1439                        ignoredCritical.push_back(rgn);
1440                        continue;
1441                    }
1442    
1443                    rgn->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1444                }
1445                if (!ignoredAll.empty()) {
1446                    Glib::ustring txt;
1447                    if (ignoredCritical.empty())
1448                        txt = ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type.");
1449                    else if (ignoredMinor.empty())
1450                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones!");
1451                    else
1452                        txt = ToString(ignoredCritical.size()) + _(" regions have been ignored due to different amount of dimension zones (and ") +
1453                              ToString(ignoredMinor.size()) + _(" regions have been ignored since they don't have that dimension type)!");
1454                    Gtk::MessageType type = (ignoredCritical.empty()) ? Gtk::MESSAGE_INFO : Gtk::MESSAGE_WARNING;
1455                    Gtk::MessageDialog msg(txt, false, type);
1456                    msg.run();
1457                }
1458            }
1459        } catch (RIFF::Exception e) {
1460            Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1461            msg.run();
1462        } catch (...) {
1463            Glib::ustring txt = _("An unknown exception occurred!");
1464            Gtk::MessageDialog msg(txt, false, Gtk::MESSAGE_ERROR);
1465            msg.run();
1466        }
1467        refresh_all();
1468    }
1469    
1470    // Cmd key on Mac, Ctrl key on all other OSs
1471    static const guint primaryKeyL =
1472        #if defined(__APPLE__)
1473        GDK_KEY_Meta_L;
1474        #else
1475        GDK_KEY_Control_L;
1476        #endif
1477    
1478    static const guint primaryKeyR =
1479        #if defined(__APPLE__)
1480        GDK_KEY_Meta_R;
1481        #else
1482        GDK_KEY_Control_R;
1483        #endif
1484    
1485    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
1486    bool DimRegionChooser::onKeyPressed(Gdk::EventKey& _key) {
1487        GdkEventKey* key = _key.gobj();
1488    #else
1489    bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1490    #endif
1491        //printf("key down 0x%x\n", key->keyval);
1492        if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1493            multiSelectKeyDown = true;
1494        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1495            primaryKeyDown = true;
1496        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1497            shiftKeyDown = true;
1498    
1499        //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
1500        /*if (key->keyval == GDK_KEY_Left)
1501            select_prev_dimzone();
1502        if (key->keyval == GDK_KEY_Right)
1503            select_next_dimzone();
1504        if (key->keyval == GDK_KEY_Up)
1505            select_prev_dimension();
1506        if (key->keyval == GDK_KEY_Down)
1507            select_next_dimension();*/
1508        return false;
1509    }
1510    
1511    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
1512    bool DimRegionChooser::onKeyReleased(Gdk::EventKey& _key) {
1513        GdkEventKey* key = _key.gobj();
1514    #else
1515    bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1516    #endif
1517        //printf("key up 0x%x\n", key->keyval);
1518        if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1519            multiSelectKeyDown = false;
1520        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1521            primaryKeyDown = false;
1522        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1523            shiftKeyDown = false;
1524    
1525        if (!has_focus()) return false;
1526    
1527        // avoid conflict with Ctrl+Left and Ctrl+Right accelerators on mainwindow
1528        // (which is supposed to switch between regions)
1529        if (primaryKeyDown) return false;
1530    
1531        // avoid conflict with Alt+Shift+Left and Alt+Shift+Right accelerators on
1532        // mainwindow
1533        if (shiftKeyDown) return false;
1534    
1535        if (key->keyval == GDK_KEY_Left)
1536            select_prev_dimzone();
1537        if (key->keyval == GDK_KEY_Right)
1538            select_next_dimzone();
1539        if (key->keyval == GDK_KEY_Up)
1540            select_prev_dimension();
1541        if (key->keyval == GDK_KEY_Down)
1542            select_next_dimension();
1543    
1544        return false;
1545    }
1546    
1547    void DimRegionChooser::resetSelectedZones() {
1548        this->dimzones.clear();
1549        if (!region) {
1550            queue_draw(); // redraw required parts
1551            return;
1552        }
1553        if (maindimregno < 0 || maindimregno >= region->DimensionRegions) {
1554            queue_draw(); // redraw required parts
1555            return;
1556        }
1557        if (!region->pDimensionRegions[maindimregno]) {
1558            queue_draw(); // redraw required parts
1559            return;
1560        }
1561        gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1562    
1563        bool isValidZone;
1564        this->maindimcase = dimensionCaseOf(dimrgn);
1565    
1566        for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1567             it != this->maindimcase.end(); ++it)
1568        {
1569            this->dimzones[it->first].insert(it->second);
1570        }
1571    
1572        // redraw required parts
1573        queue_draw();
1574    }
1575    
1576    bool DimRegionChooser::select_dimregion(gig::DimensionRegion* dimrgn) {
1577        if (!region) return false; //.selection failed
1578    
1579        for (int dr = 0; dr < region->DimensionRegions && region->pDimensionRegions[dr]; ++dr) {
1580            if (region->pDimensionRegions[dr] == dimrgn) {
1581                // reset dim region zone selection to the requested specific dim region case
1582                maindimregno = dr;
1583                resetSelectedZones();
1584    
1585                // emit signal that dimregion selection has changed, for external entities
1586                dimregion_selected();
1587    
1588                return true; // selection success
1589            }
1590        }
1591    
1592        return false; //.selection failed
1593    }
1594    
1595    void DimRegionChooser::select_next_dimzone(bool add) {
1596        select_dimzone_by_dir(+1, add);
1597    }
1598    
1599    void DimRegionChooser::select_prev_dimzone(bool add) {
1600        select_dimzone_by_dir(-1, add);
1601    }
1602    
1603    void DimRegionChooser::select_dimzone_by_dir(int dir, bool add) {
1604        if (!region) return;
1605        if (!region->Dimensions) return;
1606        if (focus_line < 0) focus_line = 0;
1607        if (focus_line >= region->Dimensions) focus_line = region->Dimensions - 1;
1608    
1609        maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1610        if (maindimtype == gig::dimension_none) {
1611            printf("maindimtype -> none\n");
1612            return;
1613        }
1614    
1615        // commented out: re-evaluate maindimcase, since it might not been reset from a previous instrument which causes errors if it got different dimension types
1616        //if (maindimcase.empty()) {
1617            maindimcase = dimensionCaseOf(region->pDimensionRegions[maindimregno]);
1618            if (maindimcase.empty()) {
1619                printf("caseOfDimregion(%d) -> empty\n", maindimregno);
1620                return;
1621            }
1622        //}
1623    
1624        int z = (dir > 0) ? maindimcase[maindimtype] + 1 : maindimcase[maindimtype] - 1;
1625        if (z < 0) z = 0;
1626        if (z >= region->pDimensionDefinitions[focus_line].zones)
1627            z = region->pDimensionDefinitions[focus_line].zones - 1;
1628    
1629        maindimcase[maindimtype] = z;
1630    
1631        ::gig::DimensionRegion* dr = dimensionRegionMatching(maindimcase, region);
1632        if (!dr) {
1633            printf("select_dimzone_by_dir(%d) -> !dr\n", dir);
1634            return;
1635      }      }
1636    
1637        maindimregno = getDimensionRegionIndex(dr);
1638    
1639        if (!add) {
1640            // reset selected dimregion zones
1641            dimzones.clear();
1642        }
1643        for (DimensionCase::const_iterator it = maindimcase.begin();
1644             it != maindimcase.end(); ++it)
1645        {
1646            dimzones[it->first].insert(it->second);
1647        }
1648    
1649        dimregion_selected();
1650    
1651        // disabled: would overwrite dimregno with wrong value
1652        //refresh_all();
1653        // so requesting just a raw repaint instead:
1654        queue_draw();
1655    }
1656    
1657    void DimRegionChooser::select_next_dimension() {
1658        if (!region) return;
1659        focus_line++;
1660        if (focus_line >= region->Dimensions)
1661            focus_line = region->Dimensions - 1;
1662        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1663        queue_draw();
1664    }
1665    
1666    void DimRegionChooser::select_prev_dimension() {
1667        if (!region) return;
1668        focus_line--;
1669        if (focus_line < 0)
1670            focus_line = 0;
1671        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1672        queue_draw();
1673    }
1674    
1675    gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {
1676        if (!region) return NULL;
1677        return region->pDimensionRegions[maindimregno];
1678  }  }

Legend:
Removed from v.2246  
changed lines
  Added in v.3364

  ViewVC Help
Powered by ViewVC