first compilable version of tabbable design.
[ardour.git] / gtk2_ardour / window_manager.cc
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 #include <gtkmm/window.h>
20
21 #include "pbd/xml++.h"
22
23 #include "ardour/session_handle.h"
24
25 #include "gtkmm2ext/visibility_tracker.h"
26
27 #include "actions.h"
28 #include "ardour_dialog.h"
29 #include "ardour_window.h"
30 #include "window_manager.h"
31 #include "processor_box.h"
32
33 #include "i18n.h"
34
35 using std::string;
36 using namespace WM;
37 using namespace PBD;
38
39 Manager* Manager::_instance = 0;
40
41 Manager&
42 Manager::instance ()
43 {
44         if (!_instance) {
45                 _instance = new Manager;
46         }
47         return *_instance;
48 }
49
50 Manager::Manager ()
51         : current_transient_parent (0)
52 {
53 }
54
55 Manager::~Manager ()
56 {
57 }
58
59 void
60 Manager::register_window (ProxyBase* info)
61 {
62         _windows.push_back (info);
63
64         if (!info->menu_name().empty()) {
65
66                 if (!window_actions) {
67                         window_actions = Gtk::ActionGroup::create (X_("Window"));
68                         ActionManager::add_action_group (window_actions);
69                 }
70
71                 info->set_action (ActionManager::register_action (window_actions, info->action_name().c_str(), info->menu_name().c_str(),
72                                                                   sigc::bind (sigc::mem_fun (*this, &Manager::toggle_window), info)));
73         }
74 }
75
76 void
77 Manager::remove (const ProxyBase* info)
78 {
79         for (Windows::iterator i = _windows.begin(); i != _windows.end(); ++i) {
80                 if ((*i) == info) {
81                         _windows.erase (i);
82                         return;
83                 }
84         }
85 }
86
87 void
88 Manager::toggle_window (ProxyBase* proxy)
89 {
90         if (proxy) {
91                 proxy->toggle ();
92         }
93 }
94
95 void
96 Manager::show_visible() const
97 {
98         for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
99                 if ((*i)->visible()) {
100                         if (! (*i)->get (true)) {
101                                 /* the window may be a plugin GUI for a plugin which
102                                  * is disabled or longer present.
103                                  */
104                                 continue;
105                         }
106                         (*i)->show_all ();
107                         (*i)->present ();
108                 }
109         }
110 }
111
112 void
113 Manager::add_state (XMLNode& root) const
114 {
115         for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
116                 /* don't save state for temporary proxy windows
117                  */
118                 if (dynamic_cast<ProxyTemporary*> (*i)) {
119                         continue;
120                 }
121                 if (dynamic_cast<ProcessorWindowProxy*> (*i)) {
122                         ProcessorWindowProxy *pi = dynamic_cast<ProcessorWindowProxy*> (*i);
123                         root.add_child_nocopy (pi->get_state());
124                 } else {
125                         root.add_child_nocopy ((*i)->get_state());
126                 }
127         }
128 }
129
130 void
131 Manager::set_session (ARDOUR::Session* s)
132 {
133         SessionHandlePtr::set_session (s);
134         for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
135                 (*i)->set_session(s);
136         }
137 }
138
139 void
140 Manager::set_transient_for (Gtk::Window* parent)
141 {
142         /* OS X has a richer concept of window layering than X does (or
143          * certainly, than any accepted conventions on X), and so the use of
144          * Manager::set_transient_for() is not necessary on that platform.
145          *
146          * On OS X this is mostly taken care of by using the window type rather
147          * than explicit 1:1 transient-for relationships.
148          */
149
150 #ifndef __APPLE__
151         if (parent) {
152                 for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
153                         Gtk::Window* win = (*i)->get();
154                         if (win) {
155                                 win->set_transient_for (*parent);
156                         }
157                 }
158         } else {
159                 for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
160                         Gtk::Window* win = (*i)->get();
161                         if (win) {
162                                 gtk_window_set_transient_for (win->gobj(), 0);
163                         }
164                 }
165         }
166
167         current_transient_parent = parent;
168 #endif
169 }
170
171 /*-------------------------*/
172
173 ProxyBase::ProxyBase (const std::string& name, const std::string& menu_name)
174         : WindowProxy (name, menu_name)
175 {
176 }
177
178 ProxyBase::ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode& node)
179         : WindowProxy (name, menu_name, node)
180 {
181 }
182
183 void
184 ProxyBase::setup ()
185 {
186         WindowProxy::setup ();
187         set_session(_session);
188 }       
189
190 /*-----------------------*/
191
192 ProxyTemporary::ProxyTemporary (const string& name, Gtk::Window* win)
193         : ProxyBase (name, string())
194 {
195         _window = win;
196 }
197
198 ProxyTemporary::~ProxyTemporary ()
199 {
200 }
201
202
203 ARDOUR::SessionHandlePtr*
204 ProxyTemporary::session_handle()
205 {
206         /* may return null */
207         ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
208         if (aw) { return aw; }
209         ArdourDialog* ad = dynamic_cast<ArdourDialog*> (_window);
210         if (ad) { return ad; }
211         return 0;
212 }