/[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 2641 - (hide annotations) (download)
Mon Jun 16 15:24:54 2014 UTC (9 years, 10 months ago) by schoenebeck
File size: 28642 byte(s)
* Region Chooser: Double click opens dimension manager dialog.
* Dimension Manager: Clicking on dimension type cell of an existing
  dimension opens a popup to alter the dimension type.

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

  ViewVC Help
Powered by ViewVC