/[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 3408 - (hide annotations) (download)
Fri Jan 19 19:17:41 2018 UTC (6 years, 3 months ago) by schoenebeck
File size: 31537 byte(s)
* Spelling fixes (patch provided by Debian maintainer Jaromír
  Mikeš).

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 3364 #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22)
282     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 1225 }
329    
330 schoenebeck 2562 bool DimensionManager::allRegions() const {
331     return allRegionsCheckBox.get_active();
332     }
333    
334     void DimensionManager::onAllRegionsCheckBoxToggled() {
335     set_title(
336     allRegions() ? _("Dimensions of all Regions") : _("Dimensions of selected Region")
337     );
338     treeView.set_tooltip_text(
339     allRegions()
340     ? _("Dimensions and numbers in gray indicates a difference among the individual regions.")
341     : _("You are currently only viewing dimensions of the currently selected region.")
342     );
343     refreshManager();
344     }
345    
346     // following two data types are just used in DimensionManager::refresManager(),
347     // due to the maps template nature however, they must be declared at global
348     // space to avoid compilation errors
349     struct _DimDef {
350     std::set<int> bits;
351     std::set<int> zones;
352     int usageCount;
353     };
354     typedef std::map<gig::dimension_t, _DimDef> _Dimensions;
355    
356 schoenebeck 3408 // update all GUI elements according to current gig::Region information
357 schoenebeck 1225 void DimensionManager::refreshManager() {
358 schoenebeck 2562 set_sensitive(false);
359 schoenebeck 1225 refTableModel->clear();
360 schoenebeck 2562 if (allRegions()) {
361     if (region) {
362     _Dimensions dims;
363     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
364     int iRegionsCount = 0;
365     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
366     for (uint i = 0; i < rgn->Dimensions; i++) {
367     gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
368     dims[dim->dimension].bits.insert(dim->bits);
369     dims[dim->dimension].zones.insert(dim->zones);
370     dims[dim->dimension].usageCount++;
371     }
372     }
373     for (_Dimensions::const_iterator it = dims.begin(); it != dims.end(); ++it) {
374     Gtk::TreeModel::Row row = *(refTableModel->append());
375     row[tableModel.m_type] = it->first;
376     row[tableModel.m_bits] = it->second.bits;
377     row[tableModel.m_zones] = it->second.zones;
378     row[tableModel.m_description] = __dimDescriptionAsString(it->first);
379     row[tableModel.m_usageCount] = it->second.usageCount;
380     row[tableModel.m_totalRegions] = iRegionsCount;
381     }
382 persson 1677 }
383 schoenebeck 2562 } else {
384     if (region) {
385     for (uint i = 0; i < region->Dimensions; i++) {
386     gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
387     Gtk::TreeModel::Row row = *(refTableModel->append());
388     std::set<int> vBits;
389     vBits.insert(dim->bits);
390     row[tableModel.m_bits] = vBits;
391     std::set<int> vZones;
392     vZones.insert(dim->zones);
393     row[tableModel.m_zones] = vZones;
394     row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
395     row[tableModel.m_type] = dim->dimension;
396     row[tableModel.m_usageCount] = 1;
397     row[tableModel.m_totalRegions] = 1;
398     }
399     }
400 schoenebeck 1225 }
401 persson 1677 set_sensitive(region);
402 schoenebeck 1225 }
403    
404     void DimensionManager::show(gig::Region* region) {
405 schoenebeck 2641 ignoreColumnClicked = true;
406 schoenebeck 1225 this->region = region;
407     refreshManager();
408     Gtk::Window::show();
409     deiconify();
410 schoenebeck 2641 ignoreColumnClicked = false;
411 schoenebeck 1225 }
412    
413 persson 1677 void DimensionManager::set_region(gig::Region* region) {
414 schoenebeck 2641 ignoreColumnClicked = true;
415 persson 1677 this->region = region;
416     refreshManager();
417 schoenebeck 2641 ignoreColumnClicked = false;
418 persson 1677 }
419    
420 schoenebeck 2641 void DimensionManager::onColumnClicked() {
421 schoenebeck 2919 printf("DimensionManager::onColumnClicked()\n");
422    
423     //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 !
424    
425 schoenebeck 2641 //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
426     if (ignoreColumnClicked) {
427     ignoreColumnClicked = false;
428     return;
429     }
430 schoenebeck 2921 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
431 schoenebeck 2919 // prevents app to crash if this dialog is closed
432     if (!get_visible())
433     return;
434 schoenebeck 2921 #else
435     # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
436     #endif
437 schoenebeck 2641
438 schoenebeck 2976 #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
439     if (!is_visible()) return;
440     #endif
441    
442 schoenebeck 2641 Gtk::TreeModel::Path path;
443     Gtk::TreeViewColumn* focus_column;
444     treeView.get_cursor(path, focus_column);
445     //const int row = path[0];
446     if (focus_column == treeView.get_column(0)) {
447     Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
448 schoenebeck 2976 if (!it) return;
449 schoenebeck 2641 Gtk::TreeModel::Row row = *it;
450     gig::dimension_t oldType = row[tableModel.m_type];
451    
452     Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
453     int oldTypeIndex = -1;
454     Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
455     for (int i = 0x01, count = 0; i < 0xff; i++) {
456     Glib::ustring sType =
457     dimTypeAsString(static_cast<gig::dimension_t>(i));
458     if (i == oldType) oldTypeIndex = count;
459     if (sType.find("Unknown") != 0) {
460     Gtk::TreeModel::Row row = *(refComboModel->append());
461     row[comboModel.m_type_id] = i;
462     row[comboModel.m_type_name] = sType;
463     count++;
464     }
465     }
466 schoenebeck 3364 #if USE_GTKMM_GRID
467     Gtk::Grid table;
468     #else
469 schoenebeck 2641 Gtk::Table table(1, 2);
470 schoenebeck 3364 #endif
471 schoenebeck 2641 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
472     Gtk::ComboBox comboDimType;
473     comboDimType.set_model(refComboModel);
474     comboDimType.pack_start(comboModel.m_type_id);
475     comboDimType.pack_start(comboModel.m_type_name);
476     table.attach(labelDimType, 0, 1, 0, 1);
477     table.attach(comboDimType, 1, 2, 0, 1);
478 schoenebeck 3364 #if USE_GTKMM_BOX
479     dialog.get_content_area()->pack_start(table);
480     #else
481 schoenebeck 2641 dialog.get_vbox()->pack_start(table);
482 schoenebeck 3364 #endif
483 schoenebeck 2641
484 schoenebeck 3364 #if HAS_GTKMM_STOCK
485 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
486     dialog.add_button(Gtk::Stock::CANCEL, 1);
487 schoenebeck 3364 #else
488     dialog.add_button(_("_OK"), 0);
489     dialog.add_button(_("_Cancel"), 1);
490     #endif
491     #if HAS_GTKMM_SHOW_ALL_CHILDREN
492 schoenebeck 2641 dialog.show_all_children();
493 schoenebeck 3364 #endif
494 schoenebeck 2641
495     comboDimType.set_active(oldTypeIndex);
496    
497     if (!dialog.run()) { // OK selected ...
498 schoenebeck 2919 ignoreColumnClicked = true;
499 schoenebeck 2641 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
500     if (!iterType) return;
501     Gtk::TreeModel::Row rowType = *iterType;
502     if (!rowType) return;
503     int iTypeID = rowType[comboModel.m_type_id];
504     gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
505     if (newType == oldType) return;
506     //printf("change 0x%x -> 0x%x\n", oldType, newType);
507    
508     // assemble the list of regions where the selected dimension type
509     // shall be changed
510     std::vector<gig::Region*> vRegions;
511     if (allRegions()) {
512     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
513     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
514     if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
515     }
516     } else vRegions.push_back(region);
517    
518     std::set<Glib::ustring> errors;
519    
520     for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
521     gig::Region* region = vRegions[iRgn];
522     try {
523     // notify everybody that we're going to update the region
524     region_to_be_changed_signal.emit(region);
525     // change the dimension type on that region
526     region->SetDimensionType(oldType, newType);
527     // let everybody know there was a change
528     region_changed_signal.emit(region);
529     } catch (RIFF::Exception e) {
530     // notify that the changes are over (i.e. to avoid dead locks)
531     region_changed_signal.emit(region);
532     Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
533     if (vRegions.size() == 1) {
534     // show error message directly
535     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
536     msg.run();
537     } else {
538     // remember error, they are shown after all regions have been processed
539     errors.insert(txt);
540     }
541     }
542     }
543     // update all GUI elements
544     refreshManager();
545    
546     if (!errors.empty()) {
547     Glib::ustring txt = _(
548     "The following errors occurred while trying to change the dimension type on all regions:"
549     );
550     txt += "\n\n";
551     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
552     it != errors.end(); ++it)
553     {
554     txt += "-> " + *it + "\n";
555     }
556     txt += "\n";
557     txt += _(
558     "You might also want to check the console for further warnings and "
559     "error messages."
560     );
561     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
562     msg.run();
563     }
564     }
565 schoenebeck 3105 } else if (focus_column == treeView.get_column(1) || focus_column == treeView.get_column(2)) {
566     Glib::ustring txt = _("Right-click on a specific dimension zone of the dimension region selector to delete or split that particular dimension zone!");
567     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_INFO);
568     msg.run();
569 schoenebeck 2641 }
570     }
571    
572 schoenebeck 1225 void DimensionManager::addDimension() {
573 schoenebeck 2562 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
574     // add dimension type combo box to the dialog
575     Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
576     for (int i = 0x01; i < 0xff; i++) {
577     Glib::ustring sType =
578     dimTypeAsString(static_cast<gig::dimension_t>(i));
579     if (sType.find("Unknown") != 0) {
580     Gtk::TreeModel::Row row = *(refComboModel->append());
581     row[comboModel.m_type_id] = i;
582     row[comboModel.m_type_name] = sType;
583 schoenebeck 1225 }
584 schoenebeck 2562 }
585 schoenebeck 3364 #if USE_GTKMM_GRID
586     Gtk::Grid table;
587     #else
588 schoenebeck 2562 Gtk::Table table(2, 2);
589 schoenebeck 3364 #endif
590 schoenebeck 2562 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
591     Gtk::ComboBox comboDimType;
592     comboDimType.set_model(refComboModel);
593     comboDimType.pack_start(comboModel.m_type_id);
594     comboDimType.pack_start(comboModel.m_type_name);
595     Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
596 schoenebeck 3364 #if USE_GTKMM_GRID
597     table.attach(labelDimType, 0, 0);
598     table.attach(comboDimType, 1, 0);
599     table.attach(labelZones, 0, 1);
600     #else
601 schoenebeck 2562 table.attach(labelDimType, 0, 1, 0, 1);
602     table.attach(comboDimType, 1, 2, 0, 1);
603     table.attach(labelZones, 0, 1, 1, 2);
604 schoenebeck 3364 #endif
605    
606     #if USE_GTKMM_BOX
607     dialog.get_content_area()->pack_start(table);
608     #else
609 schoenebeck 2562 dialog.get_vbox()->pack_start(table);
610 schoenebeck 3364 #endif
611 persson 1733
612 schoenebeck 2562 // number of zones: use a combo box with fix values for gig
613     // v2 and a spin button for v3
614     Gtk::ComboBoxText comboZones;
615     Gtk::SpinButton spinZones;
616     bool version2 = false;
617     if (region) {
618     gig::File* file = (gig::File*)region->GetParent()->GetParent();
619     version2 = file->pVersion && file->pVersion->major == 2;
620     }
621     if (version2) {
622     for (int i = 1; i <= 5; i++) {
623     char buf[3];
624     sprintf(buf, "%d", 1 << i);
625 persson 2507 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
626 schoenebeck 2562 comboZones.append_text(buf);
627 persson 2169 #else
628 schoenebeck 2562 comboZones.append(buf);
629 persson 2169 #endif
630 schoenebeck 2562 }
631     table.attach(comboZones, 1, 2, 1, 2);
632     } else {
633     spinZones.set_increments(1, 8);
634     spinZones.set_numeric(true);
635     spinZones.set_range(2, 128);
636     spinZones.set_value(2);
637     table.attach(spinZones, 1, 2, 1, 2);
638     }
639    
640 schoenebeck 3364 #if HAS_GTKMM_STOCK
641 schoenebeck 3158 dialog.add_button(Gtk::Stock::OK, 0);
642     dialog.add_button(Gtk::Stock::CANCEL, 1);
643 schoenebeck 3364 #else
644     dialog.add_button(_("_OK"), 0);
645     dialog.add_button(_("_Cancel"), 1);
646     #endif
647     #if HAS_GTKMM_SHOW_ALL_CHILDREN
648 schoenebeck 2562 dialog.show_all_children();
649 schoenebeck 3364 #endif
650 schoenebeck 2562
651     if (!dialog.run()) { // OK selected ...
652     Gtk::TreeModel::iterator iterType = comboDimType.get_active();
653     if (!iterType) return;
654     Gtk::TreeModel::Row rowType = *iterType;
655     if (!rowType) return;
656     int iTypeID = rowType[comboModel.m_type_id];
657     gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
658     gig::dimension_def_t dim;
659     dim.dimension = type;
660    
661     if (version2) {
662     if (comboZones.get_active_row_number() < 0) return;
663     dim.bits = comboZones.get_active_row_number() + 1;
664     dim.zones = 1 << dim.bits;
665 persson 1733 } else {
666 schoenebeck 2562 dim.zones = spinZones.get_value_as_int();
667     dim.bits = zoneCountToBits(dim.zones);
668 persson 1733 }
669    
670 schoenebeck 2562 // assemble the list of regions where the selected dimension shall be
671     // added to
672     std::vector<gig::Region*> vRegions;
673     if (allRegions()) {
674     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
675     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
676     if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
677     }
678     } else vRegions.push_back(region);
679    
680     std::set<Glib::ustring> errors;
681 persson 1733
682 schoenebeck 2562 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
683     gig::Region* region = vRegions[iRgn];
684     try {
685     printf(
686     "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
687     dim.dimension, dim.bits, dim.zones
688     );
689     // notify everybody that we're going to update the region
690     region_to_be_changed_signal.emit(region);
691     // add the new dimension to the region
692     // (implicitly creates new dimension regions)
693     region->AddDimension(&dim);
694     // let everybody know there was a change
695     region_changed_signal.emit(region);
696     } catch (RIFF::Exception e) {
697     // notify that the changes are over (i.e. to avoid dead locks)
698     region_changed_signal.emit(region);
699     Glib::ustring txt = _("Could not add dimension: ") + e.Message;
700     if (vRegions.size() == 1) {
701     // show error message directly
702     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
703     msg.run();
704     } else {
705     // remember error, they are shown after all regions have been processed
706     errors.insert(txt);
707     }
708     }
709     }
710     // update all GUI elements
711     refreshManager();
712 persson 1733
713 schoenebeck 2562 if (!errors.empty()) {
714     Glib::ustring txt = _(
715     "The following errors occurred while trying to create the dimension on all regions:"
716     );
717     txt += "\n\n";
718     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
719     it != errors.end(); ++it)
720     {
721     txt += "-> " + *it + "\n";
722 persson 1733 }
723 schoenebeck 2562 txt += "\n";
724     txt += _(
725     "You might also want to check the console for further warnings and "
726     "error messages."
727 schoenebeck 1225 );
728 schoenebeck 2562 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
729     msg.run();
730 schoenebeck 1225 }
731     }
732     }
733    
734 schoenebeck 2562 void DimensionManager::removeDimension() {
735 schoenebeck 1225 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
736     Gtk::TreeModel::iterator it = sel->get_selected();
737     if (it) {
738 schoenebeck 2562 Gtk::TreeModel::Row row = *it;
739     gig::dimension_t type = row[tableModel.m_type];
740    
741     // assemble the list of regions where the selected dimension shall be
742     // added to
743     std::vector<gig::Region*> vRegions;
744     if (allRegions()) {
745     gig::Instrument* instr = (gig::Instrument*)region->GetParent();
746     for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
747     if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
748     }
749     } else vRegions.push_back(region);
750    
751     std::set<Glib::ustring> errors;
752    
753     for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
754     gig::Region* region = vRegions[iRgn];
755     gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
756     try {
757     // notify everybody that we're going to update the region
758     region_to_be_changed_signal.emit(region);
759     // remove selected dimension
760     region->DeleteDimension(dim);
761     // let everybody know there was a change
762     region_changed_signal.emit(region);
763     } catch (RIFF::Exception e) {
764     // notify that the changes are over (i.e. to avoid dead locks)
765     region_changed_signal.emit(region);
766     Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
767     if (vRegions.size() == 1) {
768     // show error message directly
769     Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
770     msg.run();
771     } else {
772     // remember error, they are shown after all regions have been processed
773     errors.insert(txt);
774     }
775     }
776     }
777     // update all GUI elements
778     refreshManager();
779    
780     if (!errors.empty()) {
781     Glib::ustring txt = _(
782     "The following errors occurred while trying to remove the dimension from all regions:"
783     );
784     txt += "\n\n";
785     for (std::set<Glib::ustring>::const_iterator it = errors.begin();
786     it != errors.end(); ++it)
787     {
788     txt += "-> " + *it + "\n";
789     }
790     txt += "\n";
791     txt += _(
792     "You might also want to check the console for further warnings and "
793     "error messages."
794     );
795 schoenebeck 1225 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
796     msg.run();
797     }
798     }
799     }

  ViewVC Help
Powered by ViewVC