Speed up AFL/PFL changes for large sessions
[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 #include "gtkmm2ext/bindings.h"
31 #include "gtkmm2ext/window_proxy.h"
32
33 class XMLNode;
34
35 namespace Gtk {
36 class Window;
37 class Action;
38 }
39
40 namespace Gtkmm2ext {
41         class VisibilityTracker;
42 }
43
44 namespace ARDOUR {
45         class Session;
46         class SessionHandlePtr;
47 }
48
49 namespace WM {
50
51 class ProxyBase;
52
53 class Manager : public ARDOUR::SessionHandlePtr
54 {
55   public:
56         static Manager& instance();
57
58         void register_window (ProxyBase*);
59         void remove (const ProxyBase*);
60         void toggle_window (ProxyBase*);
61         void show_visible () const;
62         void set_session (ARDOUR::Session*);
63         void add_state (XMLNode&) const;
64
65         /* HACK HACK HACK */
66         void set_transient_for (Gtk::Window*);
67         Gtk::Window* transient_parent() const { return current_transient_parent; }
68
69                                         private:
70         typedef std::list<ProxyBase*> Windows;
71         Windows _windows;
72         Glib::RefPtr<Gtk::ActionGroup> window_actions;
73         Gtk::Window* current_transient_parent;
74
75         Manager();
76         ~Manager();
77
78         static Manager* _instance;
79   private:
80         void window_proxy_was_mapped (ProxyBase*);
81         void window_proxy_was_unmapped (ProxyBase*);
82 };
83
84 class ProxyBase : public ARDOUR::SessionHandlePtr, public Gtkmm2ext::WindowProxy
85 {
86   public:
87         ProxyBase (const std::string& name, const std::string& menu_name);
88         ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode&);
89
90         virtual ARDOUR::SessionHandlePtr* session_handle () = 0;
91
92   protected:
93         void setup ();
94 };
95
96 class ProxyTemporary: public ProxyBase
97 {
98   public:
99         ProxyTemporary (const std::string& name, Gtk::Window* win);
100         ~ProxyTemporary();
101
102         Gtk::Window* get (bool create = false) {
103                 (void) create;
104                 return _window;
105         }
106
107         Gtk::Window* operator->() {
108                 return _window;
109         }
110
111         ARDOUR::SessionHandlePtr* session_handle ();
112 };
113
114 template<typename T>
115 class ProxyWithConstructor: public ProxyBase
116 {
117   public:
118         ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c)
119                 : ProxyBase (name, menu_name) , creator (c) {}
120
121         ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c, const XMLNode* node)
122                 : ProxyBase (name, menu_name, *node) , creator (c) {}
123
124         Gtk::Window* get (bool create = false) {
125                 if (!_window) {
126                         if (!create) {
127                                 return 0;
128                         }
129
130                         _window = dynamic_cast<Gtk::Window*> (creator ());
131
132                         if (_window) {
133                                 setup ();
134                         }
135                 }
136
137                 return _window;
138         }
139
140         T* operator->() {
141                 return dynamic_cast<T*> (get (true));
142         }
143
144         ARDOUR::SessionHandlePtr* session_handle () {
145                 /* may return null */
146                 return dynamic_cast<T*> (_window);
147         }
148
149         void set_session(ARDOUR::Session *s) {
150                 SessionHandlePtr::set_session (s);
151                 ARDOUR::SessionHandlePtr* sp = session_handle ();
152                 if (sp) {
153                         sp->set_session (s);
154                         dynamic_cast<T*>(_window)->set_session(s);
155                 }
156         }
157
158                                         private:
159         boost::function<T*()>   creator;
160 };
161
162 template<typename T>
163 class Proxy : public ProxyBase
164 {
165   public:
166         Proxy (const std::string& name, const std::string& menu_name)
167                 : ProxyBase (name, menu_name) {}
168
169         Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node)
170                 : ProxyBase (name, menu_name, *node)  {}
171
172         Gtk::Window* get (bool create = false) {
173                 if (!_window) {
174                         if (!create) {
175                                 return 0;
176                         }
177
178                         _window = new T ();
179
180                         if (_window) {
181                                 setup ();
182                         }
183                 }
184
185                 return _window;
186         }
187
188         T* operator->() {
189                 return dynamic_cast<T*> (get(true));
190         }
191
192         ARDOUR::SessionHandlePtr* session_handle () {
193                 /* may return null */
194                 return dynamic_cast<T*> (_window);
195         }
196
197         void set_session(ARDOUR::Session *s) {
198                 SessionHandlePtr::set_session (s);
199                 ARDOUR::SessionHandlePtr* sp = session_handle ();
200                 if (sp) {
201                         sp->set_session (s);
202                         dynamic_cast<T*>(_window)->set_session(s);
203                 }
204         }
205
206   private:
207         boost::function<T*()>   creator;
208 };
209
210 } /* namespace */
211
212 #endif /* __gtk2_ardour_window_manager_h__ */