/[svn]/gigedit/trunk/src/gigedit/dimregionchooser.cpp
ViewVC logotype

Annotation of /gigedit/trunk/src/gigedit/dimregionchooser.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3089 - (hide annotations) (download)
Sun Jan 15 19:18:39 2017 UTC (7 years, 3 months ago) by schoenebeck
File size: 46979 byte(s)
* Implemented resizing multiple dimension region zones at once, which is
  controlled by the infamous checkbox trio "all regions",
  "all dimension splits" and "both channels".
* Bumped version (1.0.0.svn25).

1 schoenebeck 1225 /*
2 schoenebeck 3089 * Copyright (C) 2006-2017 Andreas Persson
3 schoenebeck 1225 *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License as
6     * published by the Free Software Foundation; either version 2, or (at
7     * your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful, but
10     * WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     * General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with program; see the file COPYING. If not, write to the Free
16     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17     * 02110-1301 USA.
18     */
19    
20 persson 2844 #include <gtkmm/box.h>
21 schoenebeck 1225 #include "dimregionchooser.h"
22 persson 2151 #include <cairomm/context.h>
23 schoenebeck 1225 #include <gdkmm/cursor.h>
24 persson 2151 #include <gdkmm/general.h>
25 persson 2470 #include <glibmm/stringutils.h>
26 schoenebeck 2556 #include <glibmm/ustring.h>
27     #include <gtkmm/messagedialog.h>
28 schoenebeck 3089 #include <assert.h>
29 schoenebeck 1225
30 persson 1831 #include "global.h"
31    
32 schoenebeck 2626 // taken from gdk/gdkkeysyms.h
33     // (define on demand, to avoid unnecessary dev lib package build dependency)
34     #ifndef GDK_KEY_Control_L
35     # define GDK_KEY_Control_L 0xffe3
36     #endif
37     #ifndef GDK_KEY_Control_R
38     # define GDK_KEY_Control_R 0xffe4
39     #endif
40    
41     static std::map<gig::dimension_t,int> caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
42     std::map<gig::dimension_t,int> dimCase;
43     if (!dr) {
44     *isValidZone = false;
45     return dimCase;
46     }
47    
48     gig::Region* rgn = (gig::Region*) dr->GetParent();
49    
50     // find the dimension region index of the passed dimension region
51     int drIndex;
52     for (drIndex = 0; drIndex < 256; ++drIndex)
53     if (rgn->pDimensionRegions[drIndex] == dr)
54     break;
55    
56     // not found in region, something's horribly wrong
57     if (drIndex == 256) {
58     fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");
59     *isValidZone = false;
60     return std::map<gig::dimension_t,int>();
61     }
62    
63     for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {
64     const int bits = rgn->pDimensionDefinitions[d].bits;
65     dimCase[rgn->pDimensionDefinitions[d].dimension] =
66     (drIndex >> baseBits) & ((1 << bits) - 1);
67     baseBits += bits;
68     // there are also DimensionRegion objects of unused zones, skip them
69     if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {
70     *isValidZone = false;
71     return std::map<gig::dimension_t,int>();
72     }
73     }
74    
75     *isValidZone = true;
76     return dimCase;
77     }
78    
79     DimRegionChooser::DimRegionChooser(Gtk::Window& window) :
80 persson 2169 red("#8070ff"),
81     black("black"),
82     white("white")
83 schoenebeck 1225 {
84     instrument = 0;
85     region = 0;
86 schoenebeck 2626 maindimregno = -1;
87 schoenebeck 1225 focus_line = 0;
88     resize.active = false;
89     cursor_is_resize = false;
90 schoenebeck 2627 h = 24;
91 schoenebeck 2626 multiSelectKeyDown = false;
92 schoenebeck 3089 modifybothchannels = modifyalldimregs = modifybothchannels = false;
93 persson 2151 set_can_focus();
94 schoenebeck 2556
95     actionGroup = Gtk::ActionGroup::create();
96     actionGroup->add(
97     Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone")),
98     sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
99     );
100     actionGroup->add(
101     Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone")),
102     sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
103     );
104    
105     uiManager = Gtk::UIManager::create();
106     uiManager->insert_action_group(actionGroup);
107     Glib::ustring ui_info =
108     "<ui>"
109     " <popup name='PopupMenuInsideDimRegion'>"
110     " <menuitem action='SplitDimZone'/>"
111     " <menuitem action='DeleteDimZone'/>"
112     " </popup>"
113     // " <popup name='PopupMenuOutsideDimRegion'>"
114     // " <menuitem action='Add'/>"
115     // " </popup>"
116     "</ui>";
117     uiManager->add_ui_from_string(ui_info);
118    
119     popup_menu_inside_dimregion = dynamic_cast<Gtk::Menu*>(
120     uiManager->get_widget("/PopupMenuInsideDimRegion"));
121     // popup_menu_outside_dimregion = dynamic_cast<Gtk::Menu*>(
122     // uiManager->get_widget("/PopupMenuOutsideDimRegion"));
123    
124 schoenebeck 1225 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
125     Gdk::POINTER_MOTION_HINT_MASK);
126    
127 persson 2246 labels_changed = true;
128 schoenebeck 2556
129 schoenebeck 2626 set_tooltip_text(_(
130     "Right click here for options on altering dimension zones. Press and "
131     "hold CTRL key for selecting multiple dimension zones simultaniously."
132     ));
133    
134     window.signal_key_press_event().connect(
135     sigc::mem_fun(*this, &DimRegionChooser::onKeyPressed)
136     );
137     window.signal_key_release_event().connect(
138     sigc::mem_fun(*this, &DimRegionChooser::onKeyReleased)
139     );
140 schoenebeck 1225 }
141    
142     DimRegionChooser::~DimRegionChooser()
143     {
144     }
145    
146 schoenebeck 3089 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    
158 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
159     bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
160 schoenebeck 1225 {
161 persson 2246 double clipx1 = e->area.x;
162     double clipx2 = e->area.x + e->area.width;
163     double clipy1 = e->area.y;
164     double clipy2 = e->area.y + e->area.height;
165    
166     const Cairo::RefPtr<Cairo::Context>& cr =
167     get_window()->create_cairo_context();
168     #else
169 persson 2169 bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
170     {
171 persson 2246 double clipx1, clipx2, clipy1, clipy2;
172     cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
173     #endif
174    
175 schoenebeck 1225 if (!region) return true;
176    
177     // This is where we draw on the window
178 persson 1623 int w = get_width();
179 schoenebeck 1225 Glib::RefPtr<Pango::Context> context = get_pango_context();
180    
181     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
182 persson 2151 cr->set_line_width(1);
183 schoenebeck 1225
184     int y = 0;
185 persson 2246 if (labels_changed || label_width - 10 > clipx1) {
186     // draw labels on the left (reflecting the dimension type)
187     double maxwidth = 0;
188     for (int i = 0 ; i < region->Dimensions ; i++) {
189     int nbZones = region->pDimensionDefinitions[i].zones;
190     if (nbZones) {
191     const char* dstr;
192     char dstrbuf[10];
193     switch (region->pDimensionDefinitions[i].dimension) {
194     case gig::dimension_none: dstr=_("none"); break;
195     case gig::dimension_samplechannel: dstr=_("samplechannel");
196     break;
197     case gig::dimension_layer: dstr=_("layer"); break;
198     case gig::dimension_velocity: dstr=_("velocity"); break;
199     case gig::dimension_channelaftertouch:
200     dstr=_("channelaftertouch"); break;
201     case gig::dimension_releasetrigger:
202     dstr=_("releasetrigger"); break;
203     case gig::dimension_keyboard: dstr=_("keyswitching"); break;
204     case gig::dimension_roundrobin: dstr=_("roundrobin"); break;
205     case gig::dimension_random: dstr=_("random"); break;
206     case gig::dimension_smartmidi: dstr=_("smartmidi"); break;
207     case gig::dimension_roundrobinkeyboard:
208     dstr=_("roundrobinkeyboard"); break;
209     case gig::dimension_modwheel: dstr=_("modwheel"); break;
210     case gig::dimension_breath: dstr=_("breath"); break;
211     case gig::dimension_foot: dstr=_("foot"); break;
212     case gig::dimension_portamentotime:
213     dstr=_("portamentotime"); break;
214     case gig::dimension_effect1: dstr=_("effect1"); break;
215     case gig::dimension_effect2: dstr=_("effect2"); break;
216     case gig::dimension_genpurpose1: dstr=_("genpurpose1"); break;
217     case gig::dimension_genpurpose2: dstr=_("genpurpose2"); break;
218     case gig::dimension_genpurpose3: dstr=_("genpurpose3"); break;
219     case gig::dimension_genpurpose4: dstr=_("genpurpose4"); break;
220     case gig::dimension_sustainpedal:
221     dstr=_("sustainpedal"); break;
222     case gig::dimension_portamento: dstr=_("portamento"); break;
223     case gig::dimension_sostenutopedal:
224     dstr=_("sostenutopedal"); break;
225     case gig::dimension_softpedal: dstr=_("softpedal"); break;
226     case gig::dimension_genpurpose5: dstr=_("genpurpose5"); break;
227     case gig::dimension_genpurpose6: dstr=_("genpurpose6"); break;
228     case gig::dimension_genpurpose7: dstr=_("genpurpose7"); break;
229     case gig::dimension_genpurpose8: dstr=_("genpurpose8"); break;
230     case gig::dimension_effect1depth:
231     dstr=_("effect1depth"); break;
232     case gig::dimension_effect2depth:
233     dstr=_("effect2depth"); break;
234     case gig::dimension_effect3depth:
235     dstr=_("effect3depth"); break;
236     case gig::dimension_effect4depth:
237     dstr=_("effect4depth"); break;
238     case gig::dimension_effect5depth:
239     dstr=_("effect5depth"); break;
240     default:
241     sprintf(dstrbuf, "%d",
242     region->pDimensionDefinitions[i].dimension);
243     dstr = dstrbuf;
244     break;
245     }
246     layout->set_text(dstr);
247 schoenebeck 1225
248 persson 2246 Pango::Rectangle rectangle = layout->get_logical_extents();
249     double text_w = double(rectangle.get_width()) / Pango::SCALE;
250     if (text_w > maxwidth) maxwidth = text_w;
251    
252     if (y + h > clipy1 && y < clipy2 && text_w >= clipx1) {
253     double text_h = double(rectangle.get_height()) /
254     Pango::SCALE;
255 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
256 persson 2246 const Gdk::Color fg = get_style()->get_fg(get_state());
257 persson 2169 #else
258 persson 2246 const Gdk::RGBA fg =
259     get_style_context()->get_color(get_state_flags());
260 persson 2169 #endif
261 persson 2246 Gdk::Cairo::set_source_rgba(cr, fg);
262     cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));
263 persson 2151 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
264 persson 2246 pango_cairo_show_layout(cr->cobj(), layout->gobj());
265 persson 2151 #else
266 persson 2246 layout->show_in_cairo_context(cr);
267 persson 2151 #endif
268 persson 2246 }
269     }
270     y += h;
271 schoenebeck 1225 }
272 persson 2246 label_width = int(maxwidth + 10);
273     labels_changed = false;
274 schoenebeck 1225 }
275 persson 2246 if (label_width >= clipx2) return true;
276 schoenebeck 1225
277     // draw dimensions' zones areas
278     y = 0;
279     int bitpos = 0;
280     for (int i = 0 ; i < region->Dimensions ; i++) {
281     int nbZones = region->pDimensionDefinitions[i].zones;
282     if (nbZones) {
283 schoenebeck 2626 const gig::dimension_t dimension = region->pDimensionDefinitions[i].dimension;
284    
285 persson 2246 if (y >= clipy2) break;
286     if (y + h > clipy1) {
287     // draw focus rectangle around dimension's label and zones
288     if (has_focus() && focus_line == i) {
289 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
290 schoenebeck 2627 Gdk::Rectangle farea(0, y, 150, h);
291 persson 2246 get_style()->paint_focus(get_window(), get_state(), farea,
292     *this, "",
293 schoenebeck 2627 0, y, label_width, h);
294 persson 2169 #else
295 persson 2246 get_style_context()->render_focus(cr,
296 schoenebeck 2627 0, y, label_width, h);
297 persson 2169 #endif
298 persson 2246 }
299 schoenebeck 1225
300 persson 2246 // draw top and bottom lines of dimension's zones
301     Gdk::Cairo::set_source_rgba(cr, black);
302     cr->move_to(label_width, y + 0.5);
303     cr->line_to(w, y + 0.5);
304     cr->move_to(w, y + h - 0.5);
305     cr->line_to(label_width, y + h - 0.5);
306     cr->stroke();
307 persson 2151
308 persson 2246 // erase whole dimension's zones area
309     Gdk::Cairo::set_source_rgba(cr, white);
310     cr->rectangle(label_width + 1, y + 1,
311     (w - label_width - 2), h - 2);
312     cr->fill();
313 schoenebeck 1225
314 persson 2246 int c = 0;
315 schoenebeck 2626 if (maindimregno >= 0) {
316 persson 2246 int mask =
317     ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<
318     bitpos);
319 schoenebeck 2626 c = maindimregno & mask; // mask away this dimension
320 schoenebeck 1225 }
321 persson 2246 bool customsplits =
322     ((region->pDimensionDefinitions[i].split_type ==
323     gig::split_type_normal &&
324     region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
325     (region->pDimensionDefinitions[i].dimension ==
326     gig::dimension_velocity &&
327     region->pDimensionRegions[c]->VelocityUpperLimit));
328 schoenebeck 1225
329 schoenebeck 2626 // draw dimension zones
330 persson 2246 Gdk::Cairo::set_source_rgba(cr, black);
331 schoenebeck 1225 if (customsplits) {
332 persson 2246 cr->move_to(label_width + 0.5, y + 1);
333     cr->line_to(label_width + 0.5, y + h - 1);
334 schoenebeck 2626 int prevX = label_width;
335 schoenebeck 2627 int prevUpperLimit = -1;
336 persson 2246
337 schoenebeck 1225 for (int j = 0 ; j < nbZones ; j++) {
338 schoenebeck 2626 // draw dimension zone's borders for custom splits
339 persson 2246 gig::DimensionRegion* d =
340     region->pDimensionRegions[c + (j << bitpos)];
341 schoenebeck 1225 int upperLimit = d->DimensionUpperLimits[i];
342     if (!upperLimit) upperLimit = d->VelocityUpperLimit;
343     int v = upperLimit + 1;
344 persson 2246 int x = int((w - label_width - 1) * v / 128.0 + 0.5) +
345     label_width;
346     if (x >= clipx2) break;
347     if (x < clipx1) continue;
348 schoenebeck 2626 Gdk::Cairo::set_source_rgba(cr, black);
349 persson 2246 cr->move_to(x + 0.5, y + 1);
350     cr->line_to(x + 0.5, y + h - 1);
351 schoenebeck 2626 cr->stroke();
352    
353     // draw fill for zone
354     bool isSelectedZone = this->dimzones[dimension].count(j);
355     Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);
356     cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
357     cr->fill();
358    
359     // draw text showing the beginning of the dimension zone
360     // as numeric value to the user
361     {
362     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
363 schoenebeck 2627 layout->set_text(Glib::Ascii::dtostr(prevUpperLimit+1));
364 schoenebeck 2626 Gdk::Cairo::set_source_rgba(cr, black);
365     // get the text dimensions
366     int text_width, text_height;
367     layout->get_pixel_size(text_width, text_height);
368     // move text to the left end of the dimension zone
369 schoenebeck 2627 cr->move_to(prevX + 3, y + (h - text_height) / 2);
370 schoenebeck 2626 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
371     pango_cairo_show_layout(cr->cobj(), layout->gobj());
372     #else
373     layout->show_in_cairo_context(cr);
374     #endif
375     }
376     // draw text showing the end of the dimension zone
377     // as numeric value to the user
378     {
379     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
380     layout->set_text(Glib::Ascii::dtostr(upperLimit));
381     Gdk::Cairo::set_source_rgba(cr, black);
382     // get the text dimensions
383     int text_width, text_height;
384     layout->get_pixel_size(text_width, text_height);
385     // move text to the left end of the dimension zone
386 schoenebeck 2627 cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
387 schoenebeck 2626 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
388     pango_cairo_show_layout(cr->cobj(), layout->gobj());
389     #else
390     layout->show_in_cairo_context(cr);
391     #endif
392     }
393    
394     prevX = x;
395     prevUpperLimit = upperLimit;
396 persson 2246 }
397     } else {
398 schoenebeck 2626 int prevX = 0;
399 persson 2246 for (int j = 0 ; j <= nbZones ; j++) {
400 schoenebeck 2626 // draw dimension zone's borders for normal splits
401 persson 2246 int x = int((w - label_width - 1) * j /
402     double(nbZones) + 0.5) + label_width;
403     if (x >= clipx2) break;
404     if (x < clipx1) continue;
405 schoenebeck 2626 Gdk::Cairo::set_source_rgba(cr, black);
406 persson 2246 cr->move_to(x + 0.5, y + 1);
407     cr->line_to(x + 0.5, y + h - 1);
408 schoenebeck 2626 cr->stroke();
409 persson 2246
410 schoenebeck 2626 if (j != 0) {
411     // draw fill for zone
412     bool isSelectedZone = this->dimzones[dimension].count(j-1);
413     Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);
414     cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
415 persson 2151 cr->fill();
416 schoenebeck 2462
417 schoenebeck 2626 // draw text showing the beginning of the dimension zone
418     // as numeric value to the user
419     {
420     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
421     layout->set_text(Glib::Ascii::dtostr((j-1) * 128/nbZones));
422     Gdk::Cairo::set_source_rgba(cr, black);
423     // get the text dimensions
424     int text_width, text_height;
425     layout->get_pixel_size(text_width, text_height);
426     // move text to the left end of the dimension zone
427 schoenebeck 2627 cr->move_to(prevX + 3, y + (h - text_height) / 2);
428 schoenebeck 2462 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
429 schoenebeck 2626 pango_cairo_show_layout(cr->cobj(), layout->gobj());
430 schoenebeck 2462 #else
431 schoenebeck 2626 layout->show_in_cairo_context(cr);
432 schoenebeck 2462 #endif
433 schoenebeck 2626 }
434     // draw text showing the end of the dimension zone
435     // as numeric value to the user
436     {
437     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
438     layout->set_text(Glib::Ascii::dtostr(j * 128/nbZones - 1));
439     Gdk::Cairo::set_source_rgba(cr, black);
440     // get the text dimensions
441     int text_width, text_height;
442     layout->get_pixel_size(text_width, text_height);
443     // move text to the left end of the dimension zone
444 schoenebeck 2627 cr->move_to(x - 3 - text_width, y + (h - text_height) / 2);
445 schoenebeck 2462 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
446 schoenebeck 2626 pango_cairo_show_layout(cr->cobj(), layout->gobj());
447 schoenebeck 2462 #else
448 schoenebeck 2626 layout->show_in_cairo_context(cr);
449 schoenebeck 2462 #endif
450 schoenebeck 2626 }
451     }
452     prevX = x;
453     }
454 schoenebeck 1225 }
455     }
456     y += h;
457     }
458     bitpos += region->pDimensionDefinitions[i].bits;
459     }
460    
461     return true;
462     }
463    
464     void DimRegionChooser::set_region(gig::Region* region)
465     {
466     this->region = region;
467 schoenebeck 2626 maindimregno = 0;
468 schoenebeck 1225 nbDimensions = 0;
469     if (region) {
470     int bitcount = 0;
471     for (int dim = 0 ; dim < region->Dimensions ; dim++) {
472     if (region->pDimensionDefinitions[dim].bits == 0) continue;
473     nbDimensions++;
474    
475 schoenebeck 2626 int z = std::min(maindimcase[region->pDimensionDefinitions[dim].dimension],
476 persson 1303 region->pDimensionDefinitions[dim].zones - 1);
477 schoenebeck 2626 maindimregno |= (z << bitcount);
478 schoenebeck 1225 bitcount += region->pDimensionDefinitions[dim].bits;
479     }
480     }
481 persson 1261 dimregion_selected();
482 schoenebeck 2627 set_size_request(800, region ? nbDimensions * h : 0);
483 persson 2169
484 persson 2246 labels_changed = true;
485 schoenebeck 1225 queue_resize();
486 schoenebeck 2626 queue_draw();
487 schoenebeck 1225 }
488    
489 schoenebeck 2556 void DimRegionChooser::refresh_all() {
490     set_region(region);
491     }
492 persson 1533
493     void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
494     std::set<gig::DimensionRegion*>& dimregs) const
495     {
496 schoenebeck 2626 for (int iDimRgn = 0; iDimRgn < 256; ++iDimRgn) {
497     gig::DimensionRegion* dimRgn = region->pDimensionRegions[iDimRgn];
498     if (!dimRgn) continue;
499     bool isValidZone;
500     std::map<gig::dimension_t,int> dimCase = caseOfDimRegion(dimRgn, &isValidZone);
501     if (!isValidZone) continue;
502     for (std::map<gig::dimension_t,int>::const_iterator it = dimCase.begin();
503     it != dimCase.end(); ++it)
504     {
505     if (stereo && it->first == gig::dimension_samplechannel) continue; // is selected
506    
507     std::map<gig::dimension_t, std::set<int> >::const_iterator itSelectedDimension =
508     this->dimzones.find(it->first);
509     if (itSelectedDimension != this->dimzones.end() &&
510     itSelectedDimension->second.count(it->second)) continue; // is selected
511    
512     goto notSelected;
513 persson 1533 }
514 schoenebeck 2626
515     dimregs.insert(dimRgn);
516    
517     notSelected:
518     ;
519 persson 1533 }
520     }
521    
522 persson 2246 void DimRegionChooser::update_after_resize()
523 schoenebeck 1225 {
524 schoenebeck 3089 const uint8_t upperLimit = resize.pos - 1;
525     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
526    
527     int bitpos = 0;
528     for (int j = 0 ; j < resize.dimension ; j++) {
529     bitpos += region->pDimensionDefinitions[j].bits;
530     }
531    
532     const int stereobitpos =
533     (modifybothchannels) ? baseBits(gig::dimension_samplechannel, region) : -1;
534    
535     // the velocity dimension must be handled differently than all other
536     // dimension types, because
537     // 1. it is currently the only dimension type which allows different zone
538     // sizes for different cases
539     // 2. for v2 format VelocityUpperLimit has to be set, DimensionUpperLimits for v3
540 persson 2246 if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
541     int mask =
542     ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
543 schoenebeck 2626 int c = maindimregno & mask; // mask away this dimension
544 schoenebeck 1225
545 persson 2246 if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
546     // the velocity dimension didn't previously have
547     // custom v3 splits, so we initialize all splits with
548     // default values
549     int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
550     for (int j = 0 ; j < nbZones ; j++) {
551     gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
552     d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
553 schoenebeck 1225 }
554 persson 2246 }
555     if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {
556     // the velocity dimension didn't previously have
557     // custom v2 splits, so we initialize all splits with
558     // default values
559     int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
560     for (int j = 0 ; j < nbZones ; j++) {
561     gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
562     d->VelocityUpperLimit = int(128.0 * (j + 1) / nbZones - 1);
563     }
564     }
565 schoenebeck 1225
566 schoenebeck 3089 int index = c + (resize.zone << bitpos);
567     gig::DimensionRegion* d = region->pDimensionRegions[index];
568 persson 2246 // update both v2 and v3 values
569 schoenebeck 3089 d->DimensionUpperLimits[resize.dimension] = upperLimit;
570     d->VelocityUpperLimit = upperLimit;
571     if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
572     gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
573     d->DimensionUpperLimits[resize.dimension] = upperLimit;
574     d->VelocityUpperLimit = upperLimit;
575     }
576 persson 2246
577 schoenebeck 3089 if (modifyalldimregs) {
578     gig::Region* rgn = NULL;
579     for (int key = 0; key < 128; ++key) {
580     if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
581     rgn = instr->GetRegion(key);
582     if (!modifyallregions && rgn != region) continue; // hack to reduce overall code amount a bit
583     gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
584     if (!dimdef) continue;
585     if (dimdef->zones != resize.dimensionDef.zones) continue;
586     const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
587     assert(iDim >= 0 && iDim < rgn->Dimensions);
588    
589     // the dimension layout might be completely different in this
590     // region, so we have to recalculate bitpos etc for this region
591     const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
592     const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
593     const int selection = resize.zone << bitpos;
594    
595     // primitive and inefficient loop implementation, however due to
596     // this circumstance the loop code is much simpler, and its lack
597     // of runtime efficiency should not be notable in practice
598     for (int idr = 0; idr < 256; ++idr) {
599     const int index = (idr & stencil) | selection;
600     assert(index >= 0 && index < 256);
601     gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
602     if (!dr) continue;
603     dr->DimensionUpperLimits[iDim] = upperLimit;
604     d->VelocityUpperLimit = upperLimit;
605     }
606     }
607     } else if (modifyallregions) { // implies modifyalldimregs is false ...
608     // resolve the precise case we need to modify for all other regions
609     DimensionCase dimCase = dimensionCaseOf(d);
610     // apply the velocity upper limit change to that resolved dim case
611     // of all regions ...
612     gig::Region* rgn = NULL;
613     for (int key = 0; key < 128; ++key) {
614     if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
615     rgn = instr->GetRegion(key);
616     gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
617     if (!dimdef) continue;
618     if (dimdef->zones != resize.dimensionDef.zones) continue;
619     const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
620     assert(iDim >= 0 && iDim < rgn->Dimensions);
621    
622     std::vector<gig::DimensionRegion*> dimrgns = dimensionRegionsMatching(dimCase, rgn);
623     for (int i = 0; i < dimrgns.size(); ++i) {
624     gig::DimensionRegion* dr = dimrgns[i];
625     dr->DimensionUpperLimits[iDim] = upperLimit;
626     dr->VelocityUpperLimit = upperLimit;
627     }
628     }
629     }
630 persson 2246 } else {
631     for (int i = 0 ; i < region->DimensionRegions ; ) {
632     if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
633     // the dimension didn't previously have custom
634     // limits, so we have to set default limits for
635     // all the dimension regions
636 schoenebeck 1225 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
637 persson 2246
638 schoenebeck 1225 for (int j = 0 ; j < nbZones ; j++) {
639 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[i + (j << bitpos)];
640 schoenebeck 1225 d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
641     }
642     }
643 schoenebeck 3089 int index = i + (resize.zone << bitpos);
644     gig::DimensionRegion* d = region->pDimensionRegions[index];
645     d->DimensionUpperLimits[resize.dimension] = upperLimit;
646     #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
647     if (modifybothchannels && stereobitpos >= 0) { // do the same for the other audio channel's dimregion ...
648     gig::DimensionRegion* d = region->pDimensionRegions[index ^ (1 << stereobitpos)];
649     d->DimensionUpperLimits[resize.dimension] = upperLimit;
650     }
651     #endif
652 persson 2246 int bitpos = 0;
653     int j;
654     for (j = 0 ; j < region->Dimensions ; j++) {
655     if (j != resize.dimension) {
656     int maxzones = 1 << region->pDimensionDefinitions[j].bits;
657     int dimj = (i >> bitpos) & (maxzones - 1);
658     if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
659 schoenebeck 1225 }
660 persson 2246 bitpos += region->pDimensionDefinitions[j].bits;
661 schoenebeck 1225 }
662 persson 2246 if (j == region->Dimensions) break;
663     i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
664 schoenebeck 1225 }
665 schoenebeck 3089
666     if (modifyallregions) { // TODO: this code block could be merged with the similar (and more generalized) code block of the velocity dimension above
667     gig::Region* rgn = NULL;
668     for (int key = 0; key < 128; ++key) {
669     if (!instr->GetRegion(key) || instr->GetRegion(key) == rgn) continue;
670     rgn = instr->GetRegion(key);
671     gig::dimension_def_t* dimdef = rgn->GetDimensionDefinition(resize.dimensionDef.dimension);
672     if (!dimdef) continue;
673     if (dimdef->zones != resize.dimensionDef.zones) continue;
674     const int iDim = getDimensionIndex(resize.dimensionDef.dimension, rgn);
675     assert(iDim >= 0 && iDim < rgn->Dimensions);
676    
677     // the dimension layout might be completely different in this
678     // region, so we have to recalculate bitpos etc for this region
679     const int bitpos = baseBits(resize.dimensionDef.dimension, rgn);
680     const int stencil = ~(((1 << dimdef->bits) - 1) << bitpos);
681     const int selection = resize.zone << bitpos;
682    
683     // this loop implementation is less efficient than the above's
684     // loop implementation (which skips unnecessary dimension regions)
685     // however this code is much simpler, and its lack of runtime
686     // efficiency should not be notable in practice
687     for (int idr = 0; idr < 256; ++idr) {
688     const int index = (idr & stencil) | selection;
689     assert(index >= 0 && index < 256);
690     gig::DimensionRegion* dr = rgn->pDimensionRegions[index];
691     if (!dr) continue;
692     dr->DimensionUpperLimits[iDim] = upperLimit;
693     }
694     }
695     }
696 persson 2246 }
697     }
698    
699     bool DimRegionChooser::on_button_release_event(GdkEventButton* event)
700     {
701     if (resize.active) {
702     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
703     get_window()->pointer_ungrab(event->time);
704     #else
705     Glib::wrap(event->device, true)->ungrab(event->time);
706     #endif
707     resize.active = false;
708    
709 persson 1261 region_changed();
710 schoenebeck 1225
711     if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
712     get_window()->set_cursor();
713     cursor_is_resize = false;
714     }
715     }
716     return true;
717     }
718    
719     bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
720     {
721 persson 1623 int w = get_width();
722 schoenebeck 1225 if (region && event->y < nbDimensions * h &&
723     event->x >= label_width && event->x < w) {
724    
725     if (is_in_resize_zone(event->x, event->y)) {
726 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
727 schoenebeck 1225 get_window()->pointer_grab(false,
728     Gdk::BUTTON_RELEASE_MASK |
729     Gdk::POINTER_MOTION_MASK |
730     Gdk::POINTER_MOTION_HINT_MASK,
731 persson 2169 Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
732     event->time);
733     #else
734     Glib::wrap(event->device, true)->grab(get_window(),
735     Gdk::OWNERSHIP_NONE,
736     false,
737     Gdk::BUTTON_RELEASE_MASK |
738     Gdk::POINTER_MOTION_MASK |
739     Gdk::POINTER_MOTION_HINT_MASK,
740     Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
741     event->time);
742     #endif
743 schoenebeck 1225 resize.active = true;
744     } else {
745     int ydim = int(event->y / h);
746     int dim;
747     for (dim = 0 ; dim < region->Dimensions ; dim++) {
748     if (region->pDimensionDefinitions[dim].bits == 0) continue;
749     if (ydim == 0) break;
750     ydim--;
751     }
752     int nbZones = region->pDimensionDefinitions[dim].zones;
753    
754     int z = -1;
755     int bitpos = 0;
756     for (int i = 0 ; i < dim ; i++) {
757     bitpos += region->pDimensionDefinitions[i].bits;
758     }
759    
760     int i = dim;
761 schoenebeck 2626 if (maindimregno < 0) maindimregno = 0;
762 schoenebeck 1225 int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
763 schoenebeck 2626 int c = this->maindimregno & mask; // mask away this dimension
764 schoenebeck 1225
765     bool customsplits =
766     ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
767     region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
768     (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&
769     region->pDimensionRegions[c]->VelocityUpperLimit));
770     if (customsplits) {
771     int val = int((event->x - label_width) * 128 / (w - label_width - 1));
772    
773     if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
774     for (z = 0 ; z < nbZones ; z++) {
775 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
776 schoenebeck 1225 if (val <= d->DimensionUpperLimits[i]) break;
777     }
778     } else {
779     for (z = 0 ; z < nbZones ; z++) {
780 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
781 schoenebeck 1225 if (val <= d->VelocityUpperLimit) break;
782     }
783     }
784     } else {
785     z = int((event->x - label_width) * nbZones / (w - label_width - 1));
786     }
787    
788     printf("dim=%d z=%d dimensionsource=%d split_type=%d zones=%d zone_size=%f\n", dim, z,
789     region->pDimensionDefinitions[dim].dimension,
790     region->pDimensionDefinitions[dim].split_type,
791     region->pDimensionDefinitions[dim].zones,
792     region->pDimensionDefinitions[dim].zone_size);
793 schoenebeck 2626 this->maindimcase[region->pDimensionDefinitions[dim].dimension] = z;
794     this->maindimregno = c | (z << bitpos);
795     this->maindimtype = region->pDimensionDefinitions[dim].dimension;
796 schoenebeck 1225
797 schoenebeck 2626 if (multiSelectKeyDown) {
798     if (dimzones[this->maindimtype].count(z)) {
799     if (dimzones[this->maindimtype].size() > 1) {
800     dimzones[this->maindimtype].erase(z);
801     }
802     } else {
803     dimzones[this->maindimtype].insert(z);
804     }
805     } else {
806     this->dimzones.clear();
807     for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
808     it != this->maindimcase.end(); ++it)
809     {
810     this->dimzones[it->first].insert(it->second);
811     }
812     }
813 schoenebeck 1225
814     focus_line = dim;
815     if (has_focus()) queue_draw();
816     else grab_focus();
817 persson 1261 dimregion_selected();
818 schoenebeck 2556
819     if (event->button == 3) {
820     printf("dimregion right click\n");
821     popup_menu_inside_dimregion->popup(event->button, event->time);
822     }
823 schoenebeck 2626
824     queue_draw();
825 schoenebeck 1225 }
826     }
827     return true;
828     }
829    
830     bool DimRegionChooser::on_motion_notify_event(GdkEventMotion* event)
831     {
832     Glib::RefPtr<Gdk::Window> window = get_window();
833     int x, y;
834     Gdk::ModifierType state = Gdk::ModifierType(0);
835     window->get_pointer(x, y, state);
836    
837     if (resize.active) {
838 persson 1623 int w = get_width();
839 schoenebeck 1225 int k = int((x - label_width) * 128.0 / (w - label_width - 1) + 0.5);
840    
841     if (k < resize.min) k = resize.min;
842     else if (k > resize.max) k = resize.max;
843    
844     if (k < 2) k = 2; // k is upper limit + 1, upper limit 0 is forbidden
845    
846     if (k != resize.pos) {
847     int prevx = int((w - label_width - 1) * resize.pos / 128.0 + 0.5) + label_width;
848     int x = int((w - label_width - 1) * k / 128.0 + 0.5) + label_width;
849     int y = resize.dimension * h;
850 persson 2246 int x1, x2;
851     if (k > resize.pos) {
852     x1 = prevx;
853     x2 = x;
854 schoenebeck 1225 } else {
855 persson 2246 x1 = x;
856     x2 = prevx;
857 schoenebeck 1225 }
858 persson 2246 Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
859 persson 2151
860 schoenebeck 1225 resize.pos = k;
861 persson 2246 update_after_resize();
862 schoenebeck 2626 get_window()->invalidate_rect(rect, false); // not sufficient ...
863     queue_draw(); // ... so do a complete redraw instead.
864 schoenebeck 1225 }
865     } else {
866     if (is_in_resize_zone(x, y)) {
867     if (!cursor_is_resize) {
868 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
869     window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
870     #else
871     window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
872     #endif
873 schoenebeck 1225 cursor_is_resize = true;
874     }
875     } else if (cursor_is_resize) {
876     window->set_cursor();
877     cursor_is_resize = false;
878     }
879     }
880     return true;
881     }
882    
883     bool DimRegionChooser::is_in_resize_zone(double x, double y)
884     {
885 persson 1623 int w = get_width();
886 schoenebeck 1225 if (region && y < nbDimensions * h && x >= label_width && x < w) {
887     int ydim = int(y / h);
888     int dim;
889     int bitpos = 0;
890     for (dim = 0 ; dim < region->Dimensions ; dim++) {
891     if (region->pDimensionDefinitions[dim].bits == 0) continue;
892     if (ydim == 0) break;
893     ydim--;
894     bitpos += region->pDimensionDefinitions[dim].bits;
895     }
896     int nbZones = region->pDimensionDefinitions[dim].zones;
897    
898     int c = 0;
899 schoenebeck 2626 if (maindimregno >= 0) {
900 schoenebeck 1225 int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
901 schoenebeck 2626 c = maindimregno & mask; // mask away this dimension
902 schoenebeck 1225 }
903     const bool customsplits =
904     ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&
905     region->pDimensionRegions[c]->DimensionUpperLimits[dim]) ||
906     (region->pDimensionDefinitions[dim].dimension == gig::dimension_velocity &&
907     region->pDimensionRegions[c]->VelocityUpperLimit));
908    
909     // dimensions of split_type_bit cannot be resized
910     if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {
911     int prev_limit = 0;
912     for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {
913 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
914 schoenebeck 1225 const int upperLimit =
915     (customsplits) ?
916     (d->DimensionUpperLimits[dim]) ?
917     d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
918     : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
919     int limit = upperLimit + 1;
920     int limitx = int((w - label_width - 1) * limit / 128.0 + 0.5) + label_width;
921     if (x <= limitx - 2) break;
922     if (x <= limitx + 2) {
923     resize.dimension = dim;
924 schoenebeck 3089 resize.dimensionDef = region->pDimensionDefinitions[dim];
925     resize.zone = iZone;
926 schoenebeck 1225 resize.pos = limit;
927     resize.min = prev_limit;
928    
929 schoenebeck 2626 int dr = (maindimregno >> bitpos) &
930 schoenebeck 1225 ((1 << region->pDimensionDefinitions[dim].bits) - 1);
931     resize.selected = dr == iZone ? resize.left :
932     dr == iZone + 1 ? resize.right : resize.none;
933    
934     iZone++;
935 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
936 schoenebeck 1225
937     const int upperLimit =
938     (customsplits) ?
939     (d->DimensionUpperLimits[dim]) ?
940     d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
941     : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
942    
943     int limit = upperLimit + 1;
944     resize.max = limit;
945     return true;
946     }
947     prev_limit = limit;
948     }
949     }
950     }
951     return false;
952     }
953    
954 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_dimregion_selected()
955 schoenebeck 1225 {
956 persson 1261 return dimregion_selected;
957 schoenebeck 1225 }
958    
959 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_region_changed()
960 persson 1261 {
961     return region_changed;
962     }
963    
964 schoenebeck 1225 bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
965     {
966 persson 2841 // TODO: check that region exists etc, that is, that it's possible
967     // to set focus
968 schoenebeck 1225 if (direction == Gtk::DIR_TAB_FORWARD ||
969     direction == Gtk::DIR_DOWN) {
970     if (!has_focus()) {
971     focus_line = 0;
972     grab_focus();
973     return true;
974     } else {
975     if (focus_line + 1 < region->Dimensions) {
976     focus_line++;
977     queue_draw();
978     return true;
979     } else {
980     return false;
981     }
982     }
983     } else if (direction == Gtk::DIR_TAB_BACKWARD ||
984     direction == Gtk::DIR_UP) {
985     if (!has_focus()) {
986     focus_line = region->Dimensions - 1;
987     grab_focus();
988     return true;
989     } else {
990     if (focus_line > 0) {
991     focus_line--;
992     queue_draw();
993     return true;
994     } else {
995     return false;
996     }
997     }
998     } else if (!has_focus()) {
999 persson 2841 // TODO: check that focus_line exists
1000 schoenebeck 1225 grab_focus();
1001     return true;
1002     } else {
1003 persson 2841 // TODO: increase or decrease value
1004 schoenebeck 1225 }
1005 persson 2841 return false;
1006 schoenebeck 1225 }
1007 schoenebeck 2556
1008 schoenebeck 2626 void DimRegionChooser::split_dimension_zone() {
1009     printf("split_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1010 schoenebeck 2556 try {
1011 schoenebeck 2626 region->SplitDimensionZone(maindimtype, maindimcase[maindimtype]);
1012 schoenebeck 2556 } catch (RIFF::Exception e) {
1013     Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1014     msg.run();
1015     } catch (...) {
1016     Glib::ustring txt = _("An unknown exception occurred!");
1017     Gtk::MessageDialog msg(txt, false, Gtk::MESSAGE_ERROR);
1018     msg.run();
1019     }
1020     refresh_all();
1021     }
1022    
1023     void DimRegionChooser::delete_dimension_zone() {
1024 schoenebeck 2626 printf("delete_dimension_zone() type=%d, zone=%d\n", maindimtype, maindimcase[maindimtype]);
1025 schoenebeck 2556 try {
1026 schoenebeck 2626 region->DeleteDimensionZone(maindimtype, maindimcase[maindimtype]);
1027 schoenebeck 2556 } catch (RIFF::Exception e) {
1028     Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
1029     msg.run();
1030     } catch (...) {
1031     Glib::ustring txt = _("An unknown exception occurred!");
1032     Gtk::MessageDialog msg(txt, false, Gtk::MESSAGE_ERROR);
1033     msg.run();
1034     }
1035     refresh_all();
1036     }
1037 schoenebeck 2626
1038     bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1039     //printf("key down\n");
1040     if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1041     multiSelectKeyDown = true;
1042 persson 2841 return false;
1043 schoenebeck 2626 }
1044    
1045     bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1046     //printf("key up\n");
1047     if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1048     multiSelectKeyDown = false;
1049 persson 2841 return false;
1050 schoenebeck 2626 }
1051    
1052 schoenebeck 2695 void DimRegionChooser::resetSelectedZones() {
1053     this->dimzones.clear();
1054     if (!region) {
1055     queue_draw(); // redraw required parts
1056     return;
1057     }
1058     if (maindimregno < 0 || maindimregno >= region->DimensionRegions) {
1059     queue_draw(); // redraw required parts
1060     return;
1061     }
1062     if (!region->pDimensionRegions[maindimregno]) {
1063     queue_draw(); // redraw required parts
1064     return;
1065     }
1066     gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1067    
1068     bool isValidZone;
1069     this->maindimcase = caseOfDimRegion(dimrgn, &isValidZone);
1070     if (!isValidZone) {
1071     queue_draw(); // redraw required parts
1072     return;
1073     }
1074    
1075     for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1076     it != this->maindimcase.end(); ++it)
1077     {
1078     this->dimzones[it->first].insert(it->second);
1079     }
1080    
1081     // redraw required parts
1082     queue_draw();
1083     }
1084    
1085     bool DimRegionChooser::select_dimregion(gig::DimensionRegion* dimrgn) {
1086     if (!region) return false; //.selection failed
1087    
1088     for (int dr = 0; dr < region->DimensionRegions && region->pDimensionRegions[dr]; ++dr) {
1089     if (region->pDimensionRegions[dr] == dimrgn) {
1090     // reset dim region zone selection to the requested specific dim region case
1091     maindimregno = dr;
1092     resetSelectedZones();
1093    
1094     // emit signal that dimregion selection has changed, for external entities
1095     dimregion_selected();
1096    
1097     return true; // selection success
1098     }
1099     }
1100    
1101     return false; //.selection failed
1102     }
1103    
1104 schoenebeck 2626 gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {
1105     if (!region) return NULL;
1106     return region->pDimensionRegions[maindimregno];
1107     }

  ViewVC Help
Powered by ViewVC