/[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 3473 - (hide annotations) (download)
Sat Feb 16 20:35:46 2019 UTC (5 years, 1 month ago) by persson
File size: 31636 byte(s)
- remove G_DISABLE_DEPRECATED hack as glib threads are deprecated now anyway

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

  ViewVC Help
Powered by ViewVC