fix save/restore [plugin] window pos&size (without save)
[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 
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 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     
126     void setup ();
127 };
128         
129 class ProxyTemporary: public ProxyBase {
130   public:
131     ProxyTemporary (const std::string& name, Gtk::Window* win);
132     ~ProxyTemporary();
133     
134     Gtk::Window* get (bool create = false) { 
135             (void) create;
136             return _window;
137     }
138     
139     Gtk::Window* operator->() { 
140             return _window;
141     }
142     
143     ARDOUR::SessionHandlePtr* session_handle ();
144 };
145         
146 template<typename T>
147 class ProxyWithConstructor: public ProxyBase {
148   public:
149     ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c)
150             : ProxyBase (name, menu_name) , creator (c) {}
151         
152     ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c, const XMLNode* node)
153             : ProxyBase (name, menu_name, node) , creator (c) {}
154         
155     Gtk::Window* get (bool create = false) { 
156             if (!_window) {
157                     if (!create) {
158                             return 0;
159                     }
160
161                     _window = creator ();
162
163                     if (_window) {
164                             setup ();
165                     }   
166             }
167
168             return _window;
169     }
170
171     T* operator->() { 
172             return dynamic_cast<T*> (get (true));
173     }
174
175     ARDOUR::SessionHandlePtr* session_handle () {
176             /* may return null */
177             return dynamic_cast<T*> (_window);
178     }
179
180   private:
181     boost::function<T*()>       creator;
182 };
183
184 template<typename T>
185 class Proxy : public ProxyBase {
186   public:
187     Proxy (const std::string& name, const std::string& menu_name)
188             : ProxyBase (name, menu_name) {}
189
190     Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node)
191             : ProxyBase (name, menu_name, node)  {}
192         
193     Gtk::Window* get (bool create = false) { 
194             if (!_window) {
195                     if (!create) {
196                             return 0;
197                     }
198
199                     _window = new T ();
200
201                     if (_window) {
202                             setup ();
203                     }   
204             }
205
206             return _window;
207     }
208
209     T* operator->() { 
210             return dynamic_cast<T*> (get(true));
211     }
212
213     ARDOUR::SessionHandlePtr* session_handle () {
214             /* may return null */
215             return dynamic_cast<T*> (_window);
216     }
217
218   private:
219     boost::function<T*()>       creator;
220 };
221     
222 } /* namespace */
223
224 #endif /* __gtk2_ardour_window_manager_h__ */