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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2921 - (hide annotations) (download)
Wed May 18 11:57:58 2016 UTC (7 years, 11 months ago) by schoenebeck
File size: 29564 byte(s)
- Fixed compile error with older GTKMM versions.

1 persson 2169 /*
2 persson 2507 * Copyright (C) 2006-2014 Andreas Persson
3 schoenebeck 1225 *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License as
6     * published by the Free Software Foundation; either version 2, or (at
7     * your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful, but
10     * WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     * General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with program; see the file COPYING. If not, write to the Free
16     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17     * 02110-1301 USA.
18     */
19    
20 persson 2844 #include <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 schoenebeck 1225 #include "dimensionmanager.h"
29    
30     #include <gtkmm/messagedialog.h>
31     #include <gtkmm/dialog.h>
32     #include <gtkmm/comboboxtext.h>
33 persson 1733 #include <gtkmm/spinbutton.h>
34     #include <gtkmm/table.h>
35 schoenebeck 1225
36 persson 1831 #include "global.h"
37 persson 2169 #include "compat.h"
38 persson 1831
39 schoenebeck 1225 // returns a human readable name of the given dimension type
40 schoenebeck 2558 Glib::ustring dimTypeAsString(gig::dimension_t d) {
41 schoenebeck 1225 char buf[32];
42     switch (d) {
43     case gig::dimension_none:
44 persson 1831 return _("None");
45 schoenebeck 1225 case gig::dimension_samplechannel:
46 persson 1831 return _("Sample Channel");
47 schoenebeck 1225 case gig::dimension_layer:
48 persson 1831 return _("Layer");
49 schoenebeck 1225 case gig::dimension_velocity:
50 persson 1831 return _("Velocity");
51 schoenebeck 1225 case gig::dimension_channelaftertouch:
52 persson 1831 return _("Aftertouch");
53 schoenebeck 1225 case gig::dimension_releasetrigger:
54 persson 1831 return _("Release Trigger");
55 schoenebeck 1225 case gig::dimension_keyboard:
56 persson 1831 return _("Keyswitching");
57 schoenebeck 1225 case gig::dimension_roundrobin:
58 persson 1831 return _("Round Robin");
59 schoenebeck 1225 case gig::dimension_random:
60 persson 1831 return _("Random Generator");
61 schoenebeck 1225 case gig::dimension_smartmidi:
62 persson 1831 return _("Smart MIDI");
63 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
64 persson 1831 return _("Keyboard Round Robin");
65 schoenebeck 1225 case gig::dimension_modwheel:
66 persson 1831 return _("Modulation Wheel");
67 schoenebeck 1225 case gig::dimension_breath:
68 persson 1831 return _("Breath Ctrl.");
69 schoenebeck 1225 case gig::dimension_foot:
70 persson 1831 return _("Foot Ctrl.");
71 schoenebeck 1225 case gig::dimension_portamentotime:
72 persson 1831 return _("Portamento Time Ctrl.");
73 schoenebeck 1225 case gig::dimension_effect1:
74 persson 1831 return _("Effect Ctrl. 1");
75 schoenebeck 1225 case gig::dimension_effect2:
76 persson 1831 return _("Effect Ctrl. 2");
77 schoenebeck 1225 case gig::dimension_genpurpose1:
78 persson 1831 return _("General Purpose Ctrl. 1");
79 schoenebeck 1225 case gig::dimension_genpurpose2:
80 persson 1831 return _("General Purpose Ctrl. 2");
81 schoenebeck 1225 case gig::dimension_genpurpose3:
82 persson 1831 return _("General Purpose Ctrl. 3");
83 schoenebeck 1225 case gig::dimension_genpurpose4:
84 persson 1831 return _("General Purpose Ctrl. 4");
85 schoenebeck 1225 case gig::dimension_sustainpedal:
86 persson 1831 return _("Sustain Pedal");
87 schoenebeck 1225 case gig::dimension_portamento:
88 persson 1831 return _("Portamento Ctrl.");
89 schoenebeck 1225 case gig::dimension_sostenutopedal:
90 persson 1831 return _("Sostenuto Pedal");
91 schoenebeck 1225 case gig::dimension_softpedal:
92 persson 1831 return _("Soft Pedal");
93 schoenebeck 1225 case gig::dimension_genpurpose5:
94 persson 1831 return _("General Purpose Ctrl. 5");
95 schoenebeck 1225 case gig::dimension_genpurpose6:
96 persson 1831 return _("General Purpose Ctrl. 6");
97 schoenebeck 1225 case gig::dimension_genpurpose7:
98 persson 1831 return _("General Purpose Ctrl. 7");
99 schoenebeck 1225 case gig::dimension_genpurpose8:
100 persson 1831 return _("General Purpose Ctrl. 8");
101 schoenebeck 1225 case gig::dimension_effect1depth:
102 persson 1831 return _("Effect 1 Depth");
103 schoenebeck 1225 case gig::dimension_effect2depth:
104 persson 1831 return _("Effect 2 Depth");
105 schoenebeck 1225 case gig::dimension_effect3depth:
106 persson 1831 return _("Effect 3 Depth");
107 schoenebeck 1225 case gig::dimension_effect4depth:
108 persson 1831 return _("Effect 4 Depth");
109 schoenebeck 1225 case gig::dimension_effect5depth:
110 persson 1831 return _("Effect 5 Depth");
111 schoenebeck 1225 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 persson 1831 return _("Dimension not in use");
122 schoenebeck 1225 case gig::dimension_samplechannel:
123 persson 1831 return _("If used sample has more than one channel (thus is not mono)");
124 schoenebeck 1225 case gig::dimension_layer:
125 persson 1831 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
126 schoenebeck 1225 case gig::dimension_velocity:
127 persson 1831 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
128 schoenebeck 1225 case gig::dimension_channelaftertouch:
129 persson 1831 return _("Channel Key Pressure");
130 schoenebeck 1225 case gig::dimension_releasetrigger:
131 persson 1831 return _("Special dimension for triggering samples on releasing a key");
132 schoenebeck 1225 case gig::dimension_keyboard:
133 persson 1831 return _("Dimension for keyswitching (keyboard)");
134 schoenebeck 1225 case gig::dimension_roundrobin:
135 persson 1831 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
136 schoenebeck 1225 case gig::dimension_random:
137 persson 1831 return _("Different samples triggered each time a note is played, random order");
138 schoenebeck 1225 case gig::dimension_smartmidi:
139 persson 1831 return _("For MIDI tools like legato and repetition mode");
140 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
141 persson 1831 return _("Different samples triggered each time a note is played, any key advances the counter");
142 schoenebeck 1225 case gig::dimension_modwheel:
143 persson 1831 return _("MIDI Controller 1");
144 schoenebeck 1225 case gig::dimension_breath:
145 persson 1831 return _("MIDI Controller 2");
146 schoenebeck 1225 case gig::dimension_foot:
147 persson 1831 return _("MIDI Controller 4");
148 schoenebeck 1225 case gig::dimension_portamentotime:
149 persson 1831 return _("MIDI Controller 5");
150 schoenebeck 1225 case gig::dimension_effect1:
151 persson 1831 return _("MIDI Controller 12");
152 schoenebeck 1225 case gig::dimension_effect2:
153 persson 1831 return _("MIDI Controller 13");
154 schoenebeck 1225 case gig::dimension_genpurpose1:
155 persson 1831 return _("Slider, MIDI Controller 16");
156 schoenebeck 1225 case gig::dimension_genpurpose2:
157 persson 1831 return _("Slider, MIDI Controller 17");
158 schoenebeck 1225 case gig::dimension_genpurpose3:
159 persson 1831 return _("Slider, MIDI Controller 18");
160 schoenebeck 1225 case gig::dimension_genpurpose4:
161 persson 1831 return _("Slider, MIDI Controller 19");
162 schoenebeck 1225 case gig::dimension_sustainpedal:
163 persson 1831 return _("MIDI Controller 64");
164 schoenebeck 1225 case gig::dimension_portamento:
165 persson 1831 return _("MIDI Controller 65");
166 schoenebeck 1225 case gig::dimension_sostenutopedal:
167 persson 1831 return _("MIDI Controller 66");
168 schoenebeck 1225 case gig::dimension_softpedal:
169 persson 1831 return _("MIDI Controller 67");
170 schoenebeck 1225 case gig::dimension_genpurpose5:
171 persson 1831 return _("Button, MIDI Controller 80");
172 schoenebeck 1225 case gig::dimension_genpurpose6:
173 persson 1831 return _("Button, MIDI Controller 81");
174 schoenebeck 1225 case gig::dimension_genpurpose7:
175 persson 1831 return _("Button, MIDI Controller 82");
176 schoenebeck 1225 case gig::dimension_genpurpose8:
177 persson 1831 return _("Button, MIDI Controller 83");
178 schoenebeck 1225 case gig::dimension_effect1depth:
179 persson 1831 return _("MIDI Controller 91");
180 schoenebeck 1225 case gig::dimension_effect2depth:
181 persson 1831 return _("MIDI Controller 92");
182 schoenebeck 1225 case gig::dimension_effect3depth:
183 persson 1831 return _("MIDI Controller 93");
184 schoenebeck 1225 case gig::dimension_effect4depth:
185 persson 1831 return _("MIDI Controller 94");
186 schoenebeck 1225 case gig::dimension_effect5depth:
187 persson 1831 return _("MIDI Controller 95");
188 schoenebeck 1225 default:
189 persson 1831 return _("Please report this !!!");
190 schoenebeck 1225 }
191     }
192    
193 schoenebeck 2562 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 schoenebeck 1225 DimensionManager::DimensionManager() :
246 persson 2845 addButton(_("_Add"), true),
247     removeButton(_("_Remove"), true),
248     allRegionsCheckBox(_("All Regions"))
249 schoenebeck 1225 {
250 schoenebeck 2641 ignoreColumnClicked = true;
251    
252 persson 1831 set_title(_("Dimensions of selected Region"));
253 schoenebeck 1225 add(vbox);
254     scrolledWindow.add(treeView);
255     vbox.pack_start(scrolledWindow);
256     scrolledWindow.show();
257 schoenebeck 1411 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
258 schoenebeck 1225 buttonBox.set_layout(Gtk::BUTTONBOX_END);
259     buttonBox.set_border_width(5);
260     buttonBox.show();
261 schoenebeck 2562 buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
262 schoenebeck 1411 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
263     buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
264 schoenebeck 1225 addButton.show();
265     removeButton.show();
266 schoenebeck 2562 allRegionsCheckBox.set_tooltip_text(
267     _("Enable this if you want to edit dimensions of all regions simultaniously.")
268     );
269 schoenebeck 1225
270     // setup the table
271     refTableModel = Gtk::ListStore::create(tableModel);
272     treeView.set_model(refTableModel);
273 schoenebeck 2562 treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
274     treeView.append_column(_("Bits"), m_cellRendererIntSet);
275     treeView.append_column(_("Zones"), m_cellRendererIntSet);
276 persson 1831 treeView.append_column(_("Description"), tableModel.m_description);
277 schoenebeck 2562 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 schoenebeck 1225 treeView.show();
283    
284 schoenebeck 2641 treeView.signal_cursor_changed().connect(
285     sigc::mem_fun(*this, &DimensionManager::onColumnClicked)
286     );
287    
288 schoenebeck 1225 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 schoenebeck 2562 allRegionsCheckBox.signal_toggled().connect(
296     sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
297     );
298 schoenebeck 1225
299     show_all_children();
300 schoenebeck 2558
301     resize(460,300);
302 schoenebeck 1225 }
303    
304 schoenebeck 2562 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 schoenebeck 1225 // update all GUI elements according to current gig::Region informations
331     void DimensionManager::refreshManager() {
332 schoenebeck 2562 set_sensitive(false);
333 schoenebeck 1225 refTableModel->clear();
334 schoenebeck 2562 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 persson 1677 }
357 schoenebeck 2562 } 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 schoenebeck 1225 }
375 persson 1677 set_sensitive(region);
376 schoenebeck 1225 }
377    
378     void DimensionManager::show(gig::Region* region) {
379 schoenebeck 2641 ignoreColumnClicked = true;
380 schoenebeck 1225 this->region = region;
381     refreshManager();
382     Gtk::Window::show();
383     deiconify();
384 schoenebeck 2641 ignoreColumnClicked = false;
385 schoenebeck 1225 }
386    
387 persson 1677 void DimensionManager::set_region(gig::Region* region) {
388 schoenebeck 2641 ignoreColumnClicked = true;
389 persson 1677 this->region = region;
390     refreshManager();
391 schoenebeck 2641 ignoreColumnClicked = false;
392 persson 1677 }
393    
394 schoenebeck 2641 void DimensionManager::onColumnClicked() {
395 schoenebeck 2919 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 schoenebeck 2641 //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 schoenebeck 2921 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
405 schoenebeck 2919 // prevents app to crash if this dialog is closed
406     if (!get_visible())
407     return;
408 schoenebeck 2921 #else
409     # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
410     #endif
411 schoenebeck 2641
412     Gtk::TreeModel::Path path;
413     Gtk::TreeViewColumn* focus_column;
414     treeView.get_cursor(path, focus_column);
415     //const int row = path[0];
416     if (focus_column == treeView.get_column(0)) {
417     Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
418     Gtk::TreeModel::Row row = *it;
419     gig::dimension_t oldType = row[tableModel.m_type];
420    
421     Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
422     int oldTypeIndex = -1;
423     Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
424     for (int i = 0x01, count = 0; i < 0xff; i++) {
425     Glib::ustring sType =
426     dimTypeAsString(static_cast<gig::dimension_t>(i));
427     if (i == oldType) oldTypeIndex = count;
428     if (sType.find("Unknown") != 0) {
429     Gtk::TreeModel::Row row = *(refComboModel->append());
430     row[comboModel.m_type_id] = i;
431     row[comboModel.m_type_name] = sType;
432     count++;
433     }
434     }
435     Gtk::Table table(1, 2);
436     Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
437     Gtk::ComboBox comboDimType;
438     comboDimType.set_model(refComboModel);
439     comboDimType.pack_start(comboModel.m_type_id);
440     comboDimType.pack_start(comboModel.m_type_name);
441     table.attach(labelDimType, 0, 1, 0, 1);
442     table.attach(comboDimType, 1, 2, 0, 1);
443     dialog.get_vbox()->pack_start(table);
444    
445 persson 2845 dialog.add_button(_("_OK"), 0);
446     dialog.add_button(_("_Cancel"), 1);
447 schoenebeck 2641 dialog.show_all_children();
448    
449     comboDimType.set_active(oldTypeIndex);
450    
451     if (!dialog.run()) { // OK selected ...
452 schoenebeck 2919 ignoreColumnClicked = true;
453 schoenebeck 2641 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
454     if (!iterType) return;
455     Gtk::TreeModel::Row rowType = *iterType;
456     if (!rowType) return;
457     int iTypeID = rowType[comboModel.m_type_id];
458     gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
459     if (newType == oldType) return;
460     //printf("change 0x%x -> 0x%x\n", oldType, newType);
461    
462     // assemble the list of regions where the selected dimension type
463     // shall be changed
464     std::vector<gig::Region*> vRegions;
465     if (allRegions()) {
466     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
467     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
468     if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
469     }
470     } else vRegions.push_back(region);
471    
472     std::set<Glib::ustring> errors;
473    
474     for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
475     gig::Region* region = vRegions[iRgn];
476     try {
477     // notify everybody that we're going to update the region
478     region_to_be_changed_signal.emit(region);
479     // change the dimension type on that region
480     region->SetDimensionType(oldType, newType);
481     // let everybody know there was a change
482     region_changed_signal.emit(region);
483     } catch (RIFF::Exception e) {
484     // notify that the changes are over (i.e. to avoid dead locks)
485     region_changed_signal.emit(region);
486     Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
487     if (vRegions.size() == 1) {
488     // show error message directly
489     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
490     msg.run();
491     } else {
492     // remember error, they are shown after all regions have been processed
493     errors.insert(txt);
494     }
495     }
496     }
497     // update all GUI elements
498     refreshManager();
499    
500     if (!errors.empty()) {
501     Glib::ustring txt = _(
502     "The following errors occurred while trying to change the dimension type on all regions:"
503     );
504     txt += "\n\n";
505     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
506     it != errors.end(); ++it)
507     {
508     txt += "-> " + *it + "\n";
509     }
510     txt += "\n";
511     txt += _(
512     "You might also want to check the console for further warnings and "
513     "error messages."
514     );
515     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
516     msg.run();
517     }
518     }
519     }
520     }
521    
522 schoenebeck 1225 void DimensionManager::addDimension() {
523 schoenebeck 2562 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
524     // add dimension type combo box to the dialog
525     Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
526     for (int i = 0x01; i < 0xff; i++) {
527     Glib::ustring sType =
528     dimTypeAsString(static_cast<gig::dimension_t>(i));
529     if (sType.find("Unknown") != 0) {
530     Gtk::TreeModel::Row row = *(refComboModel->append());
531     row[comboModel.m_type_id] = i;
532     row[comboModel.m_type_name] = sType;
533 schoenebeck 1225 }
534 schoenebeck 2562 }
535     Gtk::Table table(2, 2);
536     Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
537     Gtk::ComboBox comboDimType;
538     comboDimType.set_model(refComboModel);
539     comboDimType.pack_start(comboModel.m_type_id);
540     comboDimType.pack_start(comboModel.m_type_name);
541     Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
542     table.attach(labelDimType, 0, 1, 0, 1);
543     table.attach(comboDimType, 1, 2, 0, 1);
544     table.attach(labelZones, 0, 1, 1, 2);
545     dialog.get_vbox()->pack_start(table);
546 persson 1733
547 schoenebeck 2562 // number of zones: use a combo box with fix values for gig
548     // v2 and a spin button for v3
549     Gtk::ComboBoxText comboZones;
550     Gtk::SpinButton spinZones;
551     bool version2 = false;
552     if (region) {
553     gig::File* file = (gig::File*)region->GetParent()->GetParent();
554     version2 = file->pVersion && file->pVersion->major == 2;
555     }
556     if (version2) {
557     for (int i = 1; i <= 5; i++) {
558     char buf[3];
559     sprintf(buf, "%d", 1 << i);
560 persson 2507 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
561 schoenebeck 2562 comboZones.append_text(buf);
562 persson 2169 #else
563 schoenebeck 2562 comboZones.append(buf);
564 persson 2169 #endif
565 schoenebeck 2562 }
566     table.attach(comboZones, 1, 2, 1, 2);
567     } else {
568     spinZones.set_increments(1, 8);
569     spinZones.set_numeric(true);
570     spinZones.set_range(2, 128);
571     spinZones.set_value(2);
572     table.attach(spinZones, 1, 2, 1, 2);
573     }
574    
575 persson 2845 dialog.add_button(_("_OK"), 0);
576     dialog.add_button(_("_Cancel"), 1);
577 schoenebeck 2562 dialog.show_all_children();
578    
579     if (!dialog.run()) { // OK selected ...
580     Gtk::TreeModel::iterator iterType = comboDimType.get_active();
581     if (!iterType) return;
582     Gtk::TreeModel::Row rowType = *iterType;
583     if (!rowType) return;
584     int iTypeID = rowType[comboModel.m_type_id];
585     gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
586     gig::dimension_def_t dim;
587     dim.dimension = type;
588    
589     if (version2) {
590     if (comboZones.get_active_row_number() < 0) return;
591     dim.bits = comboZones.get_active_row_number() + 1;
592     dim.zones = 1 << dim.bits;
593 persson 1733 } else {
594 schoenebeck 2562 dim.zones = spinZones.get_value_as_int();
595     dim.bits = zoneCountToBits(dim.zones);
596 persson 1733 }
597    
598 schoenebeck 2562 // assemble the list of regions where the selected dimension shall be
599     // added to
600     std::vector<gig::Region*> vRegions;
601     if (allRegions()) {
602     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
603     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
604     if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
605     }
606     } else vRegions.push_back(region);
607    
608     std::set<Glib::ustring> errors;
609 persson 1733
610 schoenebeck 2562 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
611     gig::Region* region = vRegions[iRgn];
612     try {
613     printf(
614     "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
615     dim.dimension, dim.bits, dim.zones
616     );
617     // notify everybody that we're going to update the region
618     region_to_be_changed_signal.emit(region);
619     // add the new dimension to the region
620     // (implicitly creates new dimension regions)
621     region->AddDimension(&dim);
622     // let everybody know there was a change
623     region_changed_signal.emit(region);
624     } catch (RIFF::Exception e) {
625     // notify that the changes are over (i.e. to avoid dead locks)
626     region_changed_signal.emit(region);
627     Glib::ustring txt = _("Could not add dimension: ") + e.Message;
628     if (vRegions.size() == 1) {
629     // show error message directly
630     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
631     msg.run();
632     } else {
633     // remember error, they are shown after all regions have been processed
634     errors.insert(txt);
635     }
636     }
637     }
638     // update all GUI elements
639     refreshManager();
640 persson 1733
641 schoenebeck 2562 if (!errors.empty()) {
642     Glib::ustring txt = _(
643     "The following errors occurred while trying to create the dimension on all regions:"
644     );
645     txt += "\n\n";
646     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
647     it != errors.end(); ++it)
648     {
649     txt += "-> " + *it + "\n";
650 persson 1733 }
651 schoenebeck 2562 txt += "\n";
652     txt += _(
653     "You might also want to check the console for further warnings and "
654     "error messages."
655 schoenebeck 1225 );
656 schoenebeck 2562 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
657     msg.run();
658 schoenebeck 1225 }
659     }
660     }
661    
662 schoenebeck 2562 void DimensionManager::removeDimension() {
663 schoenebeck 1225 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
664     Gtk::TreeModel::iterator it = sel->get_selected();
665     if (it) {
666 schoenebeck 2562 Gtk::TreeModel::Row row = *it;
667     gig::dimension_t type = row[tableModel.m_type];
668    
669     // assemble the list of regions where the selected dimension shall be
670     // added to
671     std::vector<gig::Region*> vRegions;
672     if (allRegions()) {
673     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
674     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
675     if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
676     }
677     } else vRegions.push_back(region);
678    
679     std::set<Glib::ustring> errors;
680    
681     for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
682     gig::Region* region = vRegions[iRgn];
683     gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
684     try {
685     // notify everybody that we're going to update the region
686     region_to_be_changed_signal.emit(region);
687     // remove selected dimension
688     region->DeleteDimension(dim);
689     // let everybody know there was a change
690     region_changed_signal.emit(region);
691     } catch (RIFF::Exception e) {
692     // notify that the changes are over (i.e. to avoid dead locks)
693     region_changed_signal.emit(region);
694     Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
695     if (vRegions.size() == 1) {
696     // show error message directly
697     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
698     msg.run();
699     } else {
700     // remember error, they are shown after all regions have been processed
701     errors.insert(txt);
702     }
703     }
704     }
705     // update all GUI elements
706     refreshManager();
707    
708     if (!errors.empty()) {
709     Glib::ustring txt = _(
710     "The following errors occurred while trying to remove the dimension from all regions:"
711     );
712     txt += "\n\n";
713     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
714     it != errors.end(); ++it)
715     {
716     txt += "-> " + *it + "\n";
717     }
718     txt += "\n";
719     txt += _(
720     "You might also want to check the console for further warnings and "
721     "error messages."
722     );
723 schoenebeck 1225 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
724     msg.run();
725     }
726     }
727     }

  ViewVC Help
Powered by ViewVC