40591f84ba4a5f37d77a034231bc9abc788e5797
[ardour.git] / gtk2_ardour / window_manager.h
1 /*
2     Copyright (C) 2013 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __gtk2_ardour_window_manager_h__
21 #define __gtk2_ardour_window_manager_h__
22
23 #include <string>
24 #include <map>
25
26 #include <boost/function.hpp>
27 #include <glibmm/refptr.h>
28 #include <sigc++/trackable.h>
29
30 class XMLNode;
31
32 namespace Gtk {
33         class Window;
34         class Action;
35 }
36
37 namespace Gtkmm2ext {
38         class VisibilityTracker;
39 }
40
41 namespace ARDOUR {
42         class Session;
43         class SessionHandlePtr;
44 }
45
46 namespace WM {
47
48 class ProxyBase;
49
50 class Manager : public ARDOUR::SessionHandlePtr
51 {
52   public:
53     static Manager& instance();
54
55     void register_window (ProxyBase*);
56     void remove (const ProxyBase*);
57     void toggle_window (ProxyBase*);
58     void show_visible () const;
59     void set_session (ARDOUR::Session*);
60     void add_state (XMLNode&) const;
61
62     /* HACK HACK HACK */
63     void set_transient_for (Gtk::Window*);
64     Gtk::Window* transient_parent() const { return current_transient_parent; }
65
66   private:
67     typedef std::list<ProxyBase*> Windows;
68     Windows _windows;
69     Glib::RefPtr<Gtk::ActionGroup> window_actions;
70     Gtk::Window* current_transient_parent;
71
72     Manager();
73     ~Manager();
74
75     static Manager* _instance;
76 };
77         
78 class ProxyBase : public ARDOUR::SessionHandlePtr, public sigc::trackable {
79   public:
80     ProxyBase (const std::string& name, const std::string& menu_name);
81     ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode&);
82     virtual ~ProxyBase();
83
84     void show ();
85     void show_all ();
86     void hide ();
87     void present ();
88     void maybe_show ();
89
90     bool visible() const { return _visible; }
91     const std::string& name() const { return _name; }
92     const std::string& menu_name() const { return _menu_name; }
93
94     std::string action_name() const;
95     void set_action (Glib::RefPtr<Gtk::Action>);
96     Glib::RefPtr<Gtk::Action> action() const { return _action; };
97
98     void drop_window ();
99     void use_window (Gtk::Window&);
100
101     virtual Gtk::Window* get (bool create = false) = 0;
102
103     virtual void toggle ();
104
105     void set_state (const XMLNode&);
106     XMLNode& get_state () const;
107
108     virtual ARDOUR::SessionHandlePtr* session_handle () = 0;
109
110     operator bool() const { return _window != 0; }
111
112   protected:
113     std::string  _name;
114     std::string  _menu_name;
115     Glib::RefPtr<Gtk::Action> _action;
116     Gtk::Window* _window;
117     mutable bool _visible; ///< true if the window should be visible on startup
118     mutable int  _x_off; ///< x position
119     mutable int  _y_off; ///< y position
120     mutable int  _width; ///< width
121     mutable int  _height; ///< height
122     Gtkmm2ext::VisibilityTracker* vistracker;
123
124     void save_pos_and_size ();
125     bool delete_event_handler (GdkEventAny *ev);
126
127     void setup ();
128 };
129         
130 class ProxyTemporary: public ProxyBase {
131   public:
132     ProxyTemporary (const std::string& name, Gtk::Window* win);
133     ~ProxyTemporary();
134
135     Gtk::Window* get (bool create = false) {
136             (void) create;
137             return _window;
138     }
139
140     Gtk::Window* operator->() {
141             return _window;
142     }
143
144     ARDOUR::SessionHandlePtr* session_handle ();
145 };
146         
147 template<typename T>
148 class ProxyWithConstructor: public ProxyBase {
149   public:
150     ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c)
151             : ProxyBase (name, menu_name) , creator (c) {}
152         
153     ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c, const XMLNode* node)
154             : ProxyBase (name, menu_name, *node) , creator (c) {}
155         
156     Gtk::Window* get (bool create = false) {
157             if (!_window) {
158                     if (!create) {
159                             return 0;
160                     }
161
162                         _window = dynamic_cast<Gtk::Window*> (creator ());
163
164                     if (_window) {
165                             setup ();
166                     }   
167             }
168
169             return _window;
170     }
171
172     T* operator->() {
173             return dynamic_cast<T*> (get (true));
174     }
175
176     ARDOUR::SessionHandlePtr* session_handle () {
177             /* may return null */
178             return dynamic_cast<T*> (_window);
179     }
180
181     void set_session(ARDOUR::Session *s) {
182         SessionHandlePtr::set_session (s);
183         ARDOUR::SessionHandlePtr* sp = session_handle ();
184         if (sp) {
185             sp->set_session (s);
186             dynamic_cast<T*>(_window)->set_session(s);
187         }
188     }
189
190   private:
191     boost::function<T*()>       creator;
192 };
193
194 template<typename T>
195 class Proxy : public ProxyBase {
196   public:
197     Proxy (const std::string& name, const std::string& menu_name)
198             : ProxyBase (name, menu_name) {}
199
200     Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node)
201             : ProxyBase (name, menu_name, *node)  {}
202         
203     Gtk::Window* get (bool create = false) {
204             if (!_window) {
205                     if (!create) {
206                             return 0;
207                     }
208
209                     _window = new T ();
210
211                     if (_window) {
212                             setup ();
213                     }   
214             }
215
216             return _window;
217     }
218
219     T* operator->() {
220             return dynamic_cast<T*> (get(true));
221     }
222
223     ARDOUR::SessionHandlePtr* session_handle () {
224             /* may return null */
225             return dynamic_cast<T*> (_window);
226     }
227
228     void set_session(ARDOUR::Session *s) {
229         SessionHandlePtr::set_session (s);
230         ARDOUR::SessionHandlePtr* sp = session_handle ();
231         if (sp) {
232             sp->set_session (s);
233             dynamic_cast<T*>(_window)->set_session(s);
234         }
235     }
236
237   private:
238     boost::function<T*()>       creator;
239 };
240
241 } /* namespace */
242
243 #endif /* __gtk2_ardour_window_manager_h__ */