first version of Gtkmm2ext::WindowProxy
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 1 Jul 2015 21:26:14 +0000 (17:26 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 22 Feb 2016 20:31:21 +0000 (15:31 -0500)
libs/gtkmm2ext/gtkmm2ext/window_proxy.h [new file with mode: 0644]
libs/gtkmm2ext/window_proxy.cc [new file with mode: 0644]

diff --git a/libs/gtkmm2ext/gtkmm2ext/window_proxy.h b/libs/gtkmm2ext/gtkmm2ext/window_proxy.h
new file mode 100644 (file)
index 0000000..3ec2080
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2015 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.
+
+*/
+
+#ifndef __gtkmm2ext_window_proxy_h__
+
+#include <string>
+#include <gdkmm/event.h>
+#include <glibmm/refptr.h>
+#include <sigc++/trackable.h>
+
+class XMLNode;
+
+#include "gtkmm2ext/visibility.h"
+
+namespace Gtk {
+class Window;
+class Action;
+}
+
+namespace Gtkmm2ext {
+
+class VisibilityTracker;
+
+class LIBGTKMM2EXT_API WindowProxy : public virtual sigc::trackable
+{
+  public:
+       WindowProxy (const std::string& name, const std::string& menu_name);
+       WindowProxy (const std::string& name, const std::string& menu_name, const XMLNode&);
+       virtual ~WindowProxy();
+    
+       void show ();
+       void show_all ();
+       void hide ();
+       void present ();
+       void maybe_show ();
+    
+       bool visible() const { return _visible; }
+       const std::string& name() const { return _name; }
+       const std::string& menu_name() const { return _menu_name; }
+    
+       std::string action_name() const;
+       void set_action (Glib::RefPtr<Gtk::Action>);
+       Glib::RefPtr<Gtk::Action> action() const { return _action; };
+    
+       void drop_window ();
+       void use_window (Gtk::Window&);
+    
+       virtual Gtk::Window* get (bool create = false) = 0;
+    
+       virtual void toggle ();
+    
+       virtual void set_state (const XMLNode&);
+       virtual XMLNode& get_state () const;
+    
+       operator bool() const { return _window != 0; }
+    
+  protected:
+       std::string  _name;
+       std::string  _menu_name;
+       Glib::RefPtr<Gtk::Action> _action;
+       Gtk::Window* _window;
+       mutable bool _visible; ///< true if the window should be visible on startup
+       mutable int  _x_off; ///< x position
+       mutable int  _y_off; ///< y position
+       mutable int  _width; ///< width
+       mutable int  _height; ///< height
+       Gtkmm2ext::VisibilityTracker* vistracker;
+
+       void save_pos_and_size ();
+       void set_pos_and_size ();
+       
+       virtual bool delete_event_handler (GdkEventAny *ev);
+    
+       virtual void setup ();
+};
+
+}
+
+#endif /* __gtkmm2ext_window_proxy_h__ */
diff --git a/libs/gtkmm2ext/window_proxy.cc b/libs/gtkmm2ext/window_proxy.cc
new file mode 100644 (file)
index 0000000..b01fc6c
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+    Copyright (C) 2015 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/action.h>
+#include <gtkmm/window.h>
+
+#include "pbd/convert.h"
+#include "pbd/xml++.h"
+
+#include "gtkmm2ext/window_proxy.h"
+#include "gtkmm2ext/visibility_tracker.h"
+
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace Gtkmm2ext;
+using namespace PBD;
+
+WindowProxy::WindowProxy (const std::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)
+{
+}
+
+WindowProxy::WindowProxy (const std::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);
+}
+
+WindowProxy::~WindowProxy ()
+{
+       delete vistracker;
+       delete _window;
+}
+
+void
+WindowProxy::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());
+               }
+               if ((prop = (*i)->property (X_("y-off"))) != 0) {
+                       _y_off = atoi (prop->value());
+               }
+               if ((prop = (*i)->property (X_("x-size"))) != 0) {
+                       _width = atoi (prop->value());
+               }
+               if ((prop = (*i)->property (X_("y-size"))) != 0) {
+                       _height = atoi (prop->value());
+               }
+       }
+
+       /* if the window is marked visible but doesn't yet exist, create it */
+       
+       if (_visible) {
+               if (!_window) {
+                       _window = get (true);
+               }
+       }
+       
+       if (_window) {
+               setup ();
+       }
+}
+
+void
+WindowProxy::set_action (Glib::RefPtr<Gtk::Action> act)
+{
+       _action = act;
+}
+
+std::string
+WindowProxy::action_name() const 
+{
+       return string_compose (X_("toggle-%1"), _name);
+}
+
+void
+WindowProxy::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 {
+               if (_window->is_mapped()) {
+                       save_pos_and_size();
+               }
+               vistracker->cycle_visibility ();
+               if (_window->is_mapped()) {
+                       if (_width != -1 && _height != -1) {
+                               _window->set_default_size (_width, _height);
+                       }
+                       if (_x_off != -1 && _y_off != -1) {
+                               _window->move (_x_off, _y_off);
+                       }
+               }
+       }
+}
+
+XMLNode&
+WindowProxy::get_state () const
+{
+       XMLNode* node = new XMLNode (X_("Window"));
+       char buf[32];   
+
+       node->add_property (X_("name"), _name);
+
+       if (_window && vistracker) {
+               
+               /* we have a window, so use current state */
+
+               _visible = vistracker->partially_visible ();
+               _window->get_position (_x_off, _y_off);
+               _window->get_size (_width, _height);
+       }
+
+       node->add_property (X_("visible"), _visible? X_("yes") : X_("no"));
+       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
+WindowProxy::drop_window ()
+{
+       if (_window) {
+               _window->hide ();
+               delete _window;
+               _window = 0;
+               delete vistracker;
+               vistracker = 0;
+       }
+}
+
+void
+WindowProxy::use_window (Gtk::Window& win)
+{
+       drop_window ();
+       _window = &win;
+       setup ();
+}
+
+void
+WindowProxy::setup ()
+{
+       assert (_window);
+
+       vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
+       _window->signal_delete_event().connect (sigc::mem_fun (*this, &WindowProxy::delete_event_handler));
+
+       set_pos_and_size ();
+}
+       
+void
+WindowProxy::show ()
+{
+       get (true);
+       assert (_window);
+       _window->show ();
+}
+
+void
+WindowProxy::maybe_show ()
+{
+       if (_visible) {
+               show ();
+       }
+}
+
+void
+WindowProxy::show_all ()
+{
+       get (true);
+       assert (_window);
+       _window->show_all ();
+}
+
+void
+WindowProxy::present ()
+{
+       get (true);
+       assert (_window);
+
+       _window->show_all ();
+       _window->present ();
+
+       /* turn off any mouse-based positioning */
+       _window->set_position (Gtk::WIN_POS_NONE);
+}
+
+void
+WindowProxy::hide ()
+{
+       if (_window) {
+               save_pos_and_size();
+               _window->hide ();
+       }
+}
+
+bool
+WindowProxy::delete_event_handler (GdkEventAny* /*ev*/)
+{
+       hide();
+       return true;
+}
+
+void
+WindowProxy::save_pos_and_size ()
+{
+       if (_window) {
+               _window->get_position (_x_off, _y_off);
+               _window->get_size (_width, _height);
+       }
+}
+
+void
+WindowProxy::set_pos_and_size ()
+{
+       if (!_window) {
+               return;
+       }
+
+       if (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1) {
+               /* cancel any mouse-based positioning */
+               _window->set_position (Gtk::WIN_POS_NONE);
+       }
+
+       if (_width != -1 && _height != -1) {
+               _window->set_default_size (_width, _height);
+       }
+
+       if (_x_off != -1 && _y_off != -1) {
+               _window->move (_x_off, _y_off);
+       }
+}
+