save/restore tabbable state

This commit is contained in:
Paul Davis
2015-07-09 12:40:51 -04:00
parent 26a9471b61
commit 552e995297
13 changed files with 145 additions and 159 deletions

View File

@@ -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);

View File

@@ -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<Stateful*>(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 ());
}

View File

@@ -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
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
geometry->add_property("edit-horizontal-pane-pos", string(buf));
geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
geometry->add_property("edit-vertical-pane-pos", string(buf));
#endif
node->add_child_nocopy (Tabbable::get_state());
maybe_add_mixer_strip_width (node);
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
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<Paned*>(&editor_summary_pane)->gobj()));
node->add_property("edit-vertical-pane-pos", string(buf));
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<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::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<ToggleAction> tact = Glib::RefPtr<ToggleAction>::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");

View File

@@ -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; }

View File

@@ -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 ()
void
Gtk::Window*
Mixer_UI::use_own_window (bool and_fill_it)
{
/* 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
*/
bool new_window = !own_window();
if (_parent_window) {
return 0;
Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
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 ();
}
create_own_window ();
return (Gtk::Notebook*) _parent_window->get_child();
return win;
}
void
Mixer_UI::create_own_window ()
{
if (_parent_window) {
return;
}
_parent_window = new Window (Gtk::WINDOW_TOPLEVEL);
Notebook* notebook = manage (new Notebook);
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));
set_window_pos_and_size ();
update_title ();
}
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");
XMLNode* node = new XMLNode (X_("Mixer"));
char buf[128];
if (_parent_window && _parent_window->is_realized() ) {
Glib::RefPtr<Gdk::Window> win = _parent_window->get_window();
node->add_child_nocopy (Tabbable::get_state());
get_window_pos_and_size ();
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<Paned*>(&rhs_pane1)->gobj()));
geometry->add_property(X_("mixer_rhs_pane1_pos"), string(buf));
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&rhs_pane2)->gobj()));
geometry->add_property(X_("mixer_rhs_pane2_pos"), string(buf));
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&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<GtkPaned*>(static_cast<const Paned*>(&rhs_pane1)->gobj())));
node->add_property(X_("mixer_rhs_pane1_pos"), string(buf));
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (const_cast<GtkPaned*>(static_cast<const Paned*>(&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;

View File

@@ -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 *);

View File

@@ -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");

View File

@@ -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 &);

View File

@@ -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<ProxyTemporary*> (*i)) {
continue;
}
if (dynamic_cast<ProcessorWindowProxy*> (*i)) {
ProcessorWindowProxy *pi = dynamic_cast<ProcessorWindowProxy*> (*i);
root.add_child_nocopy (pi->get_state());
} else {
root.add_child_nocopy ((*i)->get_state());
}
root.add_child_nocopy ((*i)->get_state());
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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<Gtk::Window*> (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;
}

View File

@@ -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);