summaryrefslogtreecommitdiff
path: root/gtk2_ardour/window_manager.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2013-05-04 22:01:13 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2013-05-04 22:01:13 -0400
commit9267648e5dd8d8db5fa39ae2a264b261d6c75dbe (patch)
tree79b5249abca0fc318bf38c59980b428f9c766143 /gtk2_ardour/window_manager.cc
parent6fd66bd46768f205e4eb02d6e14ef4a3a20700d2 (diff)
VisibilityTracker needs to inherit from sigc::tracker so that it can be used without combination with other sigc::trackable parents; fix partially_visible() logic
Diffstat (limited to 'gtk2_ardour/window_manager.cc')
-rw-r--r--gtk2_ardour/window_manager.cc333
1 files changed, 333 insertions, 0 deletions
diff --git a/gtk2_ardour/window_manager.cc b/gtk2_ardour/window_manager.cc
new file mode 100644
index 0000000000..5732e21a25
--- /dev/null
+++ b/gtk2_ardour/window_manager.cc
@@ -0,0 +1,333 @@
+/*
+ Copyright (C) 2013 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <gtkmm/window.h>
+
+#include "pbd/xml++.h"
+
+#include "ardour/session_handle.h"
+
+#include "gtkmm2ext/visibility_tracker.h"
+
+#include "actions.h"
+#include "window_manager.h"
+
+#include "i18n.h"
+
+using std::string;
+
+WindowManager* WindowManager::_instance = 0;
+
+WindowManager&
+WindowManager::instance ()
+{
+ if (!_instance) {
+ _instance = new WindowManager;
+ }
+ return *_instance;
+}
+
+WindowManager::WindowManager ()
+{
+}
+
+void
+WindowManager::register_window (ProxyBase* info)
+{
+ _windows.push_back (info);
+
+ if (info->rc_configured() && !info->menu_name().empty()) {
+
+ if (!window_actions) {
+ window_actions = Gtk::ActionGroup::create (X_("Window"));
+ ActionManager::add_action_group (window_actions);
+ }
+
+ info->set_action (ActionManager::register_action (window_actions, info->action_name().c_str(), info->menu_name().c_str(),
+ sigc::bind (sigc::mem_fun (*this, &WindowManager::toggle_window), info)));
+ }
+}
+
+void
+WindowManager::remove (const ProxyBase* info)
+{
+ for (Windows::iterator i = _windows.begin(); i != _windows.end(); ++i) {
+ if ((*i) == info) {
+ _windows.erase (i);
+ return;
+ }
+ }
+}
+
+void
+WindowManager::toggle_window (ProxyBase* proxy)
+{
+ if (proxy) {
+ proxy->toggle ();
+ }
+}
+
+void
+WindowManager::show_visible() const
+{
+ for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
+ if ((*i)->visible()) {
+ (*i)->show_all ();
+ (*i)->present ();
+ }
+ }
+}
+
+void
+WindowManager::add_state (XMLNode& root) const
+{
+ for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
+ root.add_child_nocopy ((*i)->get_state());
+ }
+}
+
+void
+WindowManager::set_session (ARDOUR::Session* s)
+{
+ for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
+ ARDOUR::SessionHandlePtr* sp = (*i)->session_handle ();
+ if (sp) {
+ sp->set_session (s);
+ }
+ }
+}
+
+/*-----------------------*/
+
+WindowManager::ProxyBase::ProxyBase (const string& name, const std::string& menu_name)
+ : _name (name)
+ , _menu_name (menu_name)
+ , _window (0)
+ , _visible (false)
+ , _x_off (-1)
+ , _y_off (-1)
+ , _width (-1)
+ , _height (-1)
+ , vistracker (0)
+{
+}
+
+WindowManager::ProxyBase::ProxyBase (const string& name, const std::string& menu_name, const XMLNode& node)
+ : _name (name)
+ , _menu_name (menu_name)
+ , _window (0)
+ , _visible (false)
+ , _x_off (-1)
+ , _y_off (-1)
+ , _width (-1)
+ , _height (-1)
+ , vistracker (0)
+{
+ set_state (node);
+}
+
+WindowManager::ProxyBase::~ProxyBase ()
+{
+ delete vistracker;
+}
+
+void
+WindowManager::ProxyBase::set_state (const XMLNode& node)
+{
+ XMLNodeList children = node.children ();
+
+ XMLNodeList::const_iterator i = children.begin ();
+
+ while (i != children.end()) {
+ XMLProperty* prop = (*i)->property (X_("name"));
+ if ((*i)->name() == X_("Window") && prop && prop->value() == _name) {
+ break;
+ }
+
+ ++i;
+ }
+
+ if (i != children.end()) {
+
+ XMLProperty* prop;
+
+ if ((prop = (*i)->property (X_("visible"))) != 0) {
+ _visible = PBD::string_is_affirmative (prop->value ());
+ }
+
+ if ((prop = (*i)->property (X_("x-off"))) != 0) {
+ _x_off = atoi (prop->value().c_str());
+ }
+ if ((prop = (*i)->property (X_("y-off"))) != 0) {
+ _y_off = atoi (prop->value().c_str());
+ }
+ if ((prop = (*i)->property (X_("x-size"))) != 0) {
+ _width = atoi (prop->value().c_str());
+ }
+ if ((prop = (*i)->property (X_("y-size"))) != 0) {
+ _height = atoi (prop->value().c_str());
+ }
+ }
+
+ /* if we have a window already, reset its properties */
+
+ if (_window) {
+ setup ();
+ }
+}
+
+void
+WindowManager::ProxyBase::set_action (Glib::RefPtr<Gtk::Action> act)
+{
+ _action = act;
+}
+
+std::string
+WindowManager::ProxyBase::action_name() const
+{
+ return string_compose (X_("toggle-%1"), _name);
+}
+
+void
+WindowManager::ProxyBase::toggle()
+{
+ if (!_window) {
+ (void) get (true);
+ assert (_window);
+ /* XXX this is a hack - the window object should really
+ ensure its components are all visible. sigh.
+ */
+ _window->show_all();
+ /* we'd like to just call this and nothing else */
+ _window->present ();
+ } else {
+ vistracker->cycle_visibility ();
+ }
+}
+
+bool
+WindowManager::ProxyBase::configured (GdkEventConfigure* ev)
+{
+ _visible = true;
+ _x_off = ev->x;
+ _y_off = ev->y;
+ _height = ev->height;
+ _width = ev->width;
+
+ return false;
+}
+
+XMLNode&
+WindowManager::ProxyBase::get_state () const
+{
+ XMLNode* node = new XMLNode (X_("Window"));
+ node->add_property (X_("name"), _name);
+ node->add_property (X_("visible"), _visible ? X_("yes") : X_("no"));
+
+ char buf[32];
+ snprintf (buf, sizeof (buf), "%d", _x_off);
+ node->add_property (X_("x-off"), buf);
+ snprintf (buf, sizeof (buf), "%d", _y_off);
+ node->add_property (X_("y-off"), buf);
+ snprintf (buf, sizeof (buf), "%d", _width);
+ node->add_property (X_("x-size"), buf);
+ snprintf (buf, sizeof (buf), "%d", _height);
+ node->add_property (X_("y-size"), buf);
+
+ return *node;
+}
+
+void
+WindowManager::ProxyBase::clear ()
+{
+ if (_window) {
+ _window->hide ();
+ delete _window;
+ _window = 0;
+ configure_connection.disconnect ();
+ delete vistracker;
+ vistracker = 0;
+ }
+}
+
+void
+WindowManager::ProxyBase::use_window (Gtk::Window& win)
+{
+ clear ();
+ _window = &win;
+ setup ();
+}
+
+void
+WindowManager::ProxyBase::setup ()
+{
+ assert (_window);
+
+ configure_connection = _window->signal_configure_event().connect (sigc::mem_fun (*this, &ProxyBase::configured), false);
+
+ vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
+
+ if (_width != -1 && _height != -1) {
+ _window->set_default_size (_width, _height);
+ }
+
+ if (_x_off != -1 && _y_off != -1) {
+ _window->move (_x_off, _y_off);
+ }
+}
+
+void
+WindowManager::ProxyBase::show ()
+{
+ Gtk::Window* win = get (true);
+ win->show ();
+}
+
+void
+WindowManager::ProxyBase::maybe_show ()
+{
+ if (_visible) {
+ show ();
+ }
+}
+
+void
+WindowManager::ProxyBase::show_all ()
+{
+ Gtk::Window* win = get (true);
+ win->show_all ();
+}
+
+
+void
+WindowManager::ProxyBase::present ()
+{
+ Gtk::Window* win = get (true);
+ win->show_all ();
+ win->present ();
+}
+
+void
+WindowManager::ProxyBase::hide ()
+{
+ Gtk::Window* win = get (false);
+ if (win) {
+ win->hide ();
+ }
+}
+