/[svn]/gigedit/trunk/src/gigedit/dimensionmanager.cpp
ViewVC logotype

Diff of /gigedit/trunk/src/gigedit/dimensionmanager.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1733  
changed lines
  Added in v.2919

  ViewVC Help
Powered by ViewVC