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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3105 - (show annotations) (download)
Fri Feb 10 18:40:26 2017 UTC (3 years, 1 month ago) by schoenebeck
File size: 30061 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-2014 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 <glibmmconfig.h>
21 // threads.h must be included first to be able to build with
22 // G_DISABLE_DEPRECATED
23 #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION == 31 && GLIBMM_MICRO_VERSION >= 2) || \
24 (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION > 31) || GLIBMM_MAJOR_VERSION > 2
25 #include <glibmm/threads.h>
26 #endif
27
28 #include "dimensionmanager.h"
29
30 #include <gtkmm/messagedialog.h>
31 #include <gtkmm/dialog.h>
32 #include <gtkmm/comboboxtext.h>
33 #include <gtkmm/spinbutton.h>
34 #include <gtkmm/table.h>
35
36 #include "global.h"
37 #include "compat.h"
38
39 // returns a human readable name of the given dimension type
40 Glib::ustring dimTypeAsString(gig::dimension_t d) {
41 char buf[32];
42 switch (d) {
43 case gig::dimension_none:
44 return _("None");
45 case gig::dimension_samplechannel:
46 return _("Sample Channel");
47 case gig::dimension_layer:
48 return _("Layer");
49 case gig::dimension_velocity:
50 return _("Velocity");
51 case gig::dimension_channelaftertouch:
52 return _("Aftertouch");
53 case gig::dimension_releasetrigger:
54 return _("Release Trigger");
55 case gig::dimension_keyboard:
56 return _("Keyswitching");
57 case gig::dimension_roundrobin:
58 return _("Round Robin");
59 case gig::dimension_random:
60 return _("Random Generator");
61 case gig::dimension_smartmidi:
62 return _("Smart MIDI");
63 case gig::dimension_roundrobinkeyboard:
64 return _("Keyboard Round Robin");
65 case gig::dimension_modwheel:
66 return _("Modulation Wheel");
67 case gig::dimension_breath:
68 return _("Breath Ctrl.");
69 case gig::dimension_foot:
70 return _("Foot Ctrl.");
71 case gig::dimension_portamentotime:
72 return _("Portamento Time Ctrl.");
73 case gig::dimension_effect1:
74 return _("Effect Ctrl. 1");
75 case gig::dimension_effect2:
76 return _("Effect Ctrl. 2");
77 case gig::dimension_genpurpose1:
78 return _("General Purpose Ctrl. 1");
79 case gig::dimension_genpurpose2:
80 return _("General Purpose Ctrl. 2");
81 case gig::dimension_genpurpose3:
82 return _("General Purpose Ctrl. 3");
83 case gig::dimension_genpurpose4:
84 return _("General Purpose Ctrl. 4");
85 case gig::dimension_sustainpedal:
86 return _("Sustain Pedal");
87 case gig::dimension_portamento:
88 return _("Portamento Ctrl.");
89 case gig::dimension_sostenutopedal:
90 return _("Sostenuto Pedal");
91 case gig::dimension_softpedal:
92 return _("Soft Pedal");
93 case gig::dimension_genpurpose5:
94 return _("General Purpose Ctrl. 5");
95 case gig::dimension_genpurpose6:
96 return _("General Purpose Ctrl. 6");
97 case gig::dimension_genpurpose7:
98 return _("General Purpose Ctrl. 7");
99 case gig::dimension_genpurpose8:
100 return _("General Purpose Ctrl. 8");
101 case gig::dimension_effect1depth:
102 return _("Effect 1 Depth");
103 case gig::dimension_effect2depth:
104 return _("Effect 2 Depth");
105 case gig::dimension_effect3depth:
106 return _("Effect 3 Depth");
107 case gig::dimension_effect4depth:
108 return _("Effect 4 Depth");
109 case gig::dimension_effect5depth:
110 return _("Effect 5 Depth");
111 default:
112 sprintf(buf, "Unknown Type (0x%x) !!!", d);
113 return buf;
114 }
115 }
116
117 // returns a human readable description of the given dimension
118 static Glib::ustring __dimDescriptionAsString(gig::dimension_t d) {
119 switch (d) {
120 case gig::dimension_none:
121 return _("Dimension not in use");
122 case gig::dimension_samplechannel:
123 return _("If used sample has more than one channel (thus is not mono)");
124 case gig::dimension_layer:
125 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
126 case gig::dimension_velocity:
127 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
128 case gig::dimension_channelaftertouch:
129 return _("Channel Key Pressure");
130 case gig::dimension_releasetrigger:
131 return _("Special dimension for triggering samples on releasing a key");
132 case gig::dimension_keyboard:
133 return _("Dimension for keyswitching (keyboard)");
134 case gig::dimension_roundrobin:
135 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
136 case gig::dimension_random:
137 return _("Different samples triggered each time a note is played, random order");
138 case gig::dimension_smartmidi:
139 return _("For MIDI tools like legato and repetition mode");
140 case gig::dimension_roundrobinkeyboard:
141 return _("Different samples triggered each time a note is played, any key advances the counter");
142 case gig::dimension_modwheel:
143 return _("MIDI Controller 1");
144 case gig::dimension_breath:
145 return _("MIDI Controller 2");
146 case gig::dimension_foot:
147 return _("MIDI Controller 4");
148 case gig::dimension_portamentotime:
149 return _("MIDI Controller 5");
150 case gig::dimension_effect1:
151 return _("MIDI Controller 12");
152 case gig::dimension_effect2:
153 return _("MIDI Controller 13");
154 case gig::dimension_genpurpose1:
155 return _("Slider, MIDI Controller 16");
156 case gig::dimension_genpurpose2:
157 return _("Slider, MIDI Controller 17");
158 case gig::dimension_genpurpose3:
159 return _("Slider, MIDI Controller 18");
160 case gig::dimension_genpurpose4:
161 return _("Slider, MIDI Controller 19");
162 case gig::dimension_sustainpedal:
163 return _("MIDI Controller 64");
164 case gig::dimension_portamento:
165 return _("MIDI Controller 65");
166 case gig::dimension_sostenutopedal:
167 return _("MIDI Controller 66");
168 case gig::dimension_softpedal:
169 return _("MIDI Controller 67");
170 case gig::dimension_genpurpose5:
171 return _("Button, MIDI Controller 80");
172 case gig::dimension_genpurpose6:
173 return _("Button, MIDI Controller 81");
174 case gig::dimension_genpurpose7:
175 return _("Button, MIDI Controller 82");
176 case gig::dimension_genpurpose8:
177 return _("Button, MIDI Controller 83");
178 case gig::dimension_effect1depth:
179 return _("MIDI Controller 91");
180 case gig::dimension_effect2depth:
181 return _("MIDI Controller 92");
182 case gig::dimension_effect3depth:
183 return _("MIDI Controller 93");
184 case gig::dimension_effect4depth:
185 return _("MIDI Controller 94");
186 case gig::dimension_effect5depth:
187 return _("MIDI Controller 95");
188 default:
189 return _("Please report this !!!");
190 }
191 }
192
193 DimTypeCellRenderer::DimTypeCellRenderer() :
194 Glib::ObjectBase(typeid(DimTypeCellRenderer)),
195 Gtk::CellRendererText(),
196 m_propertyDimType(*this, "gigdimension_t", gig::dimension_none),
197 m_propertyUsageCount(*this, "intusagecount", 0),
198 m_propertyTotalRegions(*this, "inttotalregions", 0)
199 {
200 propertyDimType().signal_changed().connect(
201 sigc::mem_fun(*this, &DimTypeCellRenderer::typeChanged)
202 );
203 propertyUsageCount().signal_changed().connect(
204 sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
205 );
206 propertyTotalRegions().signal_changed().connect(
207 sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
208 );
209 }
210
211 void DimTypeCellRenderer::typeChanged() {
212 gig::dimension_t type = propertyDimType();
213 Glib::ustring s = dimTypeAsString(type);
214 property_text() = s;
215 }
216
217 void DimTypeCellRenderer::statsChanged() {
218 int usageCount = propertyUsageCount();
219 int totalRegions = propertyTotalRegions();
220 bool bDimensionExistsOnAllRegions = (usageCount == totalRegions);
221 property_foreground() = ((bDimensionExistsOnAllRegions) ? "black" : "gray");
222 }
223
224 IntSetCellRenderer::IntSetCellRenderer() :
225 Glib::ObjectBase(typeid(IntSetCellRenderer)),
226 Gtk::CellRendererText(),
227 m_propertyValue(*this, "stdintset", std::set<int>())
228 {
229 propertyValue().signal_changed().connect(
230 sigc::mem_fun(*this, &IntSetCellRenderer::valueChanged)
231 );
232 }
233
234 void IntSetCellRenderer::valueChanged() {
235 Glib::ustring s;
236 std::set<int> v = propertyValue();
237 for (std::set<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
238 s += ToString(*it);
239 if (*it != *v.rbegin()) s += "|";
240 }
241 property_text() = s;
242 property_foreground() = (v.size() > 1) ? "gray" : "black";
243 }
244
245 DimensionManager::DimensionManager() :
246 addButton(_("_Add"), true),
247 removeButton(_("_Remove"), true),
248 allRegionsCheckBox(_("All Regions"))
249 {
250 ignoreColumnClicked = true;
251
252 set_title(_("Dimensions of selected Region"));
253 add(vbox);
254 scrolledWindow.add(treeView);
255 vbox.pack_start(scrolledWindow);
256 scrolledWindow.show();
257 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
258 buttonBox.set_layout(Gtk::BUTTONBOX_END);
259 buttonBox.set_border_width(5);
260 buttonBox.show();
261 buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
262 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
263 buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
264 addButton.show();
265 removeButton.show();
266 allRegionsCheckBox.set_tooltip_text(
267 _("Enable this if you want to edit dimensions of all regions simultaniously.")
268 );
269
270 // setup the table
271 refTableModel = Gtk::ListStore::create(tableModel);
272 treeView.set_model(refTableModel);
273 treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
274 treeView.append_column(_("Bits"), m_cellRendererIntSet);
275 treeView.append_column(_("Zones"), m_cellRendererIntSet);
276 treeView.append_column(_("Description"), tableModel.m_description);
277 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyDimType(), tableModel.m_type);
278 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyUsageCount(), tableModel.m_usageCount);
279 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyTotalRegions(), tableModel.m_totalRegions);
280 treeView.get_column(1)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_bits);
281 treeView.get_column(2)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_zones);
282 treeView.show();
283
284 treeView.signal_cursor_changed().connect(
285 sigc::mem_fun(*this, &DimensionManager::onColumnClicked)
286 );
287
288 addButton.signal_clicked().connect(
289 sigc::mem_fun(*this, &DimensionManager::addDimension)
290 );
291
292 removeButton.signal_clicked().connect(
293 sigc::mem_fun(*this, &DimensionManager::removeDimension)
294 );
295 allRegionsCheckBox.signal_toggled().connect(
296 sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
297 );
298
299 show_all_children();
300
301 resize(460,300);
302 }
303
304 bool DimensionManager::allRegions() const {
305 return allRegionsCheckBox.get_active();
306 }
307
308 void DimensionManager::onAllRegionsCheckBoxToggled() {
309 set_title(
310 allRegions() ? _("Dimensions of all Regions") : _("Dimensions of selected Region")
311 );
312 treeView.set_tooltip_text(
313 allRegions()
314 ? _("Dimensions and numbers in gray indicates a difference among the individual regions.")
315 : _("You are currently only viewing dimensions of the currently selected region.")
316 );
317 refreshManager();
318 }
319
320 // following two data types are just used in DimensionManager::refresManager(),
321 // due to the maps template nature however, they must be declared at global
322 // space to avoid compilation errors
323 struct _DimDef {
324 std::set<int> bits;
325 std::set<int> zones;
326 int usageCount;
327 };
328 typedef std::map<gig::dimension_t, _DimDef> _Dimensions;
329
330 // update all GUI elements according to current gig::Region informations
331 void DimensionManager::refreshManager() {
332 set_sensitive(false);
333 refTableModel->clear();
334 if (allRegions()) {
335 if (region) {
336 _Dimensions dims;
337 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
338 int iRegionsCount = 0;
339 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
340 for (uint i = 0; i < rgn->Dimensions; i++) {
341 gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
342 dims[dim->dimension].bits.insert(dim->bits);
343 dims[dim->dimension].zones.insert(dim->zones);
344 dims[dim->dimension].usageCount++;
345 }
346 }
347 for (_Dimensions::const_iterator it = dims.begin(); it != dims.end(); ++it) {
348 Gtk::TreeModel::Row row = *(refTableModel->append());
349 row[tableModel.m_type] = it->first;
350 row[tableModel.m_bits] = it->second.bits;
351 row[tableModel.m_zones] = it->second.zones;
352 row[tableModel.m_description] = __dimDescriptionAsString(it->first);
353 row[tableModel.m_usageCount] = it->second.usageCount;
354 row[tableModel.m_totalRegions] = iRegionsCount;
355 }
356 }
357 } else {
358 if (region) {
359 for (uint i = 0; i < region->Dimensions; i++) {
360 gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
361 Gtk::TreeModel::Row row = *(refTableModel->append());
362 std::set<int> vBits;
363 vBits.insert(dim->bits);
364 row[tableModel.m_bits] = vBits;
365 std::set<int> vZones;
366 vZones.insert(dim->zones);
367 row[tableModel.m_zones] = vZones;
368 row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
369 row[tableModel.m_type] = dim->dimension;
370 row[tableModel.m_usageCount] = 1;
371 row[tableModel.m_totalRegions] = 1;
372 }
373 }
374 }
375 set_sensitive(region);
376 }
377
378 void DimensionManager::show(gig::Region* region) {
379 ignoreColumnClicked = true;
380 this->region = region;
381 refreshManager();
382 Gtk::Window::show();
383 deiconify();
384 ignoreColumnClicked = false;
385 }
386
387 void DimensionManager::set_region(gig::Region* region) {
388 ignoreColumnClicked = true;
389 this->region = region;
390 refreshManager();
391 ignoreColumnClicked = false;
392 }
393
394 void DimensionManager::onColumnClicked() {
395 printf("DimensionManager::onColumnClicked()\n");
396
397 //FIXME: BUG: this method is currently very unreliably called, it should actually be called when the user selects another column, it is ATM however also called when the table content changed programmatically causing the dialog below to popup at undesired times !
398
399 //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
400 if (ignoreColumnClicked) {
401 ignoreColumnClicked = false;
402 return;
403 }
404 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
405 // prevents app to crash if this dialog is closed
406 if (!get_visible())
407 return;
408 #else
409 # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
410 #endif
411
412 #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
413 if (!is_visible()) return;
414 #endif
415
416 Gtk::TreeModel::Path path;
417 Gtk::TreeViewColumn* focus_column;
418 treeView.get_cursor(path, focus_column);
419 //const int row = path[0];
420 if (focus_column == treeView.get_column(0)) {
421 Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
422 if (!it) return;
423 Gtk::TreeModel::Row row = *it;
424 gig::dimension_t oldType = row[tableModel.m_type];
425
426 Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
427 int oldTypeIndex = -1;
428 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
429 for (int i = 0x01, count = 0; i < 0xff; i++) {
430 Glib::ustring sType =
431 dimTypeAsString(static_cast<gig::dimension_t>(i));
432 if (i == oldType) oldTypeIndex = count;
433 if (sType.find("Unknown") != 0) {
434 Gtk::TreeModel::Row row = *(refComboModel->append());
435 row[comboModel.m_type_id] = i;
436 row[comboModel.m_type_name] = sType;
437 count++;
438 }
439 }
440 Gtk::Table table(1, 2);
441 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
442 Gtk::ComboBox comboDimType;
443 comboDimType.set_model(refComboModel);
444 comboDimType.pack_start(comboModel.m_type_id);
445 comboDimType.pack_start(comboModel.m_type_name);
446 table.attach(labelDimType, 0, 1, 0, 1);
447 table.attach(comboDimType, 1, 2, 0, 1);
448 dialog.get_vbox()->pack_start(table);
449
450 dialog.add_button(_("_OK"), 0);
451 dialog.add_button(_("_Cancel"), 1);
452 dialog.show_all_children();
453
454 comboDimType.set_active(oldTypeIndex);
455
456 if (!dialog.run()) { // OK selected ...
457 ignoreColumnClicked = true;
458 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
459 if (!iterType) return;
460 Gtk::TreeModel::Row rowType = *iterType;
461 if (!rowType) return;
462 int iTypeID = rowType[comboModel.m_type_id];
463 gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
464 if (newType == oldType) return;
465 //printf("change 0x%x -> 0x%x\n", oldType, newType);
466
467 // assemble the list of regions where the selected dimension type
468 // shall be changed
469 std::vector<gig::Region*> vRegions;
470 if (allRegions()) {
471 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
472 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
473 if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
474 }
475 } else vRegions.push_back(region);
476
477 std::set<Glib::ustring> errors;
478
479 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
480 gig::Region* region = vRegions[iRgn];
481 try {
482 // notify everybody that we're going to update the region
483 region_to_be_changed_signal.emit(region);
484 // change the dimension type on that region
485 region->SetDimensionType(oldType, newType);
486 // let everybody know there was a change
487 region_changed_signal.emit(region);
488 } catch (RIFF::Exception e) {
489 // notify that the changes are over (i.e. to avoid dead locks)
490 region_changed_signal.emit(region);
491 Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
492 if (vRegions.size() == 1) {
493 // show error message directly
494 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
495 msg.run();
496 } else {
497 // remember error, they are shown after all regions have been processed
498 errors.insert(txt);
499 }
500 }
501 }
502 // update all GUI elements
503 refreshManager();
504
505 if (!errors.empty()) {
506 Glib::ustring txt = _(
507 "The following errors occurred while trying to change the dimension type on all regions:"
508 );
509 txt += "\n\n";
510 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
511 it != errors.end(); ++it)
512 {
513 txt += "-> " + *it + "\n";
514 }
515 txt += "\n";
516 txt += _(
517 "You might also want to check the console for further warnings and "
518 "error messages."
519 );
520 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
521 msg.run();
522 }
523 }
524 } else if (focus_column == treeView.get_column(1) || focus_column == treeView.get_column(2)) {
525 Glib::ustring txt = _("Right-click on a specific dimension zone of the dimension region selector to delete or split that particular dimension zone!");
526 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_INFO);
527 msg.run();
528 }
529 }
530
531 void DimensionManager::addDimension() {
532 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
533 // add dimension type combo box to the dialog
534 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
535 for (int i = 0x01; i < 0xff; i++) {
536 Glib::ustring sType =
537 dimTypeAsString(static_cast<gig::dimension_t>(i));
538 if (sType.find("Unknown") != 0) {
539 Gtk::TreeModel::Row row = *(refComboModel->append());
540 row[comboModel.m_type_id] = i;
541 row[comboModel.m_type_name] = sType;
542 }
543 }
544 Gtk::Table table(2, 2);
545 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
546 Gtk::ComboBox comboDimType;
547 comboDimType.set_model(refComboModel);
548 comboDimType.pack_start(comboModel.m_type_id);
549 comboDimType.pack_start(comboModel.m_type_name);
550 Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
551 table.attach(labelDimType, 0, 1, 0, 1);
552 table.attach(comboDimType, 1, 2, 0, 1);
553 table.attach(labelZones, 0, 1, 1, 2);
554 dialog.get_vbox()->pack_start(table);
555
556 // number of zones: use a combo box with fix values for gig
557 // v2 and a spin button for v3
558 Gtk::ComboBoxText comboZones;
559 Gtk::SpinButton spinZones;
560 bool version2 = false;
561 if (region) {
562 gig::File* file = (gig::File*)region->GetParent()->GetParent();
563 version2 = file->pVersion && file->pVersion->major == 2;
564 }
565 if (version2) {
566 for (int i = 1; i <= 5; i++) {
567 char buf[3];
568 sprintf(buf, "%d", 1 << i);
569 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
570 comboZones.append_text(buf);
571 #else
572 comboZones.append(buf);
573 #endif
574 }
575 table.attach(comboZones, 1, 2, 1, 2);
576 } else {
577 spinZones.set_increments(1, 8);
578 spinZones.set_numeric(true);
579 spinZones.set_range(2, 128);
580 spinZones.set_value(2);
581 table.attach(spinZones, 1, 2, 1, 2);
582 }
583
584 dialog.add_button(_("_OK"), 0);
585 dialog.add_button(_("_Cancel"), 1);
586 dialog.show_all_children();
587
588 if (!dialog.run()) { // OK selected ...
589 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
590 if (!iterType) return;
591 Gtk::TreeModel::Row rowType = *iterType;
592 if (!rowType) return;
593 int iTypeID = rowType[comboModel.m_type_id];
594 gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
595 gig::dimension_def_t dim;
596 dim.dimension = type;
597
598 if (version2) {
599 if (comboZones.get_active_row_number() < 0) return;
600 dim.bits = comboZones.get_active_row_number() + 1;
601 dim.zones = 1 << dim.bits;
602 } else {
603 dim.zones = spinZones.get_value_as_int();
604 dim.bits = zoneCountToBits(dim.zones);
605 }
606
607 // assemble the list of regions where the selected dimension shall be
608 // added to
609 std::vector<gig::Region*> vRegions;
610 if (allRegions()) {
611 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
612 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
613 if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
614 }
615 } else vRegions.push_back(region);
616
617 std::set<Glib::ustring> errors;
618
619 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
620 gig::Region* region = vRegions[iRgn];
621 try {
622 printf(
623 "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
624 dim.dimension, dim.bits, dim.zones
625 );
626 // notify everybody that we're going to update the region
627 region_to_be_changed_signal.emit(region);
628 // add the new dimension to the region
629 // (implicitly creates new dimension regions)
630 region->AddDimension(&dim);
631 // let everybody know there was a change
632 region_changed_signal.emit(region);
633 } catch (RIFF::Exception e) {
634 // notify that the changes are over (i.e. to avoid dead locks)
635 region_changed_signal.emit(region);
636 Glib::ustring txt = _("Could not add dimension: ") + e.Message;
637 if (vRegions.size() == 1) {
638 // show error message directly
639 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
640 msg.run();
641 } else {
642 // remember error, they are shown after all regions have been processed
643 errors.insert(txt);
644 }
645 }
646 }
647 // update all GUI elements
648 refreshManager();
649
650 if (!errors.empty()) {
651 Glib::ustring txt = _(
652 "The following errors occurred while trying to create the dimension on all regions:"
653 );
654 txt += "\n\n";
655 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
656 it != errors.end(); ++it)
657 {
658 txt += "-> " + *it + "\n";
659 }
660 txt += "\n";
661 txt += _(
662 "You might also want to check the console for further warnings and "
663 "error messages."
664 );
665 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
666 msg.run();
667 }
668 }
669 }
670
671 void DimensionManager::removeDimension() {
672 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
673 Gtk::TreeModel::iterator it = sel->get_selected();
674 if (it) {
675 Gtk::TreeModel::Row row = *it;
676 gig::dimension_t type = row[tableModel.m_type];
677
678 // assemble the list of regions where the selected dimension shall be
679 // added to
680 std::vector<gig::Region*> vRegions;
681 if (allRegions()) {
682 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
683 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
684 if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
685 }
686 } else vRegions.push_back(region);
687
688 std::set<Glib::ustring> errors;
689
690 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
691 gig::Region* region = vRegions[iRgn];
692 gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
693 try {
694 // notify everybody that we're going to update the region
695 region_to_be_changed_signal.emit(region);
696 // remove selected dimension
697 region->DeleteDimension(dim);
698 // let everybody know there was a change
699 region_changed_signal.emit(region);
700 } catch (RIFF::Exception e) {
701 // notify that the changes are over (i.e. to avoid dead locks)
702 region_changed_signal.emit(region);
703 Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
704 if (vRegions.size() == 1) {
705 // show error message directly
706 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
707 msg.run();
708 } else {
709 // remember error, they are shown after all regions have been processed
710 errors.insert(txt);
711 }
712 }
713 }
714 // update all GUI elements
715 refreshManager();
716
717 if (!errors.empty()) {
718 Glib::ustring txt = _(
719 "The following errors occurred while trying to remove the dimension from all regions:"
720 );
721 txt += "\n\n";
722 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
723 it != errors.end(); ++it)
724 {
725 txt += "-> " + *it + "\n";
726 }
727 txt += "\n";
728 txt += _(
729 "You might also want to check the console for further warnings and "
730 "error messages."
731 );
732 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
733 msg.run();
734 }
735 }
736 }

  ViewVC Help
Powered by ViewVC