/[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 2561 by schoenebeck, Sat May 17 23:55:30 2014 UTC revision 2562 by schoenebeck, Mon May 19 18:06:57 2014 UTC
# Line 183  static Glib::ustring __dimDescriptionAsS Line 183  static Glib::ustring __dimDescriptionAsS
183      }      }
184  }  }
185    
186    DimTypeCellRenderer::DimTypeCellRenderer() :
187        Glib::ObjectBase(typeid(DimTypeCellRenderer)),
188        Gtk::CellRendererText(),
189        m_propertyDimType(*this, "gigdimension_t", gig::dimension_none),
190        m_propertyUsageCount(*this, "intusagecount", 0),
191        m_propertyTotalRegions(*this, "inttotalregions", 0)
192    {
193        propertyDimType().signal_changed().connect(
194            sigc::mem_fun(*this, &DimTypeCellRenderer::typeChanged)
195        );
196        propertyUsageCount().signal_changed().connect(
197            sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
198        );
199        propertyTotalRegions().signal_changed().connect(
200            sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
201        );
202    }
203    
204    void DimTypeCellRenderer::typeChanged() {
205        gig::dimension_t type = propertyDimType();
206        Glib::ustring s = dimTypeAsString(type);
207        property_text() = s;
208    }
209    
210    void DimTypeCellRenderer::statsChanged() {
211        int usageCount   = propertyUsageCount();
212        int totalRegions = propertyTotalRegions();
213        bool bDimensionExistsOnAllRegions = (usageCount == totalRegions);
214        property_foreground() = ((bDimensionExistsOnAllRegions) ? "black" : "gray");
215    }
216    
217    IntSetCellRenderer::IntSetCellRenderer() :
218        Glib::ObjectBase(typeid(IntSetCellRenderer)),
219        Gtk::CellRendererText(),
220        m_propertyValue(*this, "stdintset", std::set<int>())
221    {
222        propertyValue().signal_changed().connect(
223            sigc::mem_fun(*this, &IntSetCellRenderer::valueChanged)
224        );
225    }
226    
227    void IntSetCellRenderer::valueChanged() {
228        Glib::ustring s;
229        std::set<int> v = propertyValue();
230        for (std::set<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
231            s += ToString(*it);
232            if (*it != *v.rbegin()) s += "|";
233        }
234        property_text() = s;
235        property_foreground() = (v.size() > 1) ? "gray" : "black";
236    }
237    
238  DimensionManager::DimensionManager() :  DimensionManager::DimensionManager() :
239  addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE)  addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE),
240    allRegionsCheckBox(_("All Regions"))
241  {  {
242      set_title(_("Dimensions of selected Region"));      set_title(_("Dimensions of selected Region"));
243      add(vbox);      add(vbox);
# Line 195  addButton(Gtk::Stock::ADD), removeButton Line 248  addButton(Gtk::Stock::ADD), removeButton
248      buttonBox.set_layout(Gtk::BUTTONBOX_END);      buttonBox.set_layout(Gtk::BUTTONBOX_END);
249      buttonBox.set_border_width(5);      buttonBox.set_border_width(5);
250      buttonBox.show();      buttonBox.show();
251        buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
252      buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);      buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
253      buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);      buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
254      addButton.show();      addButton.show();
255      removeButton.show();      removeButton.show();
256        allRegionsCheckBox.set_tooltip_text(
257            _("Enable this if you want to edit dimensions of all regions simultaniously.")
258        );
259    
260      // setup the table      // setup the table
261      refTableModel = Gtk::ListStore::create(tableModel);      refTableModel = Gtk::ListStore::create(tableModel);
262      treeView.set_model(refTableModel);      treeView.set_model(refTableModel);
263      treeView.append_column(_("Dimension Type"), tableModel.m_dim_type);      treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
264      treeView.append_column(_("Bits"), tableModel.m_bits);      treeView.append_column(_("Bits"), m_cellRendererIntSet);
265      treeView.append_column(_("Zones"), tableModel.m_zones);      treeView.append_column(_("Zones"), m_cellRendererIntSet);
266      treeView.append_column(_("Description"), tableModel.m_description);      treeView.append_column(_("Description"), tableModel.m_description);
267        treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyDimType(), tableModel.m_type);
268        treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyUsageCount(), tableModel.m_usageCount);
269        treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyTotalRegions(), tableModel.m_totalRegions);
270        treeView.get_column(1)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_bits);
271        treeView.get_column(2)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_zones);
272      treeView.show();      treeView.show();
273    
274      addButton.signal_clicked().connect(      addButton.signal_clicked().connect(
# Line 216  addButton(Gtk::Stock::ADD), removeButton Line 278  addButton(Gtk::Stock::ADD), removeButton
278      removeButton.signal_clicked().connect(      removeButton.signal_clicked().connect(
279          sigc::mem_fun(*this, &DimensionManager::removeDimension)          sigc::mem_fun(*this, &DimensionManager::removeDimension)
280      );      );
281        allRegionsCheckBox.signal_toggled().connect(
282            sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
283        );
284    
285      show_all_children();      show_all_children();
286            
287      resize(460,300);      resize(460,300);
288  }  }
289    
290    bool DimensionManager::allRegions() const {
291        return allRegionsCheckBox.get_active();
292    }
293    
294    void DimensionManager::onAllRegionsCheckBoxToggled() {
295        set_title(
296            allRegions() ? _("Dimensions of all Regions") :  _("Dimensions of selected Region")
297        );
298        treeView.set_tooltip_text(
299            allRegions()
300                ? _("Dimensions and numbers in gray indicates a difference among the individual regions.")
301                : _("You are currently only viewing dimensions of the currently selected region.")
302        );
303        refreshManager();
304    }
305    
306    // following two data types are just used in DimensionManager::refresManager(),
307    // due to the maps template nature however, they must be declared at global
308    // space to avoid compilation errors
309    struct _DimDef {
310        std::set<int> bits;
311        std::set<int> zones;
312        int usageCount;
313    };
314    typedef std::map<gig::dimension_t, _DimDef> _Dimensions;
315    
316  // update all GUI elements according to current gig::Region informations  // update all GUI elements according to current gig::Region informations
317  void DimensionManager::refreshManager() {  void DimensionManager::refreshManager() {
318        set_sensitive(false);
319      refTableModel->clear();      refTableModel->clear();
320      if (region) {      if (allRegions()) {
321          for (int i = 0; i < region->Dimensions; i++) {          if (region) {
322              gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];              _Dimensions dims;
323              Gtk::TreeModel::Row row = *(refTableModel->append());              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
324              row[tableModel.m_dim_type] = dimTypeAsString(dim->dimension);              int iRegionsCount = 0;
325              row[tableModel.m_bits] = dim->bits;              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
326              row[tableModel.m_zones] = dim->zones;                  for (uint i = 0; i < rgn->Dimensions; i++) {
327              row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);                      gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
328              row[tableModel.m_definition] = dim;                      dims[dim->dimension].bits.insert(dim->bits);
329                        dims[dim->dimension].zones.insert(dim->zones);
330                        dims[dim->dimension].usageCount++;
331                    }
332                }
333                for (_Dimensions::const_iterator it = dims.begin(); it != dims.end(); ++it) {
334                    Gtk::TreeModel::Row row = *(refTableModel->append());
335                    row[tableModel.m_type] = it->first;
336                    row[tableModel.m_bits] = it->second.bits;
337                    row[tableModel.m_zones] = it->second.zones;
338                    row[tableModel.m_description] = __dimDescriptionAsString(it->first);
339                    row[tableModel.m_usageCount] = it->second.usageCount;
340                    row[tableModel.m_totalRegions] = iRegionsCount;
341                }
342            }
343        } else {
344            if (region) {
345                for (uint i = 0; i < region->Dimensions; i++) {
346                    gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
347                    Gtk::TreeModel::Row row = *(refTableModel->append());
348                    std::set<int> vBits;
349                    vBits.insert(dim->bits);
350                    row[tableModel.m_bits] = vBits;
351                    std::set<int> vZones;
352                    vZones.insert(dim->zones);
353                    row[tableModel.m_zones] = vZones;
354                    row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
355                    row[tableModel.m_type] = dim->dimension;
356                    row[tableModel.m_usageCount] = 1;
357                    row[tableModel.m_totalRegions] = 1;
358                }
359          }          }
360      }      }
361      set_sensitive(region);      set_sensitive(region);
# Line 252  void DimensionManager::set_region(gig::R Line 374  void DimensionManager::set_region(gig::R
374  }  }
375    
376  void DimensionManager::addDimension() {  void DimensionManager::addDimension() {
377      try {      Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
378          Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);      // add dimension type combo box to the dialog
379          // add dimension type combo box to the dialog      Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
380          Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);      for (int i = 0x01; i < 0xff; i++) {
381          for (int i = 0x01; i < 0xff; i++) {          Glib::ustring sType =
382              Glib::ustring sType =              dimTypeAsString(static_cast<gig::dimension_t>(i));
383                  dimTypeAsString(static_cast<gig::dimension_t>(i));          if (sType.find("Unknown") != 0) {
384              if (sType.find("Unknown") != 0) {              Gtk::TreeModel::Row row = *(refComboModel->append());
385                  Gtk::TreeModel::Row row = *(refComboModel->append());              row[comboModel.m_type_id]   = i;
386                  row[comboModel.m_type_id]   = i;              row[comboModel.m_type_name] = sType;
                 row[comboModel.m_type_name] = sType;  
             }  
         }  
         Gtk::Table table(2, 2);  
         Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);  
         Gtk::ComboBox comboDimType;  
         comboDimType.set_model(refComboModel);  
         comboDimType.pack_start(comboModel.m_type_id);  
         comboDimType.pack_start(comboModel.m_type_name);  
         Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);  
         table.attach(labelDimType, 0, 1, 0, 1);  
         table.attach(comboDimType, 1, 2, 0, 1);  
         table.attach(labelZones, 0, 1, 1, 2);  
         dialog.get_vbox()->pack_start(table);  
   
         // number of zones: use a combo box with fix values for gig  
         // v2 and a spin button for v3  
         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;  
387          }          }
388          if (version2) {      }
389              for (int i = 1; i <= 5; i++) {      Gtk::Table table(2, 2);
390                  char buf[3];      Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
391                  sprintf(buf, "%d", 1 << i);      Gtk::ComboBox comboDimType;
392        comboDimType.set_model(refComboModel);
393        comboDimType.pack_start(comboModel.m_type_id);
394        comboDimType.pack_start(comboModel.m_type_name);
395        Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
396        table.attach(labelDimType, 0, 1, 0, 1);
397        table.attach(comboDimType, 1, 2, 0, 1);
398        table.attach(labelZones, 0, 1, 1, 2);
399        dialog.get_vbox()->pack_start(table);
400    
401        // number of zones: use a combo box with fix values for gig
402        // v2 and a spin button for v3
403        Gtk::ComboBoxText comboZones;
404        Gtk::SpinButton spinZones;
405        bool version2 = false;
406        if (region) {
407            gig::File* file = (gig::File*)region->GetParent()->GetParent();
408            version2 = file->pVersion && file->pVersion->major == 2;
409        }
410        if (version2) {
411            for (int i = 1; i <= 5; i++) {
412                char buf[3];
413                sprintf(buf, "%d", 1 << i);
414  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
415                  comboZones.append_text(buf);              comboZones.append_text(buf);
416  #else  #else
417                  comboZones.append(buf);              comboZones.append(buf);
418  #endif  #endif
419              }          }
420              table.attach(comboZones, 1, 2, 1, 2);          table.attach(comboZones, 1, 2, 1, 2);
421        } else {
422            spinZones.set_increments(1, 8);
423            spinZones.set_numeric(true);
424            spinZones.set_range(2, 128);
425            spinZones.set_value(2);
426            table.attach(spinZones, 1, 2, 1, 2);
427        }
428    
429        dialog.add_button(Gtk::Stock::OK, 0);
430        dialog.add_button(Gtk::Stock::CANCEL, 1);
431        dialog.show_all_children();
432    
433        if (!dialog.run()) { // OK selected ...
434            Gtk::TreeModel::iterator iterType = comboDimType.get_active();
435            if (!iterType) return;
436            Gtk::TreeModel::Row rowType = *iterType;
437            if (!rowType) return;
438            int iTypeID = rowType[comboModel.m_type_id];
439            gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
440            gig::dimension_def_t dim;
441            dim.dimension = type;
442    
443            if (version2) {
444                if (comboZones.get_active_row_number() < 0) return;
445                dim.bits = comboZones.get_active_row_number() + 1;
446                dim.zones = 1 << dim.bits;
447          } else {          } else {
448              spinZones.set_increments(1, 8);              dim.zones = spinZones.get_value_as_int();
449              spinZones.set_numeric(true);              dim.bits = zoneCountToBits(dim.zones);
450              spinZones.set_range(2, 128);          }
451              spinZones.set_value(2);  
452              table.attach(spinZones, 1, 2, 1, 2);          // assemble the list of regions where the selected dimension shall be
453          }          // added to
454            std::vector<gig::Region*> vRegions;
455          dialog.add_button(Gtk::Stock::OK, 0);          if (allRegions()) {
456          dialog.add_button(Gtk::Stock::CANCEL, 1);              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
457          dialog.show_all_children();              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
458                    if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
459          if (!dialog.run()) { // OK selected ...              }
460              Gtk::TreeModel::iterator iterType = comboDimType.get_active();          } else vRegions.push_back(region);
461              if (!iterType) return;              
462              Gtk::TreeModel::Row rowType = *iterType;          std::set<Glib::ustring> errors;
463              if (!rowType) return;  
464              gig::dimension_def_t dim;          for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
465              int iTypeID = rowType[comboModel.m_type_id];              gig::Region* region = vRegions[iRgn];
466              dim.dimension = static_cast<gig::dimension_t>(iTypeID);              try {
467                    printf(
468              if (version2) {                      "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
469                  if (comboZones.get_active_row_number() < 0) return;                      dim.dimension, dim.bits, dim.zones
470                  dim.bits = comboZones.get_active_row_number() + 1;                  );
471                  dim.zones = 1 << dim.bits;                  // notify everybody that we're going to update the region
472              } else {                  region_to_be_changed_signal.emit(region);
473                  dim.zones = spinZones.get_value_as_int();                  // add the new dimension to the region
474                  // Find the number of bits required to hold the                  // (implicitly creates new dimension regions)
475                  // specified amount of zones.                  region->AddDimension(&dim);
476                  int zoneBits = dim.zones - 1;                  // let everybody know there was a change
477                  for (dim.bits = 0; zoneBits > 1; dim.bits += 2, zoneBits >>= 2);                  region_changed_signal.emit(region);
478                  dim.bits += zoneBits;              } catch (RIFF::Exception e) {
479              }                  // notify that the changes are over (i.e. to avoid dead locks)
480              printf(                  region_changed_signal.emit(region);
481                  "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",                  Glib::ustring txt = _("Could not add dimension: ") + e.Message;
482                  dim.dimension, dim.bits, dim.zones                  if (vRegions.size() == 1) {
483                        // show error message directly
484                        Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
485                        msg.run();
486                    } else {
487                        // remember error, they are shown after all regions have been processed
488                        errors.insert(txt);
489                    }
490                }
491            }
492            // update all GUI elements
493            refreshManager();
494    
495            if (!errors.empty()) {
496                Glib::ustring txt = _(
497                    "The following errors occurred while trying to create the dimension on all regions:"
498                );
499                txt += "\n\n";
500                for (std::set<Glib::ustring>::const_iterator it = errors.begin();
501                     it != errors.end(); ++it)
502                {
503                    txt += "-> " + *it + "\n";
504                }
505                txt += "\n";
506                txt += _(
507                    "You might also want to check the console for further warnings and "
508                    "error messages."
509              );              );
510              // notify everybody that we're going to update the region              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
511              region_to_be_changed_signal.emit(region);              msg.run();
512              // add the new dimension to the region          }
             // (implicitly creates new dimension regions)  
             region->AddDimension(&dim);  
             // let everybody know there was a change  
             region_changed_signal.emit(region);  
             // update all GUI elements  
             refreshManager();  
         }  
     } 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();  
513      }      }
514  }  }
515    
516  void DimensionManager::removeDimension() {  void DimensionManager::removeDimension() {        
517      Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
518      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
519      if (it) {      if (it) {
520          try {          Gtk::TreeModel::Row row = *it;
521              // notify everybody that we're going to update the region          gig::dimension_t type = row[tableModel.m_type];
522              region_to_be_changed_signal.emit(region);  
523              // remove selected dimension          // assemble the list of regions where the selected dimension shall be
524              Gtk::TreeModel::Row row = *it;          // added to
525              gig::dimension_def_t* dim = row[tableModel.m_definition];          std::vector<gig::Region*> vRegions;
526              region->DeleteDimension(dim);          if (allRegions()) {
527              // let everybody know there was a change              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
528              region_changed_signal.emit(region);              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
529              // update all GUI elements                  if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
530              refreshManager();              }
531          } catch (RIFF::Exception e) {          } else vRegions.push_back(region);
532              // notify that the changes are over (i.e. to avoid dead locks)  
533              region_changed_signal.emit(region);          std::set<Glib::ustring> errors;
534              // show error message  
535              Glib::ustring txt = _("Could not remove dimension: ") + e.Message;          for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
536                gig::Region* region = vRegions[iRgn];
537                gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
538                try {
539                    // notify everybody that we're going to update the region
540                    region_to_be_changed_signal.emit(region);
541                    // remove selected dimension    
542                    region->DeleteDimension(dim);
543                    // let everybody know there was a change
544                    region_changed_signal.emit(region);
545                } catch (RIFF::Exception e) {
546                    // notify that the changes are over (i.e. to avoid dead locks)
547                    region_changed_signal.emit(region);
548                    Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
549                    if (vRegions.size() == 1) {
550                        // show error message directly
551                        Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
552                        msg.run();
553                    } else {
554                        // remember error, they are shown after all regions have been processed
555                        errors.insert(txt);
556                    }
557                }
558            }
559            // update all GUI elements
560            refreshManager();
561    
562            if (!errors.empty()) {
563                Glib::ustring txt = _(
564                    "The following errors occurred while trying to remove the dimension from all regions:"
565                );
566                txt += "\n\n";
567                for (std::set<Glib::ustring>::const_iterator it = errors.begin();
568                     it != errors.end(); ++it)
569                {
570                    txt += "-> " + *it + "\n";
571                }
572                txt += "\n";
573                txt += _(
574                    "You might also want to check the console for further warnings and "
575                    "error messages."
576                );
577              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
578              msg.run();              msg.run();
579          }          }

Legend:
Removed from v.2561  
changed lines
  Added in v.2562

  ViewVC Help
Powered by ViewVC