/[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 3158 - (hide annotations) (download)
Mon May 8 18:05:35 2017 UTC (6 years, 11 months ago) by schoenebeck
File size: 30106 byte(s)
* Reverted major parts of r2845 concerning deprected Gtk StockIDs
  (StockIDs still available with Gtk 3, no replacement API available,
  and these changes caused useful icons to vanish with Gtk 2).
* Bumped version (1.0.0.svn39).

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 schoenebeck 3158 #include <gtkmm/stock.h>
31 schoenebeck 1225 #include <gtkmm/messagedialog.h>
32     #include <gtkmm/dialog.h>
33     #include <gtkmm/comboboxtext.h>
34 persson 1733 #include <gtkmm/spinbutton.h>
35     #include <gtkmm/table.h>
36 schoenebeck 1225
37 persson 1831 #include "global.h"
38 persson 2169 #include "compat.h"
39 persson 1831
40 schoenebeck 1225 // returns a human readable name of the given dimension type
41 schoenebeck 2558 Glib::ustring dimTypeAsString(gig::dimension_t d) {
42 schoenebeck 1225 char buf[32];
43     switch (d) {
44     case gig::dimension_none:
45 persson 1831 return _("None");
46 schoenebeck 1225 case gig::dimension_samplechannel:
47 persson 1831 return _("Sample Channel");
48 schoenebeck 1225 case gig::dimension_layer:
49 persson 1831 return _("Layer");
50 schoenebeck 1225 case gig::dimension_velocity:
51 persson 1831 return _("Velocity");
52 schoenebeck 1225 case gig::dimension_channelaftertouch:
53 persson 1831 return _("Aftertouch");
54 schoenebeck 1225 case gig::dimension_releasetrigger:
55 persson 1831 return _("Release Trigger");
56 schoenebeck 1225 case gig::dimension_keyboard:
57 persson 1831 return _("Keyswitching");
58 schoenebeck 1225 case gig::dimension_roundrobin:
59 persson 1831 return _("Round Robin");
60 schoenebeck 1225 case gig::dimension_random:
61 persson 1831 return _("Random Generator");
62 schoenebeck 1225 case gig::dimension_smartmidi:
63 persson 1831 return _("Smart MIDI");
64 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
65 persson 1831 return _("Keyboard Round Robin");
66 schoenebeck 1225 case gig::dimension_modwheel:
67 persson 1831 return _("Modulation Wheel");
68 schoenebeck 1225 case gig::dimension_breath:
69 persson 1831 return _("Breath Ctrl.");
70 schoenebeck 1225 case gig::dimension_foot:
71 persson 1831 return _("Foot Ctrl.");
72 schoenebeck 1225 case gig::dimension_portamentotime:
73 persson 1831 return _("Portamento Time Ctrl.");
74 schoenebeck 1225 case gig::dimension_effect1:
75 persson 1831 return _("Effect Ctrl. 1");
76 schoenebeck 1225 case gig::dimension_effect2:
77 persson 1831 return _("Effect Ctrl. 2");
78 schoenebeck 1225 case gig::dimension_genpurpose1:
79 persson 1831 return _("General Purpose Ctrl. 1");
80 schoenebeck 1225 case gig::dimension_genpurpose2:
81 persson 1831 return _("General Purpose Ctrl. 2");
82 schoenebeck 1225 case gig::dimension_genpurpose3:
83 persson 1831 return _("General Purpose Ctrl. 3");
84 schoenebeck 1225 case gig::dimension_genpurpose4:
85 persson 1831 return _("General Purpose Ctrl. 4");
86 schoenebeck 1225 case gig::dimension_sustainpedal:
87 persson 1831 return _("Sustain Pedal");
88 schoenebeck 1225 case gig::dimension_portamento:
89 persson 1831 return _("Portamento Ctrl.");
90 schoenebeck 1225 case gig::dimension_sostenutopedal:
91 persson 1831 return _("Sostenuto Pedal");
92 schoenebeck 1225 case gig::dimension_softpedal:
93 persson 1831 return _("Soft Pedal");
94 schoenebeck 1225 case gig::dimension_genpurpose5:
95 persson 1831 return _("General Purpose Ctrl. 5");
96 schoenebeck 1225 case gig::dimension_genpurpose6:
97 persson 1831 return _("General Purpose Ctrl. 6");
98 schoenebeck 1225 case gig::dimension_genpurpose7:
99 persson 1831 return _("General Purpose Ctrl. 7");
100 schoenebeck 1225 case gig::dimension_genpurpose8:
101 persson 1831 return _("General Purpose Ctrl. 8");
102 schoenebeck 1225 case gig::dimension_effect1depth:
103 persson 1831 return _("Effect 1 Depth");
104 schoenebeck 1225 case gig::dimension_effect2depth:
105 persson 1831 return _("Effect 2 Depth");
106 schoenebeck 1225 case gig::dimension_effect3depth:
107 persson 1831 return _("Effect 3 Depth");
108 schoenebeck 1225 case gig::dimension_effect4depth:
109 persson 1831 return _("Effect 4 Depth");
110 schoenebeck 1225 case gig::dimension_effect5depth:
111 persson 1831 return _("Effect 5 Depth");
112 schoenebeck 1225 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 persson 1831 return _("Dimension not in use");
123 schoenebeck 1225 case gig::dimension_samplechannel:
124 persson 1831 return _("If used sample has more than one channel (thus is not mono)");
125 schoenebeck 1225 case gig::dimension_layer:
126 persson 1831 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
127 schoenebeck 1225 case gig::dimension_velocity:
128 persson 1831 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
129 schoenebeck 1225 case gig::dimension_channelaftertouch:
130 persson 1831 return _("Channel Key Pressure");
131 schoenebeck 1225 case gig::dimension_releasetrigger:
132 persson 1831 return _("Special dimension for triggering samples on releasing a key");
133 schoenebeck 1225 case gig::dimension_keyboard:
134 persson 1831 return _("Dimension for keyswitching (keyboard)");
135 schoenebeck 1225 case gig::dimension_roundrobin:
136 persson 1831 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
137 schoenebeck 1225 case gig::dimension_random:
138 persson 1831 return _("Different samples triggered each time a note is played, random order");
139 schoenebeck 1225 case gig::dimension_smartmidi:
140 persson 1831 return _("For MIDI tools like legato and repetition mode");
141 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
142 persson 1831 return _("Different samples triggered each time a note is played, any key advances the counter");
143 schoenebeck 1225 case gig::dimension_modwheel:
144 persson 1831 return _("MIDI Controller 1");
145 schoenebeck 1225 case gig::dimension_breath:
146 persson 1831 return _("MIDI Controller 2");
147 schoenebeck 1225 case gig::dimension_foot:
148 persson 1831 return _("MIDI Controller 4");
149 schoenebeck 1225 case gig::dimension_portamentotime:
150 persson 1831 return _("MIDI Controller 5");
151 schoenebeck 1225 case gig::dimension_effect1:
152 persson 1831 return _("MIDI Controller 12");
153 schoenebeck 1225 case gig::dimension_effect2:
154 persson 1831 return _("MIDI Controller 13");
155 schoenebeck 1225 case gig::dimension_genpurpose1:
156 persson 1831 return _("Slider, MIDI Controller 16");
157 schoenebeck 1225 case gig::dimension_genpurpose2:
158 persson 1831 return _("Slider, MIDI Controller 17");
159 schoenebeck 1225 case gig::dimension_genpurpose3:
160 persson 1831 return _("Slider, MIDI Controller 18");
161 schoenebeck 1225 case gig::dimension_genpurpose4:
162 persson 1831 return _("Slider, MIDI Controller 19");
163 schoenebeck 1225 case gig::dimension_sustainpedal:
164 persson 1831 return _("MIDI Controller 64");
165 schoenebeck 1225 case gig::dimension_portamento:
166 persson 1831 return _("MIDI Controller 65");
167 schoenebeck 1225 case gig::dimension_sostenutopedal:
168 persson 1831 return _("MIDI Controller 66");
169 schoenebeck 1225 case gig::dimension_softpedal:
170 persson 1831 return _("MIDI Controller 67");
171 schoenebeck 1225 case gig::dimension_genpurpose5:
172 persson 1831 return _("Button, MIDI Controller 80");
173 schoenebeck 1225 case gig::dimension_genpurpose6:
174 persson 1831 return _("Button, MIDI Controller 81");
175 schoenebeck 1225 case gig::dimension_genpurpose7:
176 persson 1831 return _("Button, MIDI Controller 82");
177 schoenebeck 1225 case gig::dimension_genpurpose8:
178 persson 1831 return _("Button, MIDI Controller 83");
179 schoenebeck 1225 case gig::dimension_effect1depth:
180 persson 1831 return _("MIDI Controller 91");
181 schoenebeck 1225 case gig::dimension_effect2depth:
182 persson 1831 return _("MIDI Controller 92");
183 schoenebeck 1225 case gig::dimension_effect3depth:
184 persson 1831 return _("MIDI Controller 93");
185 schoenebeck 1225 case gig::dimension_effect4depth:
186 persson 1831 return _("MIDI Controller 94");
187 schoenebeck 1225 case gig::dimension_effect5depth:
188 persson 1831 return _("MIDI Controller 95");
189 schoenebeck 1225 default:
190 persson 1831 return _("Please report this !!!");
191 schoenebeck 1225 }
192     }
193    
194 schoenebeck 2562 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 schoenebeck 1225 DimensionManager::DimensionManager() :
247 schoenebeck 3158 addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE),
248 persson 2845 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 schoenebeck 2976 #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
413     if (!is_visible()) return;
414     #endif
415    
416 schoenebeck 2641 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 schoenebeck 2976 if (!it) return;
423 schoenebeck 2641 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 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
451     dialog.add_button(Gtk::Stock::CANCEL, 1);
452 schoenebeck 2641 dialog.show_all_children();
453    
454     comboDimType.set_active(oldTypeIndex);
455    
456     if (!dialog.run()) { // OK selected ...
457 schoenebeck 2919 ignoreColumnClicked = true;
458 schoenebeck 2641 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 schoenebeck 3105 } 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 schoenebeck 2641 }
529     }
530    
531 schoenebeck 1225 void DimensionManager::addDimension() {
532 schoenebeck 2562 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 schoenebeck 1225 }
543 schoenebeck 2562 }
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 persson 1733
556 schoenebeck 2562 // 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 persson 2507 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
570 schoenebeck 2562 comboZones.append_text(buf);
571 persson 2169 #else
572 schoenebeck 2562 comboZones.append(buf);
573 persson 2169 #endif
574 schoenebeck 2562 }
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 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
585     dialog.add_button(Gtk::Stock::CANCEL, 1);
586 schoenebeck 2562 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 persson 1733 } else {
603 schoenebeck 2562 dim.zones = spinZones.get_value_as_int();
604     dim.bits = zoneCountToBits(dim.zones);
605 persson 1733 }
606    
607 schoenebeck 2562 // 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 persson 1733
619 schoenebeck 2562 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 persson 1733
650 schoenebeck 2562 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 persson 1733 }
660 schoenebeck 2562 txt += "\n";
661     txt += _(
662     "You might also want to check the console for further warnings and "
663     "error messages."
664 schoenebeck 1225 );
665 schoenebeck 2562 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
666     msg.run();
667 schoenebeck 1225 }
668     }
669     }
670    
671 schoenebeck 2562 void DimensionManager::removeDimension() {
672 schoenebeck 1225 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
673     Gtk::TreeModel::iterator it = sel->get_selected();
674     if (it) {
675 schoenebeck 2562 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 schoenebeck 1225 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
733     msg.run();
734     }
735     }
736     }

  ViewVC Help
Powered by ViewVC