/[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 3225 - (show annotations) (download)
Fri May 26 22:10:16 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 30227 byte(s)
* Assigned more useful default dimensions (and default position) for various
  windows and dialogs (if auto-restore of user's own custom window
  dimensions is disabled).
* Bumped version (1.0.0.svn51).

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 <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 if (!Settings::singleton()->autoRestoreWindowDimension) {
253 set_default_size(630, 250);
254 set_position(Gtk::WIN_POS_MOUSE);
255 }
256
257 set_title(_("Dimensions of selected Region"));
258 add(vbox);
259 scrolledWindow.add(treeView);
260 vbox.pack_start(scrolledWindow);
261 scrolledWindow.show();
262 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
263 buttonBox.set_layout(Gtk::BUTTONBOX_END);
264 buttonBox.set_border_width(5);
265 buttonBox.show();
266 buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
267 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
268 buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
269 addButton.show();
270 removeButton.show();
271 allRegionsCheckBox.set_tooltip_text(
272 _("Enable this if you want to edit dimensions of all regions simultaniously.")
273 );
274
275 // setup the table
276 refTableModel = Gtk::ListStore::create(tableModel);
277 treeView.set_model(refTableModel);
278 treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
279 treeView.append_column(_("Bits"), m_cellRendererIntSet);
280 treeView.append_column(_("Zones"), m_cellRendererIntSet);
281 treeView.append_column(_("Description"), tableModel.m_description);
282 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyDimType(), tableModel.m_type);
283 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyUsageCount(), tableModel.m_usageCount);
284 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyTotalRegions(), tableModel.m_totalRegions);
285 treeView.get_column(1)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_bits);
286 treeView.get_column(2)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_zones);
287 treeView.show();
288
289 treeView.signal_cursor_changed().connect(
290 sigc::mem_fun(*this, &DimensionManager::onColumnClicked)
291 );
292
293 addButton.signal_clicked().connect(
294 sigc::mem_fun(*this, &DimensionManager::addDimension)
295 );
296
297 removeButton.signal_clicked().connect(
298 sigc::mem_fun(*this, &DimensionManager::removeDimension)
299 );
300 allRegionsCheckBox.signal_toggled().connect(
301 sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
302 );
303
304 show_all_children();
305 }
306
307 bool DimensionManager::allRegions() const {
308 return allRegionsCheckBox.get_active();
309 }
310
311 void DimensionManager::onAllRegionsCheckBoxToggled() {
312 set_title(
313 allRegions() ? _("Dimensions of all Regions") : _("Dimensions of selected Region")
314 );
315 treeView.set_tooltip_text(
316 allRegions()
317 ? _("Dimensions and numbers in gray indicates a difference among the individual regions.")
318 : _("You are currently only viewing dimensions of the currently selected region.")
319 );
320 refreshManager();
321 }
322
323 // following two data types are just used in DimensionManager::refresManager(),
324 // due to the maps template nature however, they must be declared at global
325 // space to avoid compilation errors
326 struct _DimDef {
327 std::set<int> bits;
328 std::set<int> zones;
329 int usageCount;
330 };
331 typedef std::map<gig::dimension_t, _DimDef> _Dimensions;
332
333 // update all GUI elements according to current gig::Region informations
334 void DimensionManager::refreshManager() {
335 set_sensitive(false);
336 refTableModel->clear();
337 if (allRegions()) {
338 if (region) {
339 _Dimensions dims;
340 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
341 int iRegionsCount = 0;
342 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
343 for (uint i = 0; i < rgn->Dimensions; i++) {
344 gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
345 dims[dim->dimension].bits.insert(dim->bits);
346 dims[dim->dimension].zones.insert(dim->zones);
347 dims[dim->dimension].usageCount++;
348 }
349 }
350 for (_Dimensions::const_iterator it = dims.begin(); it != dims.end(); ++it) {
351 Gtk::TreeModel::Row row = *(refTableModel->append());
352 row[tableModel.m_type] = it->first;
353 row[tableModel.m_bits] = it->second.bits;
354 row[tableModel.m_zones] = it->second.zones;
355 row[tableModel.m_description] = __dimDescriptionAsString(it->first);
356 row[tableModel.m_usageCount] = it->second.usageCount;
357 row[tableModel.m_totalRegions] = iRegionsCount;
358 }
359 }
360 } else {
361 if (region) {
362 for (uint i = 0; i < region->Dimensions; i++) {
363 gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
364 Gtk::TreeModel::Row row = *(refTableModel->append());
365 std::set<int> vBits;
366 vBits.insert(dim->bits);
367 row[tableModel.m_bits] = vBits;
368 std::set<int> vZones;
369 vZones.insert(dim->zones);
370 row[tableModel.m_zones] = vZones;
371 row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
372 row[tableModel.m_type] = dim->dimension;
373 row[tableModel.m_usageCount] = 1;
374 row[tableModel.m_totalRegions] = 1;
375 }
376 }
377 }
378 set_sensitive(region);
379 }
380
381 void DimensionManager::show(gig::Region* region) {
382 ignoreColumnClicked = true;
383 this->region = region;
384 refreshManager();
385 Gtk::Window::show();
386 deiconify();
387 ignoreColumnClicked = false;
388 }
389
390 void DimensionManager::set_region(gig::Region* region) {
391 ignoreColumnClicked = true;
392 this->region = region;
393 refreshManager();
394 ignoreColumnClicked = false;
395 }
396
397 void DimensionManager::onColumnClicked() {
398 printf("DimensionManager::onColumnClicked()\n");
399
400 //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 !
401
402 //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
403 if (ignoreColumnClicked) {
404 ignoreColumnClicked = false;
405 return;
406 }
407 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
408 // prevents app to crash if this dialog is closed
409 if (!get_visible())
410 return;
411 #else
412 # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
413 #endif
414
415 #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
416 if (!is_visible()) return;
417 #endif
418
419 Gtk::TreeModel::Path path;
420 Gtk::TreeViewColumn* focus_column;
421 treeView.get_cursor(path, focus_column);
422 //const int row = path[0];
423 if (focus_column == treeView.get_column(0)) {
424 Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
425 if (!it) return;
426 Gtk::TreeModel::Row row = *it;
427 gig::dimension_t oldType = row[tableModel.m_type];
428
429 Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
430 int oldTypeIndex = -1;
431 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
432 for (int i = 0x01, count = 0; i < 0xff; i++) {
433 Glib::ustring sType =
434 dimTypeAsString(static_cast<gig::dimension_t>(i));
435 if (i == oldType) oldTypeIndex = count;
436 if (sType.find("Unknown") != 0) {
437 Gtk::TreeModel::Row row = *(refComboModel->append());
438 row[comboModel.m_type_id] = i;
439 row[comboModel.m_type_name] = sType;
440 count++;
441 }
442 }
443 Gtk::Table table(1, 2);
444 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
445 Gtk::ComboBox comboDimType;
446 comboDimType.set_model(refComboModel);
447 comboDimType.pack_start(comboModel.m_type_id);
448 comboDimType.pack_start(comboModel.m_type_name);
449 table.attach(labelDimType, 0, 1, 0, 1);
450 table.attach(comboDimType, 1, 2, 0, 1);
451 dialog.get_vbox()->pack_start(table);
452
453 dialog.add_button(Gtk::Stock::OK, 0);
454 dialog.add_button(Gtk::Stock::CANCEL, 1);
455 dialog.show_all_children();
456
457 comboDimType.set_active(oldTypeIndex);
458
459 if (!dialog.run()) { // OK selected ...
460 ignoreColumnClicked = true;
461 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
462 if (!iterType) return;
463 Gtk::TreeModel::Row rowType = *iterType;
464 if (!rowType) return;
465 int iTypeID = rowType[comboModel.m_type_id];
466 gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
467 if (newType == oldType) return;
468 //printf("change 0x%x -> 0x%x\n", oldType, newType);
469
470 // assemble the list of regions where the selected dimension type
471 // shall be changed
472 std::vector<gig::Region*> vRegions;
473 if (allRegions()) {
474 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
475 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
476 if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
477 }
478 } else vRegions.push_back(region);
479
480 std::set<Glib::ustring> errors;
481
482 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
483 gig::Region* region = vRegions[iRgn];
484 try {
485 // notify everybody that we're going to update the region
486 region_to_be_changed_signal.emit(region);
487 // change the dimension type on that region
488 region->SetDimensionType(oldType, newType);
489 // let everybody know there was a change
490 region_changed_signal.emit(region);
491 } catch (RIFF::Exception e) {
492 // notify that the changes are over (i.e. to avoid dead locks)
493 region_changed_signal.emit(region);
494 Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
495 if (vRegions.size() == 1) {
496 // show error message directly
497 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
498 msg.run();
499 } else {
500 // remember error, they are shown after all regions have been processed
501 errors.insert(txt);
502 }
503 }
504 }
505 // update all GUI elements
506 refreshManager();
507
508 if (!errors.empty()) {
509 Glib::ustring txt = _(
510 "The following errors occurred while trying to change the dimension type on all regions:"
511 );
512 txt += "\n\n";
513 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
514 it != errors.end(); ++it)
515 {
516 txt += "-> " + *it + "\n";
517 }
518 txt += "\n";
519 txt += _(
520 "You might also want to check the console for further warnings and "
521 "error messages."
522 );
523 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
524 msg.run();
525 }
526 }
527 } else if (focus_column == treeView.get_column(1) || focus_column == treeView.get_column(2)) {
528 Glib::ustring txt = _("Right-click on a specific dimension zone of the dimension region selector to delete or split that particular dimension zone!");
529 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_INFO);
530 msg.run();
531 }
532 }
533
534 void DimensionManager::addDimension() {
535 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
536 // add dimension type combo box to the dialog
537 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
538 for (int i = 0x01; i < 0xff; i++) {
539 Glib::ustring sType =
540 dimTypeAsString(static_cast<gig::dimension_t>(i));
541 if (sType.find("Unknown") != 0) {
542 Gtk::TreeModel::Row row = *(refComboModel->append());
543 row[comboModel.m_type_id] = i;
544 row[comboModel.m_type_name] = sType;
545 }
546 }
547 Gtk::Table table(2, 2);
548 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
549 Gtk::ComboBox comboDimType;
550 comboDimType.set_model(refComboModel);
551 comboDimType.pack_start(comboModel.m_type_id);
552 comboDimType.pack_start(comboModel.m_type_name);
553 Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
554 table.attach(labelDimType, 0, 1, 0, 1);
555 table.attach(comboDimType, 1, 2, 0, 1);
556 table.attach(labelZones, 0, 1, 1, 2);
557 dialog.get_vbox()->pack_start(table);
558
559 // number of zones: use a combo box with fix values for gig
560 // v2 and a spin button for v3
561 Gtk::ComboBoxText comboZones;
562 Gtk::SpinButton spinZones;
563 bool version2 = false;
564 if (region) {
565 gig::File* file = (gig::File*)region->GetParent()->GetParent();
566 version2 = file->pVersion && file->pVersion->major == 2;
567 }
568 if (version2) {
569 for (int i = 1; i <= 5; i++) {
570 char buf[3];
571 sprintf(buf, "%d", 1 << i);
572 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
573 comboZones.append_text(buf);
574 #else
575 comboZones.append(buf);
576 #endif
577 }
578 table.attach(comboZones, 1, 2, 1, 2);
579 } else {
580 spinZones.set_increments(1, 8);
581 spinZones.set_numeric(true);
582 spinZones.set_range(2, 128);
583 spinZones.set_value(2);
584 table.attach(spinZones, 1, 2, 1, 2);
585 }
586
587 dialog.add_button(Gtk::Stock::OK, 0);
588 dialog.add_button(Gtk::Stock::CANCEL, 1);
589 dialog.show_all_children();
590
591 if (!dialog.run()) { // OK selected ...
592 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
593 if (!iterType) return;
594 Gtk::TreeModel::Row rowType = *iterType;
595 if (!rowType) return;
596 int iTypeID = rowType[comboModel.m_type_id];
597 gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
598 gig::dimension_def_t dim;
599 dim.dimension = type;
600
601 if (version2) {
602 if (comboZones.get_active_row_number() < 0) return;
603 dim.bits = comboZones.get_active_row_number() + 1;
604 dim.zones = 1 << dim.bits;
605 } else {
606 dim.zones = spinZones.get_value_as_int();
607 dim.bits = zoneCountToBits(dim.zones);
608 }
609
610 // assemble the list of regions where the selected dimension shall be
611 // added to
612 std::vector<gig::Region*> vRegions;
613 if (allRegions()) {
614 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
615 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
616 if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
617 }
618 } else vRegions.push_back(region);
619
620 std::set<Glib::ustring> errors;
621
622 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
623 gig::Region* region = vRegions[iRgn];
624 try {
625 printf(
626 "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
627 dim.dimension, dim.bits, dim.zones
628 );
629 // notify everybody that we're going to update the region
630 region_to_be_changed_signal.emit(region);
631 // add the new dimension to the region
632 // (implicitly creates new dimension regions)
633 region->AddDimension(&dim);
634 // let everybody know there was a change
635 region_changed_signal.emit(region);
636 } catch (RIFF::Exception e) {
637 // notify that the changes are over (i.e. to avoid dead locks)
638 region_changed_signal.emit(region);
639 Glib::ustring txt = _("Could not add dimension: ") + e.Message;
640 if (vRegions.size() == 1) {
641 // show error message directly
642 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
643 msg.run();
644 } else {
645 // remember error, they are shown after all regions have been processed
646 errors.insert(txt);
647 }
648 }
649 }
650 // update all GUI elements
651 refreshManager();
652
653 if (!errors.empty()) {
654 Glib::ustring txt = _(
655 "The following errors occurred while trying to create the dimension on all regions:"
656 );
657 txt += "\n\n";
658 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
659 it != errors.end(); ++it)
660 {
661 txt += "-> " + *it + "\n";
662 }
663 txt += "\n";
664 txt += _(
665 "You might also want to check the console for further warnings and "
666 "error messages."
667 );
668 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
669 msg.run();
670 }
671 }
672 }
673
674 void DimensionManager::removeDimension() {
675 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
676 Gtk::TreeModel::iterator it = sel->get_selected();
677 if (it) {
678 Gtk::TreeModel::Row row = *it;
679 gig::dimension_t type = row[tableModel.m_type];
680
681 // assemble the list of regions where the selected dimension shall be
682 // added to
683 std::vector<gig::Region*> vRegions;
684 if (allRegions()) {
685 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
686 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
687 if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
688 }
689 } else vRegions.push_back(region);
690
691 std::set<Glib::ustring> errors;
692
693 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
694 gig::Region* region = vRegions[iRgn];
695 gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
696 try {
697 // notify everybody that we're going to update the region
698 region_to_be_changed_signal.emit(region);
699 // remove selected dimension
700 region->DeleteDimension(dim);
701 // let everybody know there was a change
702 region_changed_signal.emit(region);
703 } catch (RIFF::Exception e) {
704 // notify that the changes are over (i.e. to avoid dead locks)
705 region_changed_signal.emit(region);
706 Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
707 if (vRegions.size() == 1) {
708 // show error message directly
709 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
710 msg.run();
711 } else {
712 // remember error, they are shown after all regions have been processed
713 errors.insert(txt);
714 }
715 }
716 }
717 // update all GUI elements
718 refreshManager();
719
720 if (!errors.empty()) {
721 Glib::ustring txt = _(
722 "The following errors occurred while trying to remove the dimension from all regions:"
723 );
724 txt += "\n\n";
725 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
726 it != errors.end(); ++it)
727 {
728 txt += "-> " + *it + "\n";
729 }
730 txt += "\n";
731 txt += _(
732 "You might also want to check the console for further warnings and "
733 "error messages."
734 );
735 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
736 msg.run();
737 }
738 }
739 }

  ViewVC Help
Powered by ViewVC