/[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 1411 by schoenebeck, Fri Oct 12 17:46:29 2007 UTC revision 2845 by persson, Sun Sep 20 10:18:22 2015 UTC
# Line 1  Line 1 
1  /*                                                         -*- c++ -*-  /*
2   * Copyright (C) 2006, 2007 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>
34    #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 106  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 190  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 211  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      for (int i = 0; i < region->Dimensions; i++) {      if (allRegions()) {
335          gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];          if (region) {
336          Gtk::TreeModel::Row row = *(refTableModel->append());              _Dimensions dims;
337          row[tableModel.m_dim_type] = __dimTypeAsString(dim->dimension);              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
338          row[tableModel.m_bits] = dim->bits;              int iRegionsCount = 0;
339          row[tableModel.m_zones] = 1 << dim->bits; //TODO: for now we calculate it here until libgig always ensures 'zones' to be correct              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
340          row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);                  for (uint i = 0; i < rgn->Dimensions; i++) {
341          row[tableModel.m_definition] = dim;                      gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
342                        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);
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::addDimension() {  void DimensionManager::set_region(gig::Region* region) {
388      try {      ignoreColumnClicked = true;
389          Gtk::Dialog dialog("New Dimension", true /*modal*/);      this->region = region;
390          // add dimension type combo box to the dialog      refreshManager();
391        ignoreColumnClicked = false;
392    }
393    
394    void DimensionManager::onColumnClicked() {
395        //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
396        if (ignoreColumnClicked) {
397            ignoreColumnClicked = false;
398            return;
399        }
400    
401        Gtk::TreeModel::Path path;
402        Gtk::TreeViewColumn* focus_column;
403        treeView.get_cursor(path, focus_column);
404        //const int row = path[0];
405        if (focus_column == treeView.get_column(0)) {
406            Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
407            Gtk::TreeModel::Row row = *it;
408            gig::dimension_t oldType = row[tableModel.m_type];
409    
410            Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
411            int oldTypeIndex = -1;
412          Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);          Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
413          for (int i = 0x01; i < 0xff; i++) {          for (int i = 0x01, count = 0; i < 0xff; i++) {
414              Glib::ustring sType =              Glib::ustring sType =
415                  __dimTypeAsString(static_cast<gig::dimension_t>(i));                  dimTypeAsString(static_cast<gig::dimension_t>(i));
416                if (i == oldType) oldTypeIndex = count;
417              if (sType.find("Unknown") != 0) {              if (sType.find("Unknown") != 0) {
418                  Gtk::TreeModel::Row row = *(refComboModel->append());                  Gtk::TreeModel::Row row = *(refComboModel->append());
419                  row[comboModel.m_type_id]   = i;                  row[comboModel.m_type_id]   = i;
420                  row[comboModel.m_type_name] = sType;                  row[comboModel.m_type_name] = sType;
421                    count++;
422              }              }
423          }          }
424            Gtk::Table table(1, 2);
425            Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
426          Gtk::ComboBox comboDimType;          Gtk::ComboBox comboDimType;
427          comboDimType.set_model(refComboModel);          comboDimType.set_model(refComboModel);
428          comboDimType.pack_start(comboModel.m_type_id);          comboDimType.pack_start(comboModel.m_type_id);
429          comboDimType.pack_start(comboModel.m_type_name);          comboDimType.pack_start(comboModel.m_type_name);
430          dialog.get_vbox()->pack_start(comboDimType);          table.attach(labelDimType, 0, 1, 0, 1);
431          comboDimType.show();          table.attach(comboDimType, 1, 2, 0, 1);
432          // add zones combo box to the dialog          dialog.get_vbox()->pack_start(table);
433          Gtk::ComboBoxText comboZones;  
434          for (int i = 1; i <= 7; i++) { //FIXME: is 7 the correct amount of max. bits ???          dialog.add_button(_("_OK"), 0);
435              char buf[64];          dialog.add_button(_("_Cancel"), 1);
             sprintf(buf, "%d Zones (%d Bits)", 1 << i, i);  
             comboZones.append_text(buf);  
         }  
         dialog.get_vbox()->pack_start(comboZones);  
         comboZones.show();  
         // add OK and CANCEL buttons to the dialog  
         dialog.add_button(Gtk::Stock::OK, 0);  
         dialog.add_button(Gtk::Stock::CANCEL, 1);  
436          dialog.show_all_children();          dialog.show_all_children();
437            
438            comboDimType.set_active(oldTypeIndex);
439    
440          if (!dialog.run()) { // OK selected ...          if (!dialog.run()) { // OK selected ...
441              Gtk::TreeModel::iterator iterType = comboDimType.get_active();              Gtk::TreeModel::iterator iterType = comboDimType.get_active();
442              if (!iterType) return;              if (!iterType) return;
443              Gtk::TreeModel::Row rowType = *iterType;              Gtk::TreeModel::Row rowType = *iterType;
444              if (!rowType) return;              if (!rowType) return;
             gig::dimension_def_t dim;  
445              int iTypeID = rowType[comboModel.m_type_id];              int iTypeID = rowType[comboModel.m_type_id];
446              dim.dimension = static_cast<gig::dimension_t>(iTypeID);              gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
447                if (newType == oldType) return;
448                //printf("change 0x%x -> 0x%x\n", oldType, newType);
449                ignoreColumnClicked = true;
450    
451                // assemble the list of regions where the selected dimension type
452                // shall be changed
453                std::vector<gig::Region*> vRegions;
454                if (allRegions()) {
455                    gig::Instrument* instr = (gig::Instrument*)region->GetParent();
456                    for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
457                        if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
458                    }
459                } else vRegions.push_back(region);
460    
461                std::set<Glib::ustring> errors;
462    
463                for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
464                    gig::Region* region = vRegions[iRgn];
465                    try {
466                        // notify everybody that we're going to update the region
467                        region_to_be_changed_signal.emit(region);
468                        // change the dimension type on that region
469                        region->SetDimensionType(oldType, newType);
470                        // let everybody know there was a change
471                        region_changed_signal.emit(region);
472                    } catch (RIFF::Exception e) {
473                        // notify that the changes are over (i.e. to avoid dead locks)
474                        region_changed_signal.emit(region);
475                        Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
476                        if (vRegions.size() == 1) {
477                            // show error message directly
478                            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
479                            msg.run();
480                        } else {
481                            // remember error, they are shown after all regions have been processed
482                            errors.insert(txt);
483                        }
484                    }
485                }
486                // update all GUI elements
487                refreshManager();
488    
489                if (!errors.empty()) {
490                    Glib::ustring txt = _(
491                        "The following errors occurred while trying to change the dimension type on all regions:"
492                    );
493                    txt += "\n\n";
494                    for (std::set<Glib::ustring>::const_iterator it = errors.begin();
495                        it != errors.end(); ++it)
496                    {
497                        txt += "-> " + *it + "\n";
498                    }
499                    txt += "\n";
500                    txt += _(
501                        "You might also want to check the console for further warnings and "
502                        "error messages."
503                    );
504                    Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
505                    msg.run();
506                }
507            }
508        }
509    }
510    
511    void DimensionManager::addDimension() {
512        Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
513        // add dimension type combo box to the dialog
514        Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
515        for (int i = 0x01; i < 0xff; i++) {
516            Glib::ustring sType =
517                dimTypeAsString(static_cast<gig::dimension_t>(i));
518            if (sType.find("Unknown") != 0) {
519                Gtk::TreeModel::Row row = *(refComboModel->append());
520                row[comboModel.m_type_id]   = i;
521                row[comboModel.m_type_name] = sType;
522            }
523        }
524        Gtk::Table table(2, 2);
525        Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
526        Gtk::ComboBox comboDimType;
527        comboDimType.set_model(refComboModel);
528        comboDimType.pack_start(comboModel.m_type_id);
529        comboDimType.pack_start(comboModel.m_type_name);
530        Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
531        table.attach(labelDimType, 0, 1, 0, 1);
532        table.attach(comboDimType, 1, 2, 0, 1);
533        table.attach(labelZones, 0, 1, 1, 2);
534        dialog.get_vbox()->pack_start(table);
535    
536        // number of zones: use a combo box with fix values for gig
537        // v2 and a spin button for v3
538        Gtk::ComboBoxText comboZones;
539        Gtk::SpinButton spinZones;
540        bool version2 = false;
541        if (region) {
542            gig::File* file = (gig::File*)region->GetParent()->GetParent();
543            version2 = file->pVersion && file->pVersion->major == 2;
544        }
545        if (version2) {
546            for (int i = 1; i <= 5; i++) {
547                char buf[3];
548                sprintf(buf, "%d", 1 << i);
549    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
550                comboZones.append_text(buf);
551    #else
552                comboZones.append(buf);
553    #endif
554            }
555            table.attach(comboZones, 1, 2, 1, 2);
556        } else {
557            spinZones.set_increments(1, 8);
558            spinZones.set_numeric(true);
559            spinZones.set_range(2, 128);
560            spinZones.set_value(2);
561            table.attach(spinZones, 1, 2, 1, 2);
562        }
563    
564        dialog.add_button(_("_OK"), 0);
565        dialog.add_button(_("_Cancel"), 1);
566        dialog.show_all_children();
567    
568        if (!dialog.run()) { // OK selected ...
569            Gtk::TreeModel::iterator iterType = comboDimType.get_active();
570            if (!iterType) return;
571            Gtk::TreeModel::Row rowType = *iterType;
572            if (!rowType) return;
573            int iTypeID = rowType[comboModel.m_type_id];
574            gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
575            gig::dimension_def_t dim;
576            dim.dimension = type;
577    
578            if (version2) {
579              if (comboZones.get_active_row_number() < 0) return;              if (comboZones.get_active_row_number() < 0) return;
580              dim.bits = comboZones.get_active_row_number() + 1;              dim.bits = comboZones.get_active_row_number() + 1;
581              dim.zones = 1 << dim.bits; //TODO: support zones != pow(2,bits) - feature of gig v3              dim.zones = 1 << dim.bits;
582              printf(          } else {
583                  "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",              dim.zones = spinZones.get_value_as_int();
584                  dim.dimension, dim.bits, dim.zones              dim.bits = zoneCountToBits(dim.zones);
585            }
586    
587            // assemble the list of regions where the selected dimension shall be
588            // added to
589            std::vector<gig::Region*> vRegions;
590            if (allRegions()) {
591                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
592                for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
593                    if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
594                }
595            } else vRegions.push_back(region);
596                
597            std::set<Glib::ustring> errors;
598    
599            for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
600                gig::Region* region = vRegions[iRgn];
601                try {
602                    printf(
603                        "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
604                        dim.dimension, dim.bits, dim.zones
605                    );
606                    // notify everybody that we're going to update the region
607                    region_to_be_changed_signal.emit(region);
608                    // add the new dimension to the region
609                    // (implicitly creates new dimension regions)
610                    region->AddDimension(&dim);
611                    // let everybody know there was a change
612                    region_changed_signal.emit(region);
613                } catch (RIFF::Exception e) {
614                    // notify that the changes are over (i.e. to avoid dead locks)
615                    region_changed_signal.emit(region);
616                    Glib::ustring txt = _("Could not add dimension: ") + e.Message;
617                    if (vRegions.size() == 1) {
618                        // show error message directly
619                        Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
620                        msg.run();
621                    } else {
622                        // remember error, they are shown after all regions have been processed
623                        errors.insert(txt);
624                    }
625                }
626            }
627            // update all GUI elements
628            refreshManager();
629    
630            if (!errors.empty()) {
631                Glib::ustring txt = _(
632                    "The following errors occurred while trying to create the dimension on all regions:"
633              );              );
634              // notify everybody that we're going to update the region              txt += "\n\n";
635              region_to_be_changed_signal.emit(region);              for (std::set<Glib::ustring>::const_iterator it = errors.begin();
636              // add the new dimension to the region                   it != errors.end(); ++it)
637              // (implicitly creates new dimension regions)              {
638              region->AddDimension(&dim);                  txt += "-> " + *it + "\n";
639              // let everybody know there was a change              }
640              region_changed_signal.emit(region);              txt += "\n";
641              // update all GUI elements              txt += _(
642              refreshManager();                  "You might also want to check the console for further warnings and "
643                    "error messages."
644                );
645                Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
646                msg.run();
647          }          }
     } 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();  
648      }      }
649  }  }
650    
651  void DimensionManager::removeDimension() {  void DimensionManager::removeDimension() {        
652      Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
653      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
654      if (it) {      if (it) {
655          try {          Gtk::TreeModel::Row row = *it;
656              // notify everybody that we're going to update the region          gig::dimension_t type = row[tableModel.m_type];
657              region_to_be_changed_signal.emit(region);  
658              // remove selected dimension          // assemble the list of regions where the selected dimension shall be
659              Gtk::TreeModel::Row row = *it;          // added to
660              gig::dimension_def_t* dim = row[tableModel.m_definition];          std::vector<gig::Region*> vRegions;
661              region->DeleteDimension(dim);          if (allRegions()) {
662              // remove respective row from table              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
663              refTableModel->erase(it);              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
664              // let everybody know there was a change                  if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
665              region_changed_signal.emit(region);              }
666          } catch (RIFF::Exception e) {          } else vRegions.push_back(region);
667              // notify that the changes are over (i.e. to avoid dead locks)  
668              region_changed_signal.emit(region);          std::set<Glib::ustring> errors;
669              // show error message  
670              Glib::ustring txt = "Could not remove dimension: " + e.Message;          for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
671                gig::Region* region = vRegions[iRgn];
672                gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
673                try {
674                    // notify everybody that we're going to update the region
675                    region_to_be_changed_signal.emit(region);
676                    // remove selected dimension    
677                    region->DeleteDimension(dim);
678                    // let everybody know there was a change
679                    region_changed_signal.emit(region);
680                } catch (RIFF::Exception e) {
681                    // notify that the changes are over (i.e. to avoid dead locks)
682                    region_changed_signal.emit(region);
683                    Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
684                    if (vRegions.size() == 1) {
685                        // show error message directly
686                        Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
687                        msg.run();
688                    } else {
689                        // remember error, they are shown after all regions have been processed
690                        errors.insert(txt);
691                    }
692                }
693            }
694            // update all GUI elements
695            refreshManager();
696    
697            if (!errors.empty()) {
698                Glib::ustring txt = _(
699                    "The following errors occurred while trying to remove the dimension from all regions:"
700                );
701                txt += "\n\n";
702                for (std::set<Glib::ustring>::const_iterator it = errors.begin();
703                     it != errors.end(); ++it)
704                {
705                    txt += "-> " + *it + "\n";
706                }
707                txt += "\n";
708                txt += _(
709                    "You might also want to check the console for further warnings and "
710                    "error messages."
711                );
712              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
713              msg.run();              msg.run();
714          }          }

Legend:
Removed from v.1411  
changed lines
  Added in v.2845

  ViewVC Help
Powered by ViewVC