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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3105 - (show annotations) (download)
Fri Feb 10 18:40:26 2017 UTC (7 years, 1 month ago) by schoenebeck
File size: 52685 byte(s)
* Implemented deleting dimension region zones of all regions at once, which
  is controlled by checkbox "all regions".
* Implemented splitting up dimension region zones of all regions at once,
  which is controlled by checkbox "all regions".
* Bumped version (1.0.0.svn26).

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

  ViewVC Help
Powered by ViewVC