/[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 3225 - (hide 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 persson 2169 /*
2 schoenebeck 3225 * Copyright (C) 2006-2017 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 schoenebeck 3225 if (!Settings::singleton()->autoRestoreWindowDimension) {
253     set_default_size(630, 250);
254     set_position(Gtk::WIN_POS_MOUSE);
255     }
256    
257 persson 1831 set_title(_("Dimensions of selected Region"));
258 schoenebeck 1225 add(vbox);
259     scrolledWindow.add(treeView);
260     vbox.pack_start(scrolledWindow);
261     scrolledWindow.show();
262 schoenebeck 1411 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
263 schoenebeck 1225 buttonBox.set_layout(Gtk::BUTTONBOX_END);
264     buttonBox.set_border_width(5);
265     buttonBox.show();
266 schoenebeck 2562 buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
267 schoenebeck 1411 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
268     buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
269 schoenebeck 1225 addButton.show();
270     removeButton.show();
271 schoenebeck 2562 allRegionsCheckBox.set_tooltip_text(
272     _("Enable this if you want to edit dimensions of all regions simultaniously.")
273     );
274 schoenebeck 1225
275     // setup the table
276     refTableModel = Gtk::ListStore::create(tableModel);
277     treeView.set_model(refTableModel);
278 schoenebeck 2562 treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
279     treeView.append_column(_("Bits"), m_cellRendererIntSet);
280     treeView.append_column(_("Zones"), m_cellRendererIntSet);
281 persson 1831 treeView.append_column(_("Description"), tableModel.m_description);
282 schoenebeck 2562 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 schoenebeck 1225 treeView.show();
288    
289 schoenebeck 2641 treeView.signal_cursor_changed().connect(
290     sigc::mem_fun(*this, &DimensionManager::onColumnClicked)
291     );
292    
293 schoenebeck 1225 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 schoenebeck 2562 allRegionsCheckBox.signal_toggled().connect(
301     sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
302     );
303 schoenebeck 1225
304     show_all_children();
305     }
306    
307 schoenebeck 2562 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 schoenebeck 1225 // update all GUI elements according to current gig::Region informations
334     void DimensionManager::refreshManager() {
335 schoenebeck 2562 set_sensitive(false);
336 schoenebeck 1225 refTableModel->clear();
337 schoenebeck 2562 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 persson 1677 }
360 schoenebeck 2562 } 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 schoenebeck 1225 }
378 persson 1677 set_sensitive(region);
379 schoenebeck 1225 }
380    
381     void DimensionManager::show(gig::Region* region) {
382 schoenebeck 2641 ignoreColumnClicked = true;
383 schoenebeck 1225 this->region = region;
384     refreshManager();
385     Gtk::Window::show();
386     deiconify();
387 schoenebeck 2641 ignoreColumnClicked = false;
388 schoenebeck 1225 }
389    
390 persson 1677 void DimensionManager::set_region(gig::Region* region) {
391 schoenebeck 2641 ignoreColumnClicked = true;
392 persson 1677 this->region = region;
393     refreshManager();
394 schoenebeck 2641 ignoreColumnClicked = false;
395 persson 1677 }
396    
397 schoenebeck 2641 void DimensionManager::onColumnClicked() {
398 schoenebeck 2919 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 schoenebeck 2641 //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 schoenebeck 2921 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
408 schoenebeck 2919 // prevents app to crash if this dialog is closed
409     if (!get_visible())
410     return;
411 schoenebeck 2921 #else
412     # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
413     #endif
414 schoenebeck 2641
415 schoenebeck 2976 #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
416     if (!is_visible()) return;
417     #endif
418    
419 schoenebeck 2641 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 schoenebeck 2976 if (!it) return;
426 schoenebeck 2641 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 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
454     dialog.add_button(Gtk::Stock::CANCEL, 1);
455 schoenebeck 2641 dialog.show_all_children();
456    
457     comboDimType.set_active(oldTypeIndex);
458    
459     if (!dialog.run()) { // OK selected ...
460 schoenebeck 2919 ignoreColumnClicked = true;
461 schoenebeck 2641 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 schoenebeck 3105 } 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 schoenebeck 2641 }
532     }
533    
534 schoenebeck 1225 void DimensionManager::addDimension() {
535 schoenebeck 2562 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 schoenebeck 1225 }
546 schoenebeck 2562 }
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 persson 1733
559 schoenebeck 2562 // 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 persson 2507 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
573 schoenebeck 2562 comboZones.append_text(buf);
574 persson 2169 #else
575 schoenebeck 2562 comboZones.append(buf);
576 persson 2169 #endif
577 schoenebeck 2562 }
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 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
588     dialog.add_button(Gtk::Stock::CANCEL, 1);
589 schoenebeck 2562 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 persson 1733 } else {
606 schoenebeck 2562 dim.zones = spinZones.get_value_as_int();
607     dim.bits = zoneCountToBits(dim.zones);
608 persson 1733 }
609    
610 schoenebeck 2562 // 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 persson 1733
622 schoenebeck 2562 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 persson 1733
653 schoenebeck 2562 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 persson 1733 }
663 schoenebeck 2562 txt += "\n";
664     txt += _(
665     "You might also want to check the console for further warnings and "
666     "error messages."
667 schoenebeck 1225 );
668 schoenebeck 2562 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
669     msg.run();
670 schoenebeck 1225 }
671     }
672     }
673    
674 schoenebeck 2562 void DimensionManager::removeDimension() {
675 schoenebeck 1225 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
676     Gtk::TreeModel::iterator it = sel->get_selected();
677     if (it) {
678 schoenebeck 2562 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 schoenebeck 1225 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
736     msg.run();
737     }
738     }
739     }

  ViewVC Help
Powered by ViewVC