/[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 3450 - (hide annotations) (download)
Wed Jan 2 16:39:20 2019 UTC (5 years, 3 months ago) by schoenebeck
File size: 31942 byte(s)
* Fixed compiler errors with Gtk 3.24.x (patch by Miroslav Ć ulc).

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 schoenebeck 3364 #include "compat.h"
21 persson 2844 // 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 3364 #if HAS_GTKMM_STOCK
31     # include <gtkmm/stock.h>
32     #endif
33 schoenebeck 1225 #include <gtkmm/messagedialog.h>
34     #include <gtkmm/dialog.h>
35     #include <gtkmm/comboboxtext.h>
36 persson 1733 #include <gtkmm/spinbutton.h>
37 schoenebeck 3364 #include <gtkmm/label.h>
38     #if USE_GTKMM_GRID
39     # include <gtkmm/grid.h>
40     #else
41     # include <gtkmm/table.h>
42     #endif
43 schoenebeck 1225
44 persson 1831 #include "global.h"
45 persson 2169 #include "compat.h"
46 persson 1831
47 schoenebeck 1225 // returns a human readable name of the given dimension type
48 schoenebeck 2558 Glib::ustring dimTypeAsString(gig::dimension_t d) {
49 schoenebeck 1225 char buf[32];
50     switch (d) {
51     case gig::dimension_none:
52 persson 1831 return _("None");
53 schoenebeck 1225 case gig::dimension_samplechannel:
54 persson 1831 return _("Sample Channel");
55 schoenebeck 1225 case gig::dimension_layer:
56 persson 1831 return _("Layer");
57 schoenebeck 1225 case gig::dimension_velocity:
58 persson 1831 return _("Velocity");
59 schoenebeck 1225 case gig::dimension_channelaftertouch:
60 persson 1831 return _("Aftertouch");
61 schoenebeck 1225 case gig::dimension_releasetrigger:
62 persson 1831 return _("Release Trigger");
63 schoenebeck 1225 case gig::dimension_keyboard:
64 persson 1831 return _("Keyswitching");
65 schoenebeck 1225 case gig::dimension_roundrobin:
66 persson 1831 return _("Round Robin");
67 schoenebeck 1225 case gig::dimension_random:
68 persson 1831 return _("Random Generator");
69 schoenebeck 1225 case gig::dimension_smartmidi:
70 persson 1831 return _("Smart MIDI");
71 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
72 persson 1831 return _("Keyboard Round Robin");
73 schoenebeck 1225 case gig::dimension_modwheel:
74 persson 1831 return _("Modulation Wheel");
75 schoenebeck 1225 case gig::dimension_breath:
76 persson 1831 return _("Breath Ctrl.");
77 schoenebeck 1225 case gig::dimension_foot:
78 persson 1831 return _("Foot Ctrl.");
79 schoenebeck 1225 case gig::dimension_portamentotime:
80 persson 1831 return _("Portamento Time Ctrl.");
81 schoenebeck 1225 case gig::dimension_effect1:
82 persson 1831 return _("Effect Ctrl. 1");
83 schoenebeck 1225 case gig::dimension_effect2:
84 persson 1831 return _("Effect Ctrl. 2");
85 schoenebeck 1225 case gig::dimension_genpurpose1:
86 persson 1831 return _("General Purpose Ctrl. 1");
87 schoenebeck 1225 case gig::dimension_genpurpose2:
88 persson 1831 return _("General Purpose Ctrl. 2");
89 schoenebeck 1225 case gig::dimension_genpurpose3:
90 persson 1831 return _("General Purpose Ctrl. 3");
91 schoenebeck 1225 case gig::dimension_genpurpose4:
92 persson 1831 return _("General Purpose Ctrl. 4");
93 schoenebeck 1225 case gig::dimension_sustainpedal:
94 persson 1831 return _("Sustain Pedal");
95 schoenebeck 1225 case gig::dimension_portamento:
96 persson 1831 return _("Portamento Ctrl.");
97 schoenebeck 1225 case gig::dimension_sostenutopedal:
98 persson 1831 return _("Sostenuto Pedal");
99 schoenebeck 1225 case gig::dimension_softpedal:
100 persson 1831 return _("Soft Pedal");
101 schoenebeck 1225 case gig::dimension_genpurpose5:
102 persson 1831 return _("General Purpose Ctrl. 5");
103 schoenebeck 1225 case gig::dimension_genpurpose6:
104 persson 1831 return _("General Purpose Ctrl. 6");
105 schoenebeck 1225 case gig::dimension_genpurpose7:
106 persson 1831 return _("General Purpose Ctrl. 7");
107 schoenebeck 1225 case gig::dimension_genpurpose8:
108 persson 1831 return _("General Purpose Ctrl. 8");
109 schoenebeck 1225 case gig::dimension_effect1depth:
110 persson 1831 return _("Effect 1 Depth");
111 schoenebeck 1225 case gig::dimension_effect2depth:
112 persson 1831 return _("Effect 2 Depth");
113 schoenebeck 1225 case gig::dimension_effect3depth:
114 persson 1831 return _("Effect 3 Depth");
115 schoenebeck 1225 case gig::dimension_effect4depth:
116 persson 1831 return _("Effect 4 Depth");
117 schoenebeck 1225 case gig::dimension_effect5depth:
118 persson 1831 return _("Effect 5 Depth");
119 schoenebeck 1225 default:
120     sprintf(buf, "Unknown Type (0x%x) !!!", d);
121     return buf;
122     }
123     }
124    
125     // returns a human readable description of the given dimension
126     static Glib::ustring __dimDescriptionAsString(gig::dimension_t d) {
127     switch (d) {
128     case gig::dimension_none:
129 persson 1831 return _("Dimension not in use");
130 schoenebeck 1225 case gig::dimension_samplechannel:
131 persson 1831 return _("If used sample has more than one channel (thus is not mono)");
132 schoenebeck 1225 case gig::dimension_layer:
133 persson 1831 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
134 schoenebeck 1225 case gig::dimension_velocity:
135 persson 1831 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
136 schoenebeck 1225 case gig::dimension_channelaftertouch:
137 persson 1831 return _("Channel Key Pressure");
138 schoenebeck 1225 case gig::dimension_releasetrigger:
139 persson 1831 return _("Special dimension for triggering samples on releasing a key");
140 schoenebeck 1225 case gig::dimension_keyboard:
141 persson 1831 return _("Dimension for keyswitching (keyboard)");
142 schoenebeck 1225 case gig::dimension_roundrobin:
143 persson 1831 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
144 schoenebeck 1225 case gig::dimension_random:
145 persson 1831 return _("Different samples triggered each time a note is played, random order");
146 schoenebeck 1225 case gig::dimension_smartmidi:
147 persson 1831 return _("For MIDI tools like legato and repetition mode");
148 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
149 persson 1831 return _("Different samples triggered each time a note is played, any key advances the counter");
150 schoenebeck 1225 case gig::dimension_modwheel:
151 persson 1831 return _("MIDI Controller 1");
152 schoenebeck 1225 case gig::dimension_breath:
153 persson 1831 return _("MIDI Controller 2");
154 schoenebeck 1225 case gig::dimension_foot:
155 persson 1831 return _("MIDI Controller 4");
156 schoenebeck 1225 case gig::dimension_portamentotime:
157 persson 1831 return _("MIDI Controller 5");
158 schoenebeck 1225 case gig::dimension_effect1:
159 persson 1831 return _("MIDI Controller 12");
160 schoenebeck 1225 case gig::dimension_effect2:
161 persson 1831 return _("MIDI Controller 13");
162 schoenebeck 1225 case gig::dimension_genpurpose1:
163 persson 1831 return _("Slider, MIDI Controller 16");
164 schoenebeck 1225 case gig::dimension_genpurpose2:
165 persson 1831 return _("Slider, MIDI Controller 17");
166 schoenebeck 1225 case gig::dimension_genpurpose3:
167 persson 1831 return _("Slider, MIDI Controller 18");
168 schoenebeck 1225 case gig::dimension_genpurpose4:
169 persson 1831 return _("Slider, MIDI Controller 19");
170 schoenebeck 1225 case gig::dimension_sustainpedal:
171 persson 1831 return _("MIDI Controller 64");
172 schoenebeck 1225 case gig::dimension_portamento:
173 persson 1831 return _("MIDI Controller 65");
174 schoenebeck 1225 case gig::dimension_sostenutopedal:
175 persson 1831 return _("MIDI Controller 66");
176 schoenebeck 1225 case gig::dimension_softpedal:
177 persson 1831 return _("MIDI Controller 67");
178 schoenebeck 1225 case gig::dimension_genpurpose5:
179 persson 1831 return _("Button, MIDI Controller 80");
180 schoenebeck 1225 case gig::dimension_genpurpose6:
181 persson 1831 return _("Button, MIDI Controller 81");
182 schoenebeck 1225 case gig::dimension_genpurpose7:
183 persson 1831 return _("Button, MIDI Controller 82");
184 schoenebeck 1225 case gig::dimension_genpurpose8:
185 persson 1831 return _("Button, MIDI Controller 83");
186 schoenebeck 1225 case gig::dimension_effect1depth:
187 persson 1831 return _("MIDI Controller 91");
188 schoenebeck 1225 case gig::dimension_effect2depth:
189 persson 1831 return _("MIDI Controller 92");
190 schoenebeck 1225 case gig::dimension_effect3depth:
191 persson 1831 return _("MIDI Controller 93");
192 schoenebeck 1225 case gig::dimension_effect4depth:
193 persson 1831 return _("MIDI Controller 94");
194 schoenebeck 1225 case gig::dimension_effect5depth:
195 persson 1831 return _("MIDI Controller 95");
196 schoenebeck 1225 default:
197 persson 1831 return _("Please report this !!!");
198 schoenebeck 1225 }
199     }
200    
201 schoenebeck 2562 DimTypeCellRenderer::DimTypeCellRenderer() :
202     Glib::ObjectBase(typeid(DimTypeCellRenderer)),
203     Gtk::CellRendererText(),
204     m_propertyDimType(*this, "gigdimension_t", gig::dimension_none),
205     m_propertyUsageCount(*this, "intusagecount", 0),
206     m_propertyTotalRegions(*this, "inttotalregions", 0)
207     {
208     propertyDimType().signal_changed().connect(
209     sigc::mem_fun(*this, &DimTypeCellRenderer::typeChanged)
210     );
211     propertyUsageCount().signal_changed().connect(
212     sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
213     );
214     propertyTotalRegions().signal_changed().connect(
215     sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
216     );
217     }
218    
219     void DimTypeCellRenderer::typeChanged() {
220     gig::dimension_t type = propertyDimType();
221     Glib::ustring s = dimTypeAsString(type);
222     property_text() = s;
223     }
224    
225     void DimTypeCellRenderer::statsChanged() {
226     int usageCount = propertyUsageCount();
227     int totalRegions = propertyTotalRegions();
228     bool bDimensionExistsOnAllRegions = (usageCount == totalRegions);
229     property_foreground() = ((bDimensionExistsOnAllRegions) ? "black" : "gray");
230     }
231    
232     IntSetCellRenderer::IntSetCellRenderer() :
233     Glib::ObjectBase(typeid(IntSetCellRenderer)),
234     Gtk::CellRendererText(),
235     m_propertyValue(*this, "stdintset", std::set<int>())
236     {
237     propertyValue().signal_changed().connect(
238     sigc::mem_fun(*this, &IntSetCellRenderer::valueChanged)
239     );
240     }
241    
242     void IntSetCellRenderer::valueChanged() {
243     Glib::ustring s;
244     std::set<int> v = propertyValue();
245     for (std::set<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
246     s += ToString(*it);
247     if (*it != *v.rbegin()) s += "|";
248     }
249     property_text() = s;
250     property_foreground() = (v.size() > 1) ? "gray" : "black";
251     }
252    
253 schoenebeck 1225 DimensionManager::DimensionManager() :
254 schoenebeck 3364 #if HAS_GTKMM_STOCK
255 schoenebeck 3158 addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE),
256 schoenebeck 3364 #else
257     addButton(_("_Add"), true), removeButton(_("_Remove"), true),
258     #endif
259 persson 2845 allRegionsCheckBox(_("All Regions"))
260 schoenebeck 1225 {
261 schoenebeck 2641 ignoreColumnClicked = true;
262    
263 schoenebeck 3225 if (!Settings::singleton()->autoRestoreWindowDimension) {
264     set_default_size(630, 250);
265     set_position(Gtk::WIN_POS_MOUSE);
266     }
267    
268 schoenebeck 3364 #if !HAS_GTKMM_STOCK
269     // see : https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
270     addButton.set_icon_name("list-add");
271     removeButton.set_icon_name("list-remove");
272     #endif
273    
274 persson 1831 set_title(_("Dimensions of selected Region"));
275 schoenebeck 1225 add(vbox);
276     scrolledWindow.add(treeView);
277     vbox.pack_start(scrolledWindow);
278     scrolledWindow.show();
279 schoenebeck 1411 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
280 schoenebeck 1225 buttonBox.set_layout(Gtk::BUTTONBOX_END);
281 schoenebeck 3450 #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
282 schoenebeck 3364 buttonBox.set_margin(5);
283     #else
284 schoenebeck 1225 buttonBox.set_border_width(5);
285 schoenebeck 3364 #endif
286 schoenebeck 1225 buttonBox.show();
287 schoenebeck 2562 buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
288 schoenebeck 1411 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
289     buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
290 schoenebeck 1225 addButton.show();
291     removeButton.show();
292 schoenebeck 2562 allRegionsCheckBox.set_tooltip_text(
293     _("Enable this if you want to edit dimensions of all regions simultaniously.")
294     );
295 schoenebeck 1225
296     // setup the table
297     refTableModel = Gtk::ListStore::create(tableModel);
298     treeView.set_model(refTableModel);
299 schoenebeck 2562 treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
300     treeView.append_column(_("Bits"), m_cellRendererIntSet);
301     treeView.append_column(_("Zones"), m_cellRendererIntSet);
302 persson 1831 treeView.append_column(_("Description"), tableModel.m_description);
303 schoenebeck 2562 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyDimType(), tableModel.m_type);
304     treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyUsageCount(), tableModel.m_usageCount);
305     treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyTotalRegions(), tableModel.m_totalRegions);
306     treeView.get_column(1)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_bits);
307     treeView.get_column(2)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_zones);
308 schoenebeck 1225 treeView.show();
309    
310 schoenebeck 2641 treeView.signal_cursor_changed().connect(
311     sigc::mem_fun(*this, &DimensionManager::onColumnClicked)
312     );
313    
314 schoenebeck 1225 addButton.signal_clicked().connect(
315     sigc::mem_fun(*this, &DimensionManager::addDimension)
316     );
317    
318     removeButton.signal_clicked().connect(
319     sigc::mem_fun(*this, &DimensionManager::removeDimension)
320     );
321 schoenebeck 2562 allRegionsCheckBox.signal_toggled().connect(
322     sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
323     );
324 schoenebeck 1225
325 schoenebeck 3364 #if HAS_GTKMM_SHOW_ALL_CHILDREN
326 schoenebeck 1225 show_all_children();
327 schoenebeck 3364 #endif
328 schoenebeck 3409
329     Settings::singleton()->showTooltips.get_proxy().signal_changed().connect(
330     sigc::mem_fun(*this, &DimensionManager::on_show_tooltips_changed)
331     );
332     on_show_tooltips_changed();
333 schoenebeck 1225 }
334    
335 schoenebeck 3409 void DimensionManager::on_show_tooltips_changed() {
336     const bool b = Settings::singleton()->showTooltips;
337    
338     treeView.set_has_tooltip(b);
339     allRegionsCheckBox.set_has_tooltip(b);
340    
341     set_has_tooltip(b);
342     }
343    
344 schoenebeck 2562 bool DimensionManager::allRegions() const {
345     return allRegionsCheckBox.get_active();
346     }
347    
348     void DimensionManager::onAllRegionsCheckBoxToggled() {
349     set_title(
350     allRegions() ? _("Dimensions of all Regions") : _("Dimensions of selected Region")
351     );
352     treeView.set_tooltip_text(
353     allRegions()
354     ? _("Dimensions and numbers in gray indicates a difference among the individual regions.")
355     : _("You are currently only viewing dimensions of the currently selected region.")
356     );
357     refreshManager();
358     }
359    
360     // following two data types are just used in DimensionManager::refresManager(),
361     // due to the maps template nature however, they must be declared at global
362     // space to avoid compilation errors
363     struct _DimDef {
364     std::set<int> bits;
365     std::set<int> zones;
366     int usageCount;
367     };
368     typedef std::map<gig::dimension_t, _DimDef> _Dimensions;
369    
370 schoenebeck 3408 // update all GUI elements according to current gig::Region information
371 schoenebeck 1225 void DimensionManager::refreshManager() {
372 schoenebeck 2562 set_sensitive(false);
373 schoenebeck 1225 refTableModel->clear();
374 schoenebeck 2562 if (allRegions()) {
375     if (region) {
376     _Dimensions dims;
377     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
378     int iRegionsCount = 0;
379     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
380     for (uint i = 0; i < rgn->Dimensions; i++) {
381     gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
382     dims[dim->dimension].bits.insert(dim->bits);
383     dims[dim->dimension].zones.insert(dim->zones);
384     dims[dim->dimension].usageCount++;
385     }
386     }
387     for (_Dimensions::const_iterator it = dims.begin(); it != dims.end(); ++it) {
388     Gtk::TreeModel::Row row = *(refTableModel->append());
389     row[tableModel.m_type] = it->first;
390     row[tableModel.m_bits] = it->second.bits;
391     row[tableModel.m_zones] = it->second.zones;
392     row[tableModel.m_description] = __dimDescriptionAsString(it->first);
393     row[tableModel.m_usageCount] = it->second.usageCount;
394     row[tableModel.m_totalRegions] = iRegionsCount;
395     }
396 persson 1677 }
397 schoenebeck 2562 } else {
398     if (region) {
399     for (uint i = 0; i < region->Dimensions; i++) {
400     gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
401     Gtk::TreeModel::Row row = *(refTableModel->append());
402     std::set<int> vBits;
403     vBits.insert(dim->bits);
404     row[tableModel.m_bits] = vBits;
405     std::set<int> vZones;
406     vZones.insert(dim->zones);
407     row[tableModel.m_zones] = vZones;
408     row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
409     row[tableModel.m_type] = dim->dimension;
410     row[tableModel.m_usageCount] = 1;
411     row[tableModel.m_totalRegions] = 1;
412     }
413     }
414 schoenebeck 1225 }
415 persson 1677 set_sensitive(region);
416 schoenebeck 1225 }
417    
418     void DimensionManager::show(gig::Region* region) {
419 schoenebeck 2641 ignoreColumnClicked = true;
420 schoenebeck 1225 this->region = region;
421     refreshManager();
422     Gtk::Window::show();
423     deiconify();
424 schoenebeck 2641 ignoreColumnClicked = false;
425 schoenebeck 1225 }
426    
427 persson 1677 void DimensionManager::set_region(gig::Region* region) {
428 schoenebeck 2641 ignoreColumnClicked = true;
429 persson 1677 this->region = region;
430     refreshManager();
431 schoenebeck 2641 ignoreColumnClicked = false;
432 persson 1677 }
433    
434 schoenebeck 2641 void DimensionManager::onColumnClicked() {
435 schoenebeck 2919 printf("DimensionManager::onColumnClicked()\n");
436    
437     //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 !
438    
439 schoenebeck 2641 //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
440     if (ignoreColumnClicked) {
441     ignoreColumnClicked = false;
442     return;
443     }
444 schoenebeck 2921 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
445 schoenebeck 2919 // prevents app to crash if this dialog is closed
446     if (!get_visible())
447     return;
448 schoenebeck 2921 #else
449     # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
450     #endif
451 schoenebeck 2641
452 schoenebeck 2976 #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
453     if (!is_visible()) return;
454     #endif
455    
456 schoenebeck 2641 Gtk::TreeModel::Path path;
457     Gtk::TreeViewColumn* focus_column;
458     treeView.get_cursor(path, focus_column);
459     //const int row = path[0];
460     if (focus_column == treeView.get_column(0)) {
461     Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
462 schoenebeck 2976 if (!it) return;
463 schoenebeck 2641 Gtk::TreeModel::Row row = *it;
464     gig::dimension_t oldType = row[tableModel.m_type];
465    
466     Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
467     int oldTypeIndex = -1;
468     Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
469     for (int i = 0x01, count = 0; i < 0xff; i++) {
470     Glib::ustring sType =
471     dimTypeAsString(static_cast<gig::dimension_t>(i));
472     if (i == oldType) oldTypeIndex = count;
473     if (sType.find("Unknown") != 0) {
474     Gtk::TreeModel::Row row = *(refComboModel->append());
475     row[comboModel.m_type_id] = i;
476     row[comboModel.m_type_name] = sType;
477     count++;
478     }
479     }
480 schoenebeck 3364 #if USE_GTKMM_GRID
481     Gtk::Grid table;
482     #else
483 schoenebeck 2641 Gtk::Table table(1, 2);
484 schoenebeck 3364 #endif
485 schoenebeck 2641 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
486     Gtk::ComboBox comboDimType;
487     comboDimType.set_model(refComboModel);
488     comboDimType.pack_start(comboModel.m_type_id);
489     comboDimType.pack_start(comboModel.m_type_name);
490     table.attach(labelDimType, 0, 1, 0, 1);
491     table.attach(comboDimType, 1, 2, 0, 1);
492 schoenebeck 3364 #if USE_GTKMM_BOX
493     dialog.get_content_area()->pack_start(table);
494     #else
495 schoenebeck 2641 dialog.get_vbox()->pack_start(table);
496 schoenebeck 3364 #endif
497 schoenebeck 2641
498 schoenebeck 3364 #if HAS_GTKMM_STOCK
499 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
500     dialog.add_button(Gtk::Stock::CANCEL, 1);
501 schoenebeck 3364 #else
502     dialog.add_button(_("_OK"), 0);
503     dialog.add_button(_("_Cancel"), 1);
504     #endif
505     #if HAS_GTKMM_SHOW_ALL_CHILDREN
506 schoenebeck 2641 dialog.show_all_children();
507 schoenebeck 3364 #endif
508 schoenebeck 2641
509     comboDimType.set_active(oldTypeIndex);
510    
511     if (!dialog.run()) { // OK selected ...
512 schoenebeck 2919 ignoreColumnClicked = true;
513 schoenebeck 2641 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
514     if (!iterType) return;
515     Gtk::TreeModel::Row rowType = *iterType;
516     if (!rowType) return;
517     int iTypeID = rowType[comboModel.m_type_id];
518     gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
519     if (newType == oldType) return;
520     //printf("change 0x%x -> 0x%x\n", oldType, newType);
521    
522     // assemble the list of regions where the selected dimension type
523     // shall be changed
524     std::vector<gig::Region*> vRegions;
525     if (allRegions()) {
526     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
527     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
528     if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
529     }
530     } else vRegions.push_back(region);
531    
532     std::set<Glib::ustring> errors;
533    
534     for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
535     gig::Region* region = vRegions[iRgn];
536     try {
537     // notify everybody that we're going to update the region
538     region_to_be_changed_signal.emit(region);
539     // change the dimension type on that region
540     region->SetDimensionType(oldType, newType);
541     // let everybody know there was a change
542     region_changed_signal.emit(region);
543     } catch (RIFF::Exception e) {
544     // notify that the changes are over (i.e. to avoid dead locks)
545     region_changed_signal.emit(region);
546     Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
547     if (vRegions.size() == 1) {
548     // show error message directly
549     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
550     msg.run();
551     } else {
552     // remember error, they are shown after all regions have been processed
553     errors.insert(txt);
554     }
555     }
556     }
557     // update all GUI elements
558     refreshManager();
559    
560     if (!errors.empty()) {
561     Glib::ustring txt = _(
562     "The following errors occurred while trying to change the dimension type on all regions:"
563     );
564     txt += "\n\n";
565     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
566     it != errors.end(); ++it)
567     {
568     txt += "-> " + *it + "\n";
569     }
570     txt += "\n";
571     txt += _(
572     "You might also want to check the console for further warnings and "
573     "error messages."
574     );
575     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
576     msg.run();
577     }
578     }
579 schoenebeck 3105 } else if (focus_column == treeView.get_column(1) || focus_column == treeView.get_column(2)) {
580     Glib::ustring txt = _("Right-click on a specific dimension zone of the dimension region selector to delete or split that particular dimension zone!");
581     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_INFO);
582     msg.run();
583 schoenebeck 2641 }
584     }
585    
586 schoenebeck 1225 void DimensionManager::addDimension() {
587 schoenebeck 2562 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
588     // add dimension type combo box to the dialog
589     Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
590     for (int i = 0x01; i < 0xff; i++) {
591     Glib::ustring sType =
592     dimTypeAsString(static_cast<gig::dimension_t>(i));
593     if (sType.find("Unknown") != 0) {
594     Gtk::TreeModel::Row row = *(refComboModel->append());
595     row[comboModel.m_type_id] = i;
596     row[comboModel.m_type_name] = sType;
597 schoenebeck 1225 }
598 schoenebeck 2562 }
599 schoenebeck 3364 #if USE_GTKMM_GRID
600     Gtk::Grid table;
601     #else
602 schoenebeck 2562 Gtk::Table table(2, 2);
603 schoenebeck 3364 #endif
604 schoenebeck 2562 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
605     Gtk::ComboBox comboDimType;
606     comboDimType.set_model(refComboModel);
607     comboDimType.pack_start(comboModel.m_type_id);
608     comboDimType.pack_start(comboModel.m_type_name);
609     Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
610 schoenebeck 3364 #if USE_GTKMM_GRID
611     table.attach(labelDimType, 0, 0);
612     table.attach(comboDimType, 1, 0);
613     table.attach(labelZones, 0, 1);
614     #else
615 schoenebeck 2562 table.attach(labelDimType, 0, 1, 0, 1);
616     table.attach(comboDimType, 1, 2, 0, 1);
617     table.attach(labelZones, 0, 1, 1, 2);
618 schoenebeck 3364 #endif
619    
620     #if USE_GTKMM_BOX
621     dialog.get_content_area()->pack_start(table);
622     #else
623 schoenebeck 2562 dialog.get_vbox()->pack_start(table);
624 schoenebeck 3364 #endif
625 persson 1733
626 schoenebeck 2562 // number of zones: use a combo box with fix values for gig
627     // v2 and a spin button for v3
628     Gtk::ComboBoxText comboZones;
629     Gtk::SpinButton spinZones;
630     bool version2 = false;
631     if (region) {
632     gig::File* file = (gig::File*)region->GetParent()->GetParent();
633     version2 = file->pVersion && file->pVersion->major == 2;
634     }
635     if (version2) {
636     for (int i = 1; i <= 5; i++) {
637     char buf[3];
638     sprintf(buf, "%d", 1 << i);
639 persson 2507 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
640 schoenebeck 2562 comboZones.append_text(buf);
641 persson 2169 #else
642 schoenebeck 2562 comboZones.append(buf);
643 persson 2169 #endif
644 schoenebeck 2562 }
645     table.attach(comboZones, 1, 2, 1, 2);
646     } else {
647     spinZones.set_increments(1, 8);
648     spinZones.set_numeric(true);
649     spinZones.set_range(2, 128);
650     spinZones.set_value(2);
651     table.attach(spinZones, 1, 2, 1, 2);
652     }
653    
654 schoenebeck 3364 #if HAS_GTKMM_STOCK
655 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
656     dialog.add_button(Gtk::Stock::CANCEL, 1);
657 schoenebeck 3364 #else
658     dialog.add_button(_("_OK"), 0);
659     dialog.add_button(_("_Cancel"), 1);
660     #endif
661     #if HAS_GTKMM_SHOW_ALL_CHILDREN
662 schoenebeck 2562 dialog.show_all_children();
663 schoenebeck 3364 #endif
664 schoenebeck 2562
665     if (!dialog.run()) { // OK selected ...
666     Gtk::TreeModel::iterator iterType = comboDimType.get_active();
667     if (!iterType) return;
668     Gtk::TreeModel::Row rowType = *iterType;
669     if (!rowType) return;
670     int iTypeID = rowType[comboModel.m_type_id];
671     gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
672     gig::dimension_def_t dim;
673     dim.dimension = type;
674    
675     if (version2) {
676     if (comboZones.get_active_row_number() < 0) return;
677     dim.bits = comboZones.get_active_row_number() + 1;
678     dim.zones = 1 << dim.bits;
679 persson 1733 } else {
680 schoenebeck 2562 dim.zones = spinZones.get_value_as_int();
681     dim.bits = zoneCountToBits(dim.zones);
682 persson 1733 }
683    
684 schoenebeck 2562 // assemble the list of regions where the selected dimension shall be
685     // added to
686     std::vector<gig::Region*> vRegions;
687     if (allRegions()) {
688     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
689     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
690     if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
691     }
692     } else vRegions.push_back(region);
693    
694     std::set<Glib::ustring> errors;
695 persson 1733
696 schoenebeck 2562 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
697     gig::Region* region = vRegions[iRgn];
698     try {
699     printf(
700     "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
701     dim.dimension, dim.bits, dim.zones
702     );
703     // notify everybody that we're going to update the region
704     region_to_be_changed_signal.emit(region);
705     // add the new dimension to the region
706     // (implicitly creates new dimension regions)
707     region->AddDimension(&dim);
708     // let everybody know there was a change
709     region_changed_signal.emit(region);
710     } catch (RIFF::Exception e) {
711     // notify that the changes are over (i.e. to avoid dead locks)
712     region_changed_signal.emit(region);
713     Glib::ustring txt = _("Could not add dimension: ") + e.Message;
714     if (vRegions.size() == 1) {
715     // show error message directly
716     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
717     msg.run();
718     } else {
719     // remember error, they are shown after all regions have been processed
720     errors.insert(txt);
721     }
722     }
723     }
724     // update all GUI elements
725     refreshManager();
726 persson 1733
727 schoenebeck 2562 if (!errors.empty()) {
728     Glib::ustring txt = _(
729     "The following errors occurred while trying to create the dimension on all regions:"
730     );
731     txt += "\n\n";
732     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
733     it != errors.end(); ++it)
734     {
735     txt += "-> " + *it + "\n";
736 persson 1733 }
737 schoenebeck 2562 txt += "\n";
738     txt += _(
739     "You might also want to check the console for further warnings and "
740     "error messages."
741 schoenebeck 1225 );
742 schoenebeck 2562 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
743     msg.run();
744 schoenebeck 1225 }
745     }
746     }
747    
748 schoenebeck 2562 void DimensionManager::removeDimension() {
749 schoenebeck 1225 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
750     Gtk::TreeModel::iterator it = sel->get_selected();
751     if (it) {
752 schoenebeck 2562 Gtk::TreeModel::Row row = *it;
753     gig::dimension_t type = row[tableModel.m_type];
754    
755     // assemble the list of regions where the selected dimension shall be
756     // added to
757     std::vector<gig::Region*> vRegions;
758     if (allRegions()) {
759     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
760     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
761     if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
762     }
763     } else vRegions.push_back(region);
764    
765     std::set<Glib::ustring> errors;
766    
767     for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
768     gig::Region* region = vRegions[iRgn];
769     gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
770     try {
771     // notify everybody that we're going to update the region
772     region_to_be_changed_signal.emit(region);
773     // remove selected dimension
774     region->DeleteDimension(dim);
775     // let everybody know there was a change
776     region_changed_signal.emit(region);
777     } catch (RIFF::Exception e) {
778     // notify that the changes are over (i.e. to avoid dead locks)
779     region_changed_signal.emit(region);
780     Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
781     if (vRegions.size() == 1) {
782     // show error message directly
783     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
784     msg.run();
785     } else {
786     // remember error, they are shown after all regions have been processed
787     errors.insert(txt);
788     }
789     }
790     }
791     // update all GUI elements
792     refreshManager();
793    
794     if (!errors.empty()) {
795     Glib::ustring txt = _(
796     "The following errors occurred while trying to remove the dimension from all regions:"
797     );
798     txt += "\n\n";
799     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
800     it != errors.end(); ++it)
801     {
802     txt += "-> " + *it + "\n";
803     }
804     txt += "\n";
805     txt += _(
806     "You might also want to check the console for further warnings and "
807     "error messages."
808     );
809 schoenebeck 1225 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
810     msg.run();
811     }
812     }
813     }

  ViewVC Help
Powered by ViewVC