/[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 2844 - (show annotations) (download)
Sun Sep 20 08:49:40 2015 UTC (8 years, 6 months ago) by persson
File size: 28974 byte(s)
* allow building with gtkmm 2 and G/GDK/GTK_DISABLE_DEPRECATED

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/stock.h>
31 #include <gtkmm/messagedialog.h>
32 #include <gtkmm/dialog.h>
33 #include <gtkmm/comboboxtext.h>
34 #include <gtkmm/spinbutton.h>
35 #include <gtkmm/table.h>
36
37 #include "global.h"
38 #include "compat.h"
39
40 // returns a human readable name of the given dimension type
41 Glib::ustring dimTypeAsString(gig::dimension_t d) {
42 char buf[32];
43 switch (d) {
44 case gig::dimension_none:
45 return _("None");
46 case gig::dimension_samplechannel:
47 return _("Sample Channel");
48 case gig::dimension_layer:
49 return _("Layer");
50 case gig::dimension_velocity:
51 return _("Velocity");
52 case gig::dimension_channelaftertouch:
53 return _("Aftertouch");
54 case gig::dimension_releasetrigger:
55 return _("Release Trigger");
56 case gig::dimension_keyboard:
57 return _("Keyswitching");
58 case gig::dimension_roundrobin:
59 return _("Round Robin");
60 case gig::dimension_random:
61 return _("Random Generator");
62 case gig::dimension_smartmidi:
63 return _("Smart MIDI");
64 case gig::dimension_roundrobinkeyboard:
65 return _("Keyboard Round Robin");
66 case gig::dimension_modwheel:
67 return _("Modulation Wheel");
68 case gig::dimension_breath:
69 return _("Breath Ctrl.");
70 case gig::dimension_foot:
71 return _("Foot Ctrl.");
72 case gig::dimension_portamentotime:
73 return _("Portamento Time Ctrl.");
74 case gig::dimension_effect1:
75 return _("Effect Ctrl. 1");
76 case gig::dimension_effect2:
77 return _("Effect Ctrl. 2");
78 case gig::dimension_genpurpose1:
79 return _("General Purpose Ctrl. 1");
80 case gig::dimension_genpurpose2:
81 return _("General Purpose Ctrl. 2");
82 case gig::dimension_genpurpose3:
83 return _("General Purpose Ctrl. 3");
84 case gig::dimension_genpurpose4:
85 return _("General Purpose Ctrl. 4");
86 case gig::dimension_sustainpedal:
87 return _("Sustain Pedal");
88 case gig::dimension_portamento:
89 return _("Portamento Ctrl.");
90 case gig::dimension_sostenutopedal:
91 return _("Sostenuto Pedal");
92 case gig::dimension_softpedal:
93 return _("Soft Pedal");
94 case gig::dimension_genpurpose5:
95 return _("General Purpose Ctrl. 5");
96 case gig::dimension_genpurpose6:
97 return _("General Purpose Ctrl. 6");
98 case gig::dimension_genpurpose7:
99 return _("General Purpose Ctrl. 7");
100 case gig::dimension_genpurpose8:
101 return _("General Purpose Ctrl. 8");
102 case gig::dimension_effect1depth:
103 return _("Effect 1 Depth");
104 case gig::dimension_effect2depth:
105 return _("Effect 2 Depth");
106 case gig::dimension_effect3depth:
107 return _("Effect 3 Depth");
108 case gig::dimension_effect4depth:
109 return _("Effect 4 Depth");
110 case gig::dimension_effect5depth:
111 return _("Effect 5 Depth");
112 default:
113 sprintf(buf, "Unknown Type (0x%x) !!!", d);
114 return buf;
115 }
116 }
117
118 // returns a human readable description of the given dimension
119 static Glib::ustring __dimDescriptionAsString(gig::dimension_t d) {
120 switch (d) {
121 case gig::dimension_none:
122 return _("Dimension not in use");
123 case gig::dimension_samplechannel:
124 return _("If used sample has more than one channel (thus is not mono)");
125 case gig::dimension_layer:
126 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
127 case gig::dimension_velocity:
128 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
129 case gig::dimension_channelaftertouch:
130 return _("Channel Key Pressure");
131 case gig::dimension_releasetrigger:
132 return _("Special dimension for triggering samples on releasing a key");
133 case gig::dimension_keyboard:
134 return _("Dimension for keyswitching (keyboard)");
135 case gig::dimension_roundrobin:
136 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
137 case gig::dimension_random:
138 return _("Different samples triggered each time a note is played, random order");
139 case gig::dimension_smartmidi:
140 return _("For MIDI tools like legato and repetition mode");
141 case gig::dimension_roundrobinkeyboard:
142 return _("Different samples triggered each time a note is played, any key advances the counter");
143 case gig::dimension_modwheel:
144 return _("MIDI Controller 1");
145 case gig::dimension_breath:
146 return _("MIDI Controller 2");
147 case gig::dimension_foot:
148 return _("MIDI Controller 4");
149 case gig::dimension_portamentotime:
150 return _("MIDI Controller 5");
151 case gig::dimension_effect1:
152 return _("MIDI Controller 12");
153 case gig::dimension_effect2:
154 return _("MIDI Controller 13");
155 case gig::dimension_genpurpose1:
156 return _("Slider, MIDI Controller 16");
157 case gig::dimension_genpurpose2:
158 return _("Slider, MIDI Controller 17");
159 case gig::dimension_genpurpose3:
160 return _("Slider, MIDI Controller 18");
161 case gig::dimension_genpurpose4:
162 return _("Slider, MIDI Controller 19");
163 case gig::dimension_sustainpedal:
164 return _("MIDI Controller 64");
165 case gig::dimension_portamento:
166 return _("MIDI Controller 65");
167 case gig::dimension_sostenutopedal:
168 return _("MIDI Controller 66");
169 case gig::dimension_softpedal:
170 return _("MIDI Controller 67");
171 case gig::dimension_genpurpose5:
172 return _("Button, MIDI Controller 80");
173 case gig::dimension_genpurpose6:
174 return _("Button, MIDI Controller 81");
175 case gig::dimension_genpurpose7:
176 return _("Button, MIDI Controller 82");
177 case gig::dimension_genpurpose8:
178 return _("Button, MIDI Controller 83");
179 case gig::dimension_effect1depth:
180 return _("MIDI Controller 91");
181 case gig::dimension_effect2depth:
182 return _("MIDI Controller 92");
183 case gig::dimension_effect3depth:
184 return _("MIDI Controller 93");
185 case gig::dimension_effect4depth:
186 return _("MIDI Controller 94");
187 case gig::dimension_effect5depth:
188 return _("MIDI Controller 95");
189 default:
190 return _("Please report this !!!");
191 }
192 }
193
194 DimTypeCellRenderer::DimTypeCellRenderer() :
195 Glib::ObjectBase(typeid(DimTypeCellRenderer)),
196 Gtk::CellRendererText(),
197 m_propertyDimType(*this, "gigdimension_t", gig::dimension_none),
198 m_propertyUsageCount(*this, "intusagecount", 0),
199 m_propertyTotalRegions(*this, "inttotalregions", 0)
200 {
201 propertyDimType().signal_changed().connect(
202 sigc::mem_fun(*this, &DimTypeCellRenderer::typeChanged)
203 );
204 propertyUsageCount().signal_changed().connect(
205 sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
206 );
207 propertyTotalRegions().signal_changed().connect(
208 sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
209 );
210 }
211
212 void DimTypeCellRenderer::typeChanged() {
213 gig::dimension_t type = propertyDimType();
214 Glib::ustring s = dimTypeAsString(type);
215 property_text() = s;
216 }
217
218 void DimTypeCellRenderer::statsChanged() {
219 int usageCount = propertyUsageCount();
220 int totalRegions = propertyTotalRegions();
221 bool bDimensionExistsOnAllRegions = (usageCount == totalRegions);
222 property_foreground() = ((bDimensionExistsOnAllRegions) ? "black" : "gray");
223 }
224
225 IntSetCellRenderer::IntSetCellRenderer() :
226 Glib::ObjectBase(typeid(IntSetCellRenderer)),
227 Gtk::CellRendererText(),
228 m_propertyValue(*this, "stdintset", std::set<int>())
229 {
230 propertyValue().signal_changed().connect(
231 sigc::mem_fun(*this, &IntSetCellRenderer::valueChanged)
232 );
233 }
234
235 void IntSetCellRenderer::valueChanged() {
236 Glib::ustring s;
237 std::set<int> v = propertyValue();
238 for (std::set<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
239 s += ToString(*it);
240 if (*it != *v.rbegin()) s += "|";
241 }
242 property_text() = s;
243 property_foreground() = (v.size() > 1) ? "gray" : "black";
244 }
245
246 DimensionManager::DimensionManager() :
247 addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE),
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 //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
396 if (ignoreColumnClicked) {
397 ignoreColumnClicked = false;
398 return;
399 }
400
401 Gtk::TreeModel::Path path;
402 Gtk::TreeViewColumn* focus_column;
403 treeView.get_cursor(path, focus_column);
404 //const int row = path[0];
405 if (focus_column == treeView.get_column(0)) {
406 Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
407 Gtk::TreeModel::Row row = *it;
408 gig::dimension_t oldType = row[tableModel.m_type];
409
410 Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
411 int oldTypeIndex = -1;
412 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
413 for (int i = 0x01, count = 0; i < 0xff; i++) {
414 Glib::ustring sType =
415 dimTypeAsString(static_cast<gig::dimension_t>(i));
416 if (i == oldType) oldTypeIndex = count;
417 if (sType.find("Unknown") != 0) {
418 Gtk::TreeModel::Row row = *(refComboModel->append());
419 row[comboModel.m_type_id] = i;
420 row[comboModel.m_type_name] = sType;
421 count++;
422 }
423 }
424 Gtk::Table table(1, 2);
425 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
426 Gtk::ComboBox comboDimType;
427 comboDimType.set_model(refComboModel);
428 comboDimType.pack_start(comboModel.m_type_id);
429 comboDimType.pack_start(comboModel.m_type_name);
430 table.attach(labelDimType, 0, 1, 0, 1);
431 table.attach(comboDimType, 1, 2, 0, 1);
432 dialog.get_vbox()->pack_start(table);
433
434 dialog.add_button(Gtk::Stock::OK, 0);
435 dialog.add_button(Gtk::Stock::CANCEL, 1);
436 dialog.show_all_children();
437
438 comboDimType.set_active(oldTypeIndex);
439
440 if (!dialog.run()) { // OK selected ...
441 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
442 if (!iterType) return;
443 Gtk::TreeModel::Row rowType = *iterType;
444 if (!rowType) return;
445 int iTypeID = rowType[comboModel.m_type_id];
446 gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
447 if (newType == oldType) return;
448 //printf("change 0x%x -> 0x%x\n", oldType, newType);
449 ignoreColumnClicked = true;
450
451 // assemble the list of regions where the selected dimension type
452 // shall be changed
453 std::vector<gig::Region*> vRegions;
454 if (allRegions()) {
455 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
456 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
457 if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
458 }
459 } else vRegions.push_back(region);
460
461 std::set<Glib::ustring> errors;
462
463 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
464 gig::Region* region = vRegions[iRgn];
465 try {
466 // notify everybody that we're going to update the region
467 region_to_be_changed_signal.emit(region);
468 // change the dimension type on that region
469 region->SetDimensionType(oldType, newType);
470 // let everybody know there was a change
471 region_changed_signal.emit(region);
472 } catch (RIFF::Exception e) {
473 // notify that the changes are over (i.e. to avoid dead locks)
474 region_changed_signal.emit(region);
475 Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
476 if (vRegions.size() == 1) {
477 // show error message directly
478 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
479 msg.run();
480 } else {
481 // remember error, they are shown after all regions have been processed
482 errors.insert(txt);
483 }
484 }
485 }
486 // update all GUI elements
487 refreshManager();
488
489 if (!errors.empty()) {
490 Glib::ustring txt = _(
491 "The following errors occurred while trying to change the dimension type on all regions:"
492 );
493 txt += "\n\n";
494 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
495 it != errors.end(); ++it)
496 {
497 txt += "-> " + *it + "\n";
498 }
499 txt += "\n";
500 txt += _(
501 "You might also want to check the console for further warnings and "
502 "error messages."
503 );
504 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
505 msg.run();
506 }
507 }
508 }
509 }
510
511 void DimensionManager::addDimension() {
512 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
513 // add dimension type combo box to the dialog
514 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
515 for (int i = 0x01; i < 0xff; i++) {
516 Glib::ustring sType =
517 dimTypeAsString(static_cast<gig::dimension_t>(i));
518 if (sType.find("Unknown") != 0) {
519 Gtk::TreeModel::Row row = *(refComboModel->append());
520 row[comboModel.m_type_id] = i;
521 row[comboModel.m_type_name] = sType;
522 }
523 }
524 Gtk::Table table(2, 2);
525 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
526 Gtk::ComboBox comboDimType;
527 comboDimType.set_model(refComboModel);
528 comboDimType.pack_start(comboModel.m_type_id);
529 comboDimType.pack_start(comboModel.m_type_name);
530 Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
531 table.attach(labelDimType, 0, 1, 0, 1);
532 table.attach(comboDimType, 1, 2, 0, 1);
533 table.attach(labelZones, 0, 1, 1, 2);
534 dialog.get_vbox()->pack_start(table);
535
536 // number of zones: use a combo box with fix values for gig
537 // v2 and a spin button for v3
538 Gtk::ComboBoxText comboZones;
539 Gtk::SpinButton spinZones;
540 bool version2 = false;
541 if (region) {
542 gig::File* file = (gig::File*)region->GetParent()->GetParent();
543 version2 = file->pVersion && file->pVersion->major == 2;
544 }
545 if (version2) {
546 for (int i = 1; i <= 5; i++) {
547 char buf[3];
548 sprintf(buf, "%d", 1 << i);
549 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
550 comboZones.append_text(buf);
551 #else
552 comboZones.append(buf);
553 #endif
554 }
555 table.attach(comboZones, 1, 2, 1, 2);
556 } else {
557 spinZones.set_increments(1, 8);
558 spinZones.set_numeric(true);
559 spinZones.set_range(2, 128);
560 spinZones.set_value(2);
561 table.attach(spinZones, 1, 2, 1, 2);
562 }
563
564 dialog.add_button(Gtk::Stock::OK, 0);
565 dialog.add_button(Gtk::Stock::CANCEL, 1);
566 dialog.show_all_children();
567
568 if (!dialog.run()) { // OK selected ...
569 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
570 if (!iterType) return;
571 Gtk::TreeModel::Row rowType = *iterType;
572 if (!rowType) return;
573 int iTypeID = rowType[comboModel.m_type_id];
574 gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
575 gig::dimension_def_t dim;
576 dim.dimension = type;
577
578 if (version2) {
579 if (comboZones.get_active_row_number() < 0) return;
580 dim.bits = comboZones.get_active_row_number() + 1;
581 dim.zones = 1 << dim.bits;
582 } else {
583 dim.zones = spinZones.get_value_as_int();
584 dim.bits = zoneCountToBits(dim.zones);
585 }
586
587 // assemble the list of regions where the selected dimension shall be
588 // added to
589 std::vector<gig::Region*> vRegions;
590 if (allRegions()) {
591 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
592 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
593 if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
594 }
595 } else vRegions.push_back(region);
596
597 std::set<Glib::ustring> errors;
598
599 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
600 gig::Region* region = vRegions[iRgn];
601 try {
602 printf(
603 "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
604 dim.dimension, dim.bits, dim.zones
605 );
606 // notify everybody that we're going to update the region
607 region_to_be_changed_signal.emit(region);
608 // add the new dimension to the region
609 // (implicitly creates new dimension regions)
610 region->AddDimension(&dim);
611 // let everybody know there was a change
612 region_changed_signal.emit(region);
613 } catch (RIFF::Exception e) {
614 // notify that the changes are over (i.e. to avoid dead locks)
615 region_changed_signal.emit(region);
616 Glib::ustring txt = _("Could not add dimension: ") + e.Message;
617 if (vRegions.size() == 1) {
618 // show error message directly
619 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
620 msg.run();
621 } else {
622 // remember error, they are shown after all regions have been processed
623 errors.insert(txt);
624 }
625 }
626 }
627 // update all GUI elements
628 refreshManager();
629
630 if (!errors.empty()) {
631 Glib::ustring txt = _(
632 "The following errors occurred while trying to create the dimension on all regions:"
633 );
634 txt += "\n\n";
635 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
636 it != errors.end(); ++it)
637 {
638 txt += "-> " + *it + "\n";
639 }
640 txt += "\n";
641 txt += _(
642 "You might also want to check the console for further warnings and "
643 "error messages."
644 );
645 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
646 msg.run();
647 }
648 }
649 }
650
651 void DimensionManager::removeDimension() {
652 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
653 Gtk::TreeModel::iterator it = sel->get_selected();
654 if (it) {
655 Gtk::TreeModel::Row row = *it;
656 gig::dimension_t type = row[tableModel.m_type];
657
658 // assemble the list of regions where the selected dimension shall be
659 // added to
660 std::vector<gig::Region*> vRegions;
661 if (allRegions()) {
662 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
663 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
664 if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
665 }
666 } else vRegions.push_back(region);
667
668 std::set<Glib::ustring> errors;
669
670 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
671 gig::Region* region = vRegions[iRgn];
672 gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
673 try {
674 // notify everybody that we're going to update the region
675 region_to_be_changed_signal.emit(region);
676 // remove selected dimension
677 region->DeleteDimension(dim);
678 // let everybody know there was a change
679 region_changed_signal.emit(region);
680 } catch (RIFF::Exception e) {
681 // notify that the changes are over (i.e. to avoid dead locks)
682 region_changed_signal.emit(region);
683 Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
684 if (vRegions.size() == 1) {
685 // show error message directly
686 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
687 msg.run();
688 } else {
689 // remember error, they are shown after all regions have been processed
690 errors.insert(txt);
691 }
692 }
693 }
694 // update all GUI elements
695 refreshManager();
696
697 if (!errors.empty()) {
698 Glib::ustring txt = _(
699 "The following errors occurred while trying to remove the dimension from all regions:"
700 );
701 txt += "\n\n";
702 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
703 it != errors.end(); ++it)
704 {
705 txt += "-> " + *it + "\n";
706 }
707 txt += "\n";
708 txt += _(
709 "You might also want to check the console for further warnings and "
710 "error messages."
711 );
712 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
713 msg.run();
714 }
715 }
716 }

  ViewVC Help
Powered by ViewVC