--- gigedit/trunk/src/gigedit/mainwindow.cpp 2007/09/07 21:18:31 1328 +++ gigedit/trunk/src/gigedit/mainwindow.cpp 2007/10/27 12:28:33 1460 @@ -17,7 +17,6 @@ * 02110-1301 USA. */ -#include #include #include @@ -25,6 +24,9 @@ #include #include #include +#include + +#include "global.h" #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2 #define ABOUT_DIALOG @@ -48,7 +50,8 @@ #include "mainwindow.h" -#define _(String) gettext(String) +#include "../../gfx/status_attached.xpm" +#include "../../gfx/status_detached.xpm" template inline std::string ToString(T o) { std::stringstream ss; @@ -127,6 +130,14 @@ *this, &MainWindow::on_action_quit)); actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument"))); + actionGroup->add(Gtk::Action::create("MenuView", _("_View"))); + Glib::RefPtr toggle_action = + Gtk::ToggleAction::create("Statusbar", _("_Statusbar")); + toggle_action->set_active(true); + actionGroup->add(toggle_action, + sigc::mem_fun( + *this, &MainWindow::on_action_view_status_bar)); + action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP); actionGroup->add(Gtk::Action::create("MenuHelp", action->property_label())); @@ -182,6 +193,9 @@ " " " " " " + " " + " " + " " #ifdef ABOUT_DIALOG " " " " @@ -211,6 +225,12 @@ m_VBox.pack_start(m_HPaned); m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK); m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK); + m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK); + + // Status Bar: + m_StatusBar.pack_start(m_AttachedStateLabel, Gtk::PACK_SHRINK); + m_StatusBar.pack_start(m_AttachedStateImage, Gtk::PACK_SHRINK); + m_StatusBar.show(); m_RegionChooser.signal_region_selected().connect( sigc::mem_fun(*this, &MainWindow::region_changed) ); @@ -295,6 +315,7 @@ file = 0; file_is_changed = false; + set_file_is_shared(false); show_all_children(); @@ -308,12 +329,12 @@ bool MainWindow::on_delete_event(GdkEventAny* event) { - return file_is_changed && !close_confirmation_dialog(); + return !file_is_shared && file_is_changed && !close_confirmation_dialog(); } void MainWindow::on_action_quit() { - if (file_is_changed && !close_confirmation_dialog()) return; + if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return; hide(); } @@ -427,15 +448,16 @@ m_refTreeModel->clear(); m_refSamplesTreeModel->clear(); // free libgig's gig::File instance - if (file) { - delete file; - file = NULL; - } + if (file && !file_is_shared) delete file; + file = NULL; + set_file_is_shared(false); } void MainWindow::on_action_file_new() { - if (file_is_changed && !close_confirmation_dialog()) return; + if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return; + + if (file_is_shared && !leaving_shared_mode_dialog()) return; // clear all GUI elements __clear(); @@ -467,9 +489,29 @@ return response != Gtk::RESPONSE_CANCEL; } +bool MainWindow::leaving_shared_mode_dialog() { + Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?"); + Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE); +#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2 + dialog.set_secondary_text( + _("If you proceed to work on another instrument file, it won't be " + "used by the sampler until you tell the sampler explicitly to " + "load it.") + ); +#endif + dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES); + dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + dialog.set_default_response(Gtk::RESPONSE_CANCEL); + int response = dialog.run(); + dialog.hide(); + return response == Gtk::RESPONSE_YES; +} + void MainWindow::on_action_file_open() { - if (file_is_changed && !close_confirmation_dialog()) return; + if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return; + + if (file_is_shared && !leaving_shared_mode_dialog()) return; Gtk::FileChooserDialog dialog(*this, _("Open file")); dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); @@ -514,7 +556,7 @@ __clear(); // load the instrument gig::File* pFile = (gig::File*) instr->GetParent(); - load_gig(pFile, 0 /*file name*/); + load_gig(pFile, 0 /*file name*/, true /*shared instrument*/); //TODO: automatically select the given instrument } @@ -563,7 +605,7 @@ bool MainWindow::file_save() { if (!check_if_savable()) return false; - if (!file_has_name) return file_save_as(); + if (!file_is_shared && !file_has_name) return file_save_as(); std::cout << "Saving file\n" << std::flush; file_structure_to_be_changed_signal.emit(this->file); @@ -575,7 +617,7 @@ } } catch (RIFF::Exception e) { file_structure_changed_signal.emit(this->file); - Glib::ustring txt = "Could not save file: " + e.Message; + Glib::ustring txt = _("Could not save file: ") + e.Message; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); return false; @@ -630,7 +672,7 @@ file_is_changed = false; } catch (RIFF::Exception e) { file_structure_changed_signal.emit(this->file); - Glib::ustring txt = "Could not save file: " + e.Message; + Glib::ustring txt = _("Could not save file: ") + e.Message; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); return false; @@ -727,7 +769,7 @@ } // show error message box when some sample(s) could not be imported if (error_files.size()) { - Glib::ustring txt = "Could not import the following sample(s):\n" + error_files; + Glib::ustring txt = _("Could not import the following sample(s):\n") + error_files; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); } @@ -744,6 +786,18 @@ #ifdef ABOUT_DIALOG Gtk::AboutDialog dialog; dialog.set_version(VERSION); + dialog.set_copyright("Copyright (C) 2006,2007 Andreas Persson"); + dialog.set_comments( + "Released under the GNU General Public License.\n" + "\n" + "Please notice that this is still a very young instrument editor. " + "So better backup your Gigasampler files before editing them with " + "this application.\n" + "\n" + "Please report bugs to: http://bugs.linuxsampler.org" + ); + dialog.set_website("http://www.linuxsampler.org"); + dialog.set_website_label("http://www.linuxsampler.org"); dialog.run(); #endif } @@ -804,12 +858,42 @@ entry[15].set_text(info->Subject); } +void InstrumentProps::set_IsDrum(bool value) +{ + instrument->IsDrum = value; +} + +void InstrumentProps::set_MIDIBank(uint16_t value) +{ + instrument->MIDIBank = value; +} + +void InstrumentProps::set_MIDIProgram(uint32_t value) +{ + instrument->MIDIProgram = value; +} + +void InstrumentProps::set_DimensionKeyRange_low(uint8_t value) +{ + instrument->DimensionKeyRange.low = value; + if (value > instrument->DimensionKeyRange.high) { + eDimensionKeyRangeHigh.set_value(value); + } +} + +void InstrumentProps::set_DimensionKeyRange_high(uint8_t value) +{ + instrument->DimensionKeyRange.high = value; + if (value < instrument->DimensionKeyRange.low) { + eDimensionKeyRangeLow.set_value(value); + } +} + void InstrumentProps::add_prop(BoolEntry& boolentry) { table.attach(boolentry.widget, 0, 2, rowno, rowno + 1, Gtk::FILL, Gtk::SHRINK); rowno++; - boolentry.signal_changed_by_user().connect(instrument_changed.make_slot()); } void InstrumentProps::add_prop(BoolEntryPlus6& boolentry) @@ -817,7 +901,6 @@ table.attach(boolentry.widget, 0, 2, rowno, rowno + 1, Gtk::FILL, Gtk::SHRINK); rowno++; - boolentry.signal_changed_by_user().connect(instrument_changed.make_slot()); } void InstrumentProps::add_prop(LabelWidget& prop) @@ -827,7 +910,6 @@ table.attach(prop.widget, 1, 2, rowno, rowno + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK); rowno++; - prop.signal_changed_by_user().connect(instrument_changed.make_slot()); } InstrumentProps::InstrumentProps() @@ -844,10 +926,25 @@ ePitchbendRange("Pitchbend range", 0, 12), ePianoReleaseMode("Piano release mode"), eDimensionKeyRangeLow("Dimension key range low"), - eDimensionKeyRangeHigh("Dimension key range high") + eDimensionKeyRangeHigh("Dimension key range high"), + update_model(0) { set_title("Instrument properties"); + connect(eIsDrum, &InstrumentProps::set_IsDrum); + connect(eMIDIBank, &InstrumentProps::set_MIDIBank); + connect(eMIDIProgram, &InstrumentProps::set_MIDIProgram); + connect(eAttenuation, &gig::Instrument::Attenuation); + connect(eGainPlus6, &gig::Instrument::Attenuation); + connect(eEffectSend, &gig::Instrument::EffectSend); + connect(eFineTune, &gig::Instrument::FineTune); + connect(ePitchbendRange, &gig::Instrument::PitchbendRange); + connect(ePianoReleaseMode, &gig::Instrument::PianoReleaseMode); + connect(eDimensionKeyRangeLow, + &InstrumentProps::set_DimensionKeyRange_low); + connect(eDimensionKeyRangeHigh, + &InstrumentProps::set_DimensionKeyRange_high); + rowno = 0; table.set_col_spacings(5); @@ -864,11 +961,6 @@ add_prop(eDimensionKeyRangeLow); add_prop(eDimensionKeyRangeHigh); - eDimensionKeyRangeLow.signal_changed_by_user().connect( - sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed)); - eDimensionKeyRangeHigh.signal_changed_by_user().connect( - sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed)); - add(vbox); table.set_border_width(5); vbox.pack_start(table); @@ -891,37 +983,25 @@ void InstrumentProps::set_instrument(gig::Instrument* instrument) { - eName.set_ptr(&instrument->pInfo->Name); - eIsDrum.set_ptr(&instrument->IsDrum); - eMIDIBank.set_ptr(&instrument->MIDIBank); - eMIDIProgram.set_ptr(&instrument->MIDIProgram); - eAttenuation.set_ptr(&instrument->Attenuation); - eGainPlus6.set_ptr(&instrument->Attenuation); - eEffectSend.set_ptr(&instrument->EffectSend); - eFineTune.set_ptr(&instrument->FineTune); - ePitchbendRange.set_ptr(&instrument->PitchbendRange); - ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode); - eDimensionKeyRangeLow.set_ptr(0); - eDimensionKeyRangeHigh.set_ptr(0); - eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low); - eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high); -} + this->instrument = instrument; -void InstrumentProps::key_range_low_changed() -{ - double l = eDimensionKeyRangeLow.get_value(); - double h = eDimensionKeyRangeHigh.get_value(); - if (h < l) eDimensionKeyRangeHigh.set_value(l); -} - -void InstrumentProps::key_range_high_changed() -{ - double l = eDimensionKeyRangeLow.get_value(); - double h = eDimensionKeyRangeHigh.get_value(); - if (h < l) eDimensionKeyRangeLow.set_value(h); + update_model++; + eName.set_ptr(&instrument->pInfo->Name); + eIsDrum.set_value(instrument->IsDrum); + eMIDIBank.set_value(instrument->MIDIBank); + eMIDIProgram.set_value(instrument->MIDIProgram); + eAttenuation.set_value(instrument->Attenuation); + eGainPlus6.set_value(instrument->Attenuation); + eEffectSend.set_value(instrument->EffectSend); + eFineTune.set_value(instrument->FineTune); + ePitchbendRange.set_value(instrument->PitchbendRange); + ePianoReleaseMode.set_value(instrument->PianoReleaseMode); + eDimensionKeyRangeLow.set_value(instrument->DimensionKeyRange.low); + eDimensionKeyRangeHigh.set_value(instrument->DimensionKeyRange.high); + update_model--; } -sigc::signal InstrumentProps::signal_instrument_changed() +sigc::signal& InstrumentProps::signal_instrument_changed() { return instrument_changed; } @@ -934,9 +1014,10 @@ } } -void MainWindow::load_gig(gig::File* gig, const char* filename) +void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument) { file = 0; + set_file_is_shared(isSharedInstrument); this->filename = filename ? filename : _("Unsaved Gig File"); set_title(Glib::filename_display_basename(this->filename)); @@ -1013,6 +1094,17 @@ } } +void MainWindow::on_action_view_status_bar() { + Gtk::CheckMenuItem* item = + dynamic_cast(uiManager->get_widget("/MenuBar/MenuView/Statusbar")); + if (!item) { + std::cerr << "/MenuBar/MenuView/Statusbar == NULL\n"; + return; + } + if (item->get_active()) m_StatusBar.show(); + else m_StatusBar.hide(); +} + void MainWindow::on_button_release(GdkEventButton* button) { if (button->type == GDK_2BUTTON_PRESS) { @@ -1070,6 +1162,17 @@ void MainWindow::on_action_remove_instrument() { if (!file) return; + if (file_is_shared) { + Gtk::MessageDialog msg( + *this, + _("You cannot delete an instrument from this file, since it's " + "currently used by the sampler."), + false, Gtk::MESSAGE_INFO + ); + msg.run(); + return; + } + Glib::RefPtr sel = m_TreeView.get_selection(); Gtk::TreeModel::iterator it = sel->get_selected(); if (it) { @@ -1256,7 +1359,7 @@ } // show error message box when some file(s) could not be opened / added if (error_files.size()) { - Glib::ustring txt = "Could not add the following sample(s):\n" + error_files; + Glib::ustring txt = _("Could not add the following sample(s):\n") + error_files; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); } @@ -1429,6 +1532,8 @@ // notify we're done with altering region_changed_signal.emit(region); + file_changed(); + return; } // drop failed @@ -1469,38 +1574,54 @@ } } -sigc::signal MainWindow::signal_file_structure_to_be_changed() { +void MainWindow::set_file_is_shared(bool b) { + this->file_is_shared = b; + + if (file_is_shared) { + m_AttachedStateLabel.set_label(_("live-mode")); + m_AttachedStateImage.set( + Gdk::Pixbuf::create_from_xpm_data(status_attached_xpm) + ); + } else { + m_AttachedStateLabel.set_label(_("stand-alone")); + m_AttachedStateImage.set( + Gdk::Pixbuf::create_from_xpm_data(status_detached_xpm) + ); + } +} + +sigc::signal& MainWindow::signal_file_structure_to_be_changed() { return file_structure_to_be_changed_signal; } -sigc::signal MainWindow::signal_file_structure_changed() { +sigc::signal& MainWindow::signal_file_structure_changed() { return file_structure_changed_signal; } -sigc::signal > MainWindow::signal_samples_to_be_removed() { +sigc::signal >& MainWindow::signal_samples_to_be_removed() { return samples_to_be_removed_signal; } -sigc::signal MainWindow::signal_samples_removed() { +sigc::signal& MainWindow::signal_samples_removed() { return samples_removed_signal; } -sigc::signal MainWindow::signal_region_to_be_changed() { +sigc::signal& MainWindow::signal_region_to_be_changed() { return region_to_be_changed_signal; } -sigc::signal MainWindow::signal_region_changed() { +sigc::signal& MainWindow::signal_region_changed() { return region_changed_signal; } -sigc::signal MainWindow::signal_sample_ref_changed() { +sigc::signal& MainWindow::signal_sample_ref_changed() { return sample_ref_changed_signal; } -sigc::signal MainWindow::signal_dimreg_to_be_changed() { +sigc::signal& MainWindow::signal_dimreg_to_be_changed() { return dimreg_to_be_changed_signal; } -sigc::signal MainWindow::signal_dimreg_changed() { +sigc::signal& MainWindow::signal_dimreg_changed() { return dimreg_changed_signal; }