From 552e995297d7706790ed2dfaab75749e914ad317 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 9 Jul 2015 12:40:51 -0400 Subject: [PATCH] save/restore tabbable state --- gtk2_ardour/ardour_ui.cc | 8 +- gtk2_ardour/ardour_ui_ed.cc | 9 +- gtk2_ardour/editor.cc | 82 ++++++++--------- gtk2_ardour/editor.h | 2 +- gtk2_ardour/mixer_ui.cc | 111 +++++------------------- gtk2_ardour/mixer_ui.h | 2 +- gtk2_ardour/rc_option_editor.cc | 4 +- gtk2_ardour/rc_option_editor.h | 2 +- gtk2_ardour/window_manager.cc | 9 +- libs/gtkmm2ext/gtkmm2ext/tabbable.h | 8 +- libs/gtkmm2ext/gtkmm2ext/window_proxy.h | 2 + libs/gtkmm2ext/tabbable.cc | 49 ++++++++++- libs/gtkmm2ext/window_proxy.cc | 8 +- 13 files changed, 141 insertions(+), 155 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 18bd872133..9e17d52e5e 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -427,15 +427,11 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) audio_port_matrix.set_state (*ui_xml, 0); midi_port_matrix.set_state (*ui_xml, 0); export_video_dialog.set_state (*ui_xml, 0); - - /* tabbables */ - // rc_option_editor->set_state (*ui_xml, 0); - // editor->set_state (*ui_xml, 0); - // mixer->set_state (*ui_xml, 0); } + /* Separate windows */ + WM::Manager::instance().register_window (&key_editor); - // WM::Manager::instance().register_window (&rc_option_editor); WM::Manager::instance().register_window (&session_option_editor); WM::Manager::instance().register_window (&speaker_config_window); WM::Manager::instance().register_window (&about); diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 1a89311ec3..20d2153005 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -665,6 +665,10 @@ ARDOUR_UI::save_ardour_state () window_node->add_child_nocopy (*tearoff_node); + XMLNode& enode (editor->get_state()); + XMLNode& mnode (mixer->get_state()); + XMLNode& bnode (meterbridge->get_state()); + Config->add_extra_xml (*window_node); Config->add_extra_xml (audio_midi_setup->get_state()); @@ -672,10 +676,6 @@ ARDOUR_UI::save_ardour_state () UIConfiguration::instance().save_state (); - XMLNode& enode (static_cast(editor)->get_state()); - XMLNode& mnode (mixer->get_state()); - XMLNode& bnode (meterbridge->get_state()); - if (_session) { _session->add_instant_xml (enode); _session->add_instant_xml (mnode); @@ -686,6 +686,7 @@ ARDOUR_UI::save_ardour_state () } else { Config->add_instant_xml (enode); Config->add_instant_xml (mnode); + Config->add_instant_xml (bnode); if (location_ui) { Config->add_instant_xml (location_ui->ui().get_state ()); } diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index aed4330c46..f1dd0b2edd 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1336,6 +1336,8 @@ Editor::set_session (Session *t) the selected Marker; this needs the LocationMarker list to be available. */ XMLNode* node = ARDOUR_UI::instance()->editor_settings(); + + cerr << "Editor - found state node " << node << endl; set_state (*node, Stateful::loading_state_version); /* catch up with the playhead */ @@ -2182,7 +2184,6 @@ int Editor::set_state (const XMLNode& node, int version) { const XMLProperty* prop; - set_id (node); Tabbable::set_state (node, version); @@ -2410,82 +2411,81 @@ Editor::set_state (const XMLNode& node, int version) XMLNode& Editor::get_state () { - XMLNode& node (Tabbable::get_state()); + XMLNode* node = new XMLNode (X_("Editor")); char buf[32]; id().print (buf, sizeof (buf)); - node.add_property ("id", buf); + node->add_property ("id", buf); -#if 0 - // need to save this somehow + node->add_child_nocopy (Tabbable::get_state()); + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&edit_pane)->gobj())); - geometry->add_property("edit-horizontal-pane-pos", string(buf)); - geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0"); + node->add_property("edit-horizontal-pane-pos", string(buf)); + node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0"); snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&editor_summary_pane)->gobj())); - geometry->add_property("edit-vertical-pane-pos", string(buf)); -#endif + node->add_property("edit-vertical-pane-pos", string(buf)); - maybe_add_mixer_strip_width (node); + maybe_add_mixer_strip_width (*node); - node.add_property ("zoom-focus", enum_2_string (zoom_focus)); + node->add_property ("zoom-focus", enum_2_string (zoom_focus)); snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel); - node.add_property ("zoom", buf); - node.add_property ("snap-to", enum_2_string (_snap_type)); - node.add_property ("snap-mode", enum_2_string (_snap_mode)); - node.add_property ("internal-snap-to", enum_2_string (internal_snap_type)); - node.add_property ("internal-snap-mode", enum_2_string (internal_snap_mode)); - node.add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type)); - node.add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode)); - node.add_property ("edit-point", enum_2_string (_edit_point)); + node->add_property ("zoom", buf); + node->add_property ("snap-to", enum_2_string (_snap_type)); + node->add_property ("snap-mode", enum_2_string (_snap_mode)); + node->add_property ("internal-snap-to", enum_2_string (internal_snap_type)); + node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode)); + node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type)); + node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode)); + node->add_property ("edit-point", enum_2_string (_edit_point)); snprintf (buf, sizeof(buf), "%d", _visible_track_count); - node.add_property ("visible-track-count", buf); + node->add_property ("visible-track-count", buf); snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ()); - node.add_property ("playhead", buf); + node->add_property ("playhead", buf); snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame); - node.add_property ("left-frame", buf); + node->add_property ("left-frame", buf); snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ()); - node.add_property ("y-origin", buf); + node->add_property ("y-origin", buf); - node.add_property ("show-measures", _show_measures ? "yes" : "no"); - node.add_property ("maximised", _maximised ? "yes" : "no"); - node.add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); - node.add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no"); - node.add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ())); - node.add_property ("mouse-mode", enum2str(mouse_mode)); - node.add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no"); + node->add_property ("show-measures", _show_measures ? "yes" : "no"); + node->add_property ("maximised", _maximised ? "yes" : "no"); + node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); + node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no"); + node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ())); + node->add_property ("mouse-mode", enum2str(mouse_mode)); + node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no"); Glib::RefPtr act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer")); if (act) { Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - node.add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no"); + node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no"); } act = ActionManager::get_action (X_("Editor"), X_("show-editor-list")); if (act) { Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - node.add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no"); + node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no"); } snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ()); - node.add_property (X_("editor-list-page"), buf); + node->add_property (X_("editor-list-page"), buf); if (button_bindings) { XMLNode* bb = new XMLNode (X_("Buttons")); button_bindings->save (*bb); - node.add_child_nocopy (*bb); + node->add_child_nocopy (*bb); } - node.add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no"); + node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no"); - node.add_child_nocopy (selection->get_state ()); - node.add_child_nocopy (_regions->get_state ()); + node->add_child_nocopy (selection->get_state ()); + node->add_child_nocopy (_regions->get_state ()); snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration()); - node.add_property ("nudge-clock-value", buf); + node->add_property ("nudge-clock-value", buf); - return node; + return *node; } /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units @@ -5935,11 +5935,11 @@ Editor::ui_parameter_changed (string parameter) } Gtk::Window* -Editor::use_own_window () +Editor::use_own_window (bool and_fill_it) { bool new_window = !own_window(); - Gtk::Window* win = Tabbable::use_own_window (); + Gtk::Window* win = Tabbable::use_own_window (and_fill_it); if (win && new_window) { win->set_name ("EditorWindow"); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 8f00fe110b..bd20ba250f 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -144,7 +144,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void set_session (ARDOUR::Session *); ARDOUR::Session* session() const { return _session; } - Gtk::Window* use_own_window (); + Gtk::Window* use_own_window (bool and_fill_it); void first_idle (); virtual bool have_idled () const { return _have_idled; } diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index ad4025c52f..ed2fdfdde5 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -295,50 +295,26 @@ Mixer_UI::track_editor_selection () PublicEditor::instance().get_selection().TracksChanged.connect (sigc::mem_fun (*this, &Mixer_UI::follow_editor_selection)); } -Gtk::Notebook* -Mixer_UI::use_own_window () -{ - /* This is called after a drop of a tab onto the root window. Its - * responsibility is to return the notebook that this Mixer_UI should - * be packed into before the drop handling is completed. It is not - * responsible for actually taking care of this packing - */ - - if (_parent_window) { - return 0; - } - - create_own_window (); - - return (Gtk::Notebook*) _parent_window->get_child(); -} - void -Mixer_UI::create_own_window () +Gtk::Window* +Mixer_UI::use_own_window (bool and_fill_it) { - if (_parent_window) { - return; - } + bool new_window = !own_window(); - _parent_window = new Window (Gtk::WINDOW_TOPLEVEL); - Notebook* notebook = manage (new Notebook); + Gtk::Window* win = Tabbable::use_own_window (and_fill_it); - notebook->set_show_tabs (false); - notebook->show_all (); - _parent_window->add (*notebook); - - /* allow parent window to become the key focus window */ - _parent_window->set_flags (CAN_FOCUS); - - /* handle window manager close/delete event sensibly */ - _parent_window->signal_delete_event().connect (sigc::mem_fun (*this, &Mixer_UI::hide_window)); + if (win && new_window) { + win->set_name ("MixerWindow"); + ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Mixer"), this); + win->signal_scroll_event().connect (sigc::mem_fun (*this, &Mixer_UI::on_scroll_event), false); + win->set_data ("ardour-bindings", bindings); + update_title (); + } - set_window_pos_and_size (); - update_title (); + return win; } -void Mixer_UI::show_window () { if (_parent_window) { @@ -1019,16 +995,16 @@ void Mixer_UI::show_window () { Tabbable::show_window (); - + /* show/hide group tabs as required */ parameter_changed ("show-group-tabs"); - + /* now reset each strips width so the right widgets are shown */ MixerStrip* ms; - + TreeModel::Children rows = track_model->children(); TreeModel::Children::iterator ri; - + for (ri = rows.begin(); ri != rows.end(); ++ri) { ms = (*ri)[track_columns.strip]; ms->set_width_enum (ms->get_width_enum (), ms->width_owner()); @@ -1848,63 +1824,24 @@ Mixer_UI::set_state (const XMLNode& node, int version) XMLNode& Mixer_UI::get_state () { - XMLNode* node = new XMLNode ("Mixer"); - - if (_parent_window && _parent_window->is_realized() ) { - Glib::RefPtr win = _parent_window->get_window(); + XMLNode* node = new XMLNode (X_("Mixer")); + char buf[128]; - get_window_pos_and_size (); + node->add_child_nocopy (Tabbable::get_state()); - XMLNode* geometry = new XMLNode ("geometry"); - char buf[32]; - snprintf(buf, sizeof(buf), "%d", m_width); - geometry->add_property(X_("x_size"), string(buf)); - snprintf(buf, sizeof(buf), "%d", m_height); - geometry->add_property(X_("y_size"), string(buf)); - snprintf(buf, sizeof(buf), "%d", m_root_x); - geometry->add_property(X_("x_pos"), string(buf)); - snprintf(buf, sizeof(buf), "%d", m_root_y); - geometry->add_property(X_("y_pos"), string(buf)); - - // written only for compatibility, they are not used. - snprintf(buf, sizeof(buf), "%d", 0); - geometry->add_property(X_("x_off"), string(buf)); - snprintf(buf, sizeof(buf), "%d", 0); - geometry->add_property(X_("y_off"), string(buf)); - - snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&rhs_pane1)->gobj())); - geometry->add_property(X_("mixer_rhs_pane1_pos"), string(buf)); - snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&rhs_pane2)->gobj())); - geometry->add_property(X_("mixer_rhs_pane2_pos"), string(buf)); - snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&list_hpane)->gobj())); - geometry->add_property(X_("mixer_list_hpane_pos"), string(buf)); - - node->add_child_nocopy (*geometry); - } + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (const_cast(static_cast(&rhs_pane1)->gobj()))); + node->add_property(X_("mixer_rhs_pane1_pos"), string(buf)); + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (const_cast(static_cast(&list_hpane)->gobj()))); + node->add_property(X_("mixer_list_hpane_pos"), string(buf)); node->add_property ("narrow-strips", _strip_width == Narrow ? "yes" : "no"); node->add_property ("show-mixer", _visible ? "yes" : "no"); node->add_property ("show-mixer-list", _show_mixer_list ? "yes" : "no"); node->add_property ("maximised", _maximised ? "yes" : "no"); - store_current_favorite_order (); - XMLNode* plugin_order = new XMLNode ("PluginOrder"); - int cnt = 0; - for (PluginInfoList::const_iterator i = favorite_order.begin(); i != favorite_order.end(); ++i, ++cnt) { - XMLNode* p = new XMLNode ("PluginInfo"); - p->add_property ("sort", cnt); - p->add_property ("unique-id", (*i)->unique_id); - if (favorite_ui_state.find ((*i)->unique_id) != favorite_ui_state.end ()) { - p->add_property ("expanded", favorite_ui_state[(*i)->unique_id]); - } - plugin_order->add_child_nocopy (*p); - ; - } - node->add_child_nocopy (*plugin_order); return *node; } - void Mixer_UI::pane_allocation_handler (Allocation&, Gtk::Paned* which) { @@ -2163,7 +2100,7 @@ Mixer_UI::update_title () if (!own_window()) { return; } - + if (_session) { string n; diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h index 4721bf106f..68c31757e5 100644 --- a/gtk2_ardour/mixer_ui.h +++ b/gtk2_ardour/mixer_ui.h @@ -81,7 +81,7 @@ class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, p static Mixer_UI* instance(); ~Mixer_UI(); - Gtk::Window* use_own_window (); + Gtk::Window* use_own_window (bool and_fill_it); void show_window (); void set_session (ARDOUR::Session *); diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index fee9e47094..1d78c8e855 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -3250,11 +3250,11 @@ RCOptionEditor::populate_sync_options () } Gtk::Window* -RCOptionEditor::use_own_window () +RCOptionEditor::use_own_window (bool and_fill_it) { bool new_window = !own_window(); - Gtk::Window* win = Tabbable::use_own_window (); + Gtk::Window* win = Tabbable::use_own_window (and_fill_it); if (win && new_window) { win->set_name ("PreferencesWindow"); diff --git a/gtk2_ardour/rc_option_editor.h b/gtk2_ardour/rc_option_editor.h index 1681a92a2b..416563dac5 100644 --- a/gtk2_ardour/rc_option_editor.h +++ b/gtk2_ardour/rc_option_editor.h @@ -41,7 +41,7 @@ public: void populate_sync_options (); - Gtk::Window* use_own_window (); + Gtk::Window* use_own_window (bool and_fill_it); private: void parameter_changed (std::string const &); diff --git a/gtk2_ardour/window_manager.cc b/gtk2_ardour/window_manager.cc index 3ab742199d..e876668e59 100644 --- a/gtk2_ardour/window_manager.cc +++ b/gtk2_ardour/window_manager.cc @@ -115,15 +115,12 @@ Manager::add_state (XMLNode& root) const for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) { /* don't save state for temporary proxy windows */ + if (dynamic_cast (*i)) { continue; } - if (dynamic_cast (*i)) { - ProcessorWindowProxy *pi = dynamic_cast (*i); - root.add_child_nocopy (pi->get_state()); - } else { - root.add_child_nocopy ((*i)->get_state()); - } + + root.add_child_nocopy ((*i)->get_state()); } } diff --git a/libs/gtkmm2ext/gtkmm2ext/tabbable.h b/libs/gtkmm2ext/gtkmm2ext/tabbable.h index 7c7dd15d23..5ed0eeb843 100644 --- a/libs/gtkmm2ext/gtkmm2ext/tabbable.h +++ b/libs/gtkmm2ext/gtkmm2ext/tabbable.h @@ -46,8 +46,7 @@ class LIBGTKMM2EXT_API Tabbable : public WindowProxy { Gtk::Window* get (bool create = false); Gtk::Window* own_window () { return get (false); } - Gtk::Notebook* tabbed_parent (); - virtual Gtk::Window* use_own_window (); + virtual Gtk::Window* use_own_window (bool and_pack_it); bool has_own_window () const; bool is_tabbed () const; @@ -59,6 +58,11 @@ class LIBGTKMM2EXT_API Tabbable : public WindowProxy { Gtk::Window* current_toplevel () const; Gtk::Notebook* tab_root_drop (); + + int set_state (const XMLNode&, int version); + XMLNode& get_state (); + + static std::string xml_node_name(); protected: bool delete_event_handler (GdkEventAny *ev); diff --git a/libs/gtkmm2ext/gtkmm2ext/window_proxy.h b/libs/gtkmm2ext/gtkmm2ext/window_proxy.h index 01f53826bd..a0026d9f97 100644 --- a/libs/gtkmm2ext/gtkmm2ext/window_proxy.h +++ b/libs/gtkmm2ext/gtkmm2ext/window_proxy.h @@ -73,6 +73,8 @@ class LIBGTKMM2EXT_API WindowProxy : public PBD::StatefulDestructible, public vi operator bool() const { return _window != 0; } + static std::string xml_node_name(); + protected: std::string _name; std::string _menu_name; diff --git a/libs/gtkmm2ext/tabbable.cc b/libs/gtkmm2ext/tabbable.cc index 45e21a6b7b..245be5542f 100644 --- a/libs/gtkmm2ext/tabbable.cc +++ b/libs/gtkmm2ext/tabbable.cc @@ -24,6 +24,8 @@ #include "gtkmm2ext/tabbable.h" #include "gtkmm2ext/visibility_tracker.h" +#include "i18n.h" + using namespace Gtkmm2ext; using namespace Gtk; using std::string; @@ -55,9 +57,20 @@ Tabbable::add_to_notebook (Notebook& notebook, const string& tab_title, int posi } Window* -Tabbable::use_own_window () +Tabbable::use_own_window (bool and_pack_it) { - return get (true); + Gtk::Window* win = get (true); + + if (and_pack_it) { + Gtk::Container* parent = _contents.get_parent(); + if (parent) { + parent->remove (_contents); + } + _own_notebook.append_page (_contents, _tab_title); + } + + return win; + } bool @@ -108,7 +121,7 @@ Tabbable::tab_root_drop () alloc = _contents.get_parent()->get_allocation(); - (void) use_own_window (); + (void) use_own_window (false); /* This is called after a drop of a tab onto the root window. Its * responsibility is to return the notebook that this Tabbable's @@ -212,3 +225,33 @@ Tabbable::current_toplevel () const { return dynamic_cast (contents().get_toplevel()); } + +string +Tabbable::xml_node_name() +{ + return WindowProxy::xml_node_name(); +} + +XMLNode& +Tabbable::get_state() +{ + XMLNode& node (WindowProxy::get_state()); + + return node; +} + +int +Tabbable::set_state (const XMLNode& node, int version) +{ + int ret; + + if ((ret = WindowProxy::set_state (node, version)) == 0) { + if (_visible) { + if (use_own_window (true) == 0) { + ret = -1; + } + } + } + + return ret; +} diff --git a/libs/gtkmm2ext/window_proxy.cc b/libs/gtkmm2ext/window_proxy.cc index d393f4d9bb..dd1d4c35bd 100644 --- a/libs/gtkmm2ext/window_proxy.cc +++ b/libs/gtkmm2ext/window_proxy.cc @@ -171,10 +171,16 @@ WindowProxy::toggle() } } +std::string +WindowProxy::xml_node_name() +{ + return X_("Window"); +} + XMLNode& WindowProxy::get_state () { - XMLNode* node = new XMLNode (X_("Window")); + XMLNode* node = new XMLNode (xml_node_name()); char buf[32]; node->add_property (X_("name"), _name); -- 2.30.2