first compilable version of tabbable design.
[ardour.git] / libs / gtkmm2ext / window_proxy.cc
1 /*
2     Copyright (C) 2015 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 #include <gtkmm/action.h>
21 #include <gtkmm/window.h>
22
23 #include "pbd/convert.h"
24 #include "pbd/xml++.h"
25
26 #include "gtkmm2ext/window_proxy.h"
27 #include "gtkmm2ext/visibility_tracker.h"
28
29 #include "i18n.h"
30
31 using namespace Gtk;
32 using namespace Gtkmm2ext;
33 using namespace PBD;
34
35 WindowProxy::WindowProxy (const std::string& name)
36         : _name (name)
37         , _window (0)
38         , _visible (false)
39         , _x_off (-1)
40         , _y_off (-1)
41         , _width (-1)
42         , _height (-1) 
43         , vistracker (0)
44 {
45 }
46
47 WindowProxy::WindowProxy (const std::string& name, const std::string& menu_name)
48         : _name (name)
49         , _menu_name (menu_name)
50         , _window (0)
51         , _visible (false)
52         , _x_off (-1)
53         , _y_off (-1)
54         , _width (-1)
55         , _height (-1) 
56         , vistracker (0)
57 {
58 }
59
60 WindowProxy::WindowProxy (const std::string& name, const std::string& menu_name, const XMLNode& node)
61         : _name (name)
62         , _menu_name (menu_name)
63         , _window (0)
64         , _visible (false)
65         , _x_off (-1)
66         , _y_off (-1)
67         , _width (-1)
68         , _height (-1) 
69         , vistracker (0)
70 {
71         set_state (node, 0);
72 }
73
74 WindowProxy::~WindowProxy ()
75 {
76         delete vistracker;
77         delete _window;
78 }
79
80 int
81 WindowProxy::set_state (const XMLNode& node, int /* version */)
82 {
83         XMLNodeList children = node.children ();
84
85         XMLNodeList::const_iterator i = children.begin ();
86
87         while (i != children.end()) {
88                 XMLProperty* prop = (*i)->property (X_("name"));
89                 if ((*i)->name() == X_("Window") && prop && prop->value() == _name) {
90                         break;
91                 }
92
93                 ++i;
94         }
95
96         if (i != children.end()) {
97
98                 XMLProperty* prop;
99
100                 if ((prop = (*i)->property (X_("visible"))) != 0) {
101                         _visible = PBD::string_is_affirmative (prop->value ());
102                 }
103
104                 if ((prop = (*i)->property (X_("x-off"))) != 0) {
105                         _x_off = atoi (prop->value());
106                 }
107                 if ((prop = (*i)->property (X_("y-off"))) != 0) {
108                         _y_off = atoi (prop->value());
109                 }
110                 if ((prop = (*i)->property (X_("x-size"))) != 0) {
111                         _width = atoi (prop->value());
112                 }
113                 if ((prop = (*i)->property (X_("y-size"))) != 0) {
114                         _height = atoi (prop->value());
115                 }
116         }
117
118         /* if the window is marked visible but doesn't yet exist, create it */
119         
120         if (_visible) {
121                 if (!_window) {
122                         _window = get (true);
123                 }
124         }
125         
126         if (_window) {
127                 setup ();
128         }
129
130         return 0;
131 }
132
133 void
134 WindowProxy::set_action (Glib::RefPtr<Gtk::Action> act)
135 {
136         _action = act;
137 }
138
139 std::string
140 WindowProxy::action_name() const 
141 {
142         return string_compose (X_("toggle-%1"), _name);
143 }
144
145 void
146 WindowProxy::toggle() 
147 {
148         if (!_window) {
149                 (void) get (true);
150                 assert (_window);
151                 /* XXX this is a hack - the window object should really
152                    ensure its components are all visible. sigh.
153                 */
154                 _window->show_all();
155                 /* we'd like to just call this and nothing else */
156                 _window->present ();
157
158         } else {
159                 if (_window->is_mapped()) {
160                         save_pos_and_size();
161                 }
162                 vistracker->cycle_visibility ();
163                 if (_window->is_mapped()) {
164                         if (_width != -1 && _height != -1) {
165                                 _window->set_default_size (_width, _height);
166                         }
167                         if (_x_off != -1 && _y_off != -1) {
168                                 _window->move (_x_off, _y_off);
169                         }
170                 }
171         }
172 }
173
174 XMLNode&
175 WindowProxy::get_state ()
176 {
177         XMLNode* node = new XMLNode (X_("Window"));
178         char buf[32];   
179
180         node->add_property (X_("name"), _name);
181
182         if (_window && vistracker) {
183                 
184                 /* we have a window, so use current state */
185
186                 _visible = vistracker->partially_visible ();
187                 _window->get_position (_x_off, _y_off);
188                 _window->get_size (_width, _height);
189         }
190
191         node->add_property (X_("visible"), _visible? X_("yes") : X_("no"));
192         snprintf (buf, sizeof (buf), "%d", _x_off);
193         node->add_property (X_("x-off"), buf);
194         snprintf (buf, sizeof (buf), "%d", _y_off);
195         node->add_property (X_("y-off"), buf);
196         snprintf (buf, sizeof (buf), "%d", _width);
197         node->add_property (X_("x-size"), buf);
198         snprintf (buf, sizeof (buf), "%d", _height);
199         node->add_property (X_("y-size"), buf);
200
201         return *node;
202 }
203
204 void
205 WindowProxy::drop_window ()
206 {
207         if (_window) {
208                 _window->hide ();
209                 delete _window;
210                 _window = 0;
211                 delete vistracker;
212                 vistracker = 0;
213         }
214 }
215
216 void
217 WindowProxy::use_window (Gtk::Window& win)
218 {
219         drop_window ();
220         _window = &win;
221         setup ();
222 }
223
224 void
225 WindowProxy::setup ()
226 {
227         assert (_window);
228
229         vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
230         _window->signal_delete_event().connect (sigc::mem_fun (*this, &WindowProxy::delete_event_handler));
231
232         set_pos_and_size ();
233 }
234         
235 void
236 WindowProxy::show ()
237 {
238         get (true);
239         assert (_window);
240         _window->show ();
241 }
242
243 void
244 WindowProxy::maybe_show ()
245 {
246         if (_visible) {
247                 show ();
248         }
249 }
250
251 void
252 WindowProxy::show_all ()
253 {
254         get (true);
255         assert (_window);
256         _window->show_all ();
257 }
258
259 void
260 WindowProxy::present ()
261 {
262         get (true);
263         assert (_window);
264
265         _window->show_all ();
266         _window->present ();
267
268         /* turn off any mouse-based positioning */
269         _window->set_position (Gtk::WIN_POS_NONE);
270 }
271
272 void
273 WindowProxy::hide ()
274 {
275         if (_window) {
276                 save_pos_and_size();
277                 _window->hide ();
278         }
279 }
280
281 bool
282 WindowProxy::delete_event_handler (GdkEventAny* /*ev*/)
283 {
284         hide();
285         return true;
286 }
287
288 void
289 WindowProxy::save_pos_and_size ()
290 {
291         if (_window) {
292                 _window->get_position (_x_off, _y_off);
293                 _window->get_size (_width, _height);
294         }
295 }
296
297 void
298 WindowProxy::set_pos_and_size ()
299 {
300         if (!_window) {
301                 return;
302         }
303
304         if (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1) {
305                 /* cancel any mouse-based positioning */
306                 _window->set_position (Gtk::WIN_POS_NONE);
307         }
308
309         if (_width != -1 && _height != -1) {
310                 _window->set_default_size (_width, _height);
311         }
312
313         if (_x_off != -1 && _y_off != -1) {
314                 _window->move (_x_off, _y_off);
315         }
316 }
317