get rid of a warning message by setting up the main window properties before showing it
[ardour.git] / gtk2_ardour / ardour_ui_dependents.cc
1 /*
2     Copyright (C) 2000 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 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 /* this file exists solely to break compilation dependencies that
25    would connect changes to the mixer or editor objects.
26 */
27
28 #include <cstdio>
29
30 #include "pbd/error.h"
31
32 #include "ardour/session.h"
33
34 #include "gtkmm2ext/bindings.h"
35
36 #include "actions.h"
37 #include "ardour_ui.h"
38 #include "public_editor.h"
39 #include "meterbridge.h"
40 #include "mixer_ui.h"
41 #include "keyboard.h"
42 #include "splash.h"
43 #include "rc_option_editor.h"
44 #include "route_params_ui.h"
45 #include "opts.h"
46 #include "utils.h"
47
48 #include "i18n.h"
49
50 using namespace Gtk;
51 using namespace PBD;
52
53 namespace ARDOUR {
54         class Session;
55         class Route;
56 }
57
58 using namespace ARDOUR;
59
60 void
61 ARDOUR_UI::we_have_dependents ()
62 {
63         install_actions ();
64         load_bindings ();
65
66         ProcessorBox::register_actions ();
67
68         /* Global, editor, mixer, processor box actions are defined now. Link
69            them with any bindings, so that GTK does not get a chance to define
70            the GTK accel map entries first when we ask the GtkUIManager to
71            create menus/widgets.
72
73            If GTK adds the actions to its accel map before we do, we lose our
74            freedom to use any keys. More precisely, we can use any keys, but
75            ones that GTK considers illegal as accelerators will not show up in
76            menus.
77
78            There are other dynamic actions that can be created by a monitor
79            section, by step entry dialogs. These need to be handled
80            separately. They don't tend to use GTK-illegal bindings and more
81            importantly they don't have menus showing the bindings, so it is
82            less of an issue.
83         */
84
85         Gtkmm2ext::Bindings::associate_all ();
86
87         editor->setup_tooltips ();
88         editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
89
90         /* catch up on tabbable state */
91
92         tabbable_state_change (*editor);
93         tabbable_state_change (*mixer);
94         tabbable_state_change (*rc_option_editor);
95
96         /* all actions are defined */
97
98         ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
99
100         editor->track_mixer_selection ();
101         mixer->track_editor_selection ();
102
103         /* catch up on parameters */
104
105         boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
106         Config->map_parameters (pc);
107
108         UIConfiguration::instance().reset_dpi ();
109 }
110
111 void
112 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
113 {
114         DisplaySuspender ds;
115         BootMessage (_("Setup Editor"));
116         editor->set_session (s);
117         BootMessage (_("Setup Mixer"));
118         mixer->set_session (s);
119         meterbridge->set_session (s);
120
121         /* its safe to do this now */
122
123         BootMessage (_("Reload Session History"));
124         s->restore_history ("");
125 }
126
127 /** The main editor window has been closed */
128 gint
129 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
130 {
131 #ifdef TOP_MENUBAR
132         /* just hide the window, and return - the top menu stays up */
133         editor->hide ();
134         return TRUE;
135 #else
136         /* time to get out of here */
137         finish();
138         return TRUE;
139 #endif
140 }
141
142 GtkNotebook*
143 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
144                                  GtkWidget* w,
145                                  gint x,
146                                  gint y,
147                                  gpointer)
148 {
149         using namespace std;
150         Gtk::Notebook* nb = 0;
151         Gtk::Window* win = 0;
152         Gtkmm2ext::Tabbable* tabbable = 0;
153
154
155         if (w == GTK_WIDGET(editor->contents().gobj())) {
156                 tabbable = editor;
157         } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
158                 tabbable = mixer;
159         } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
160                 tabbable = rc_option_editor;
161         } else {
162                 return 0;
163         }
164
165         nb = tabbable->tab_root_drop ();
166         win = tabbable->own_window ();
167
168         if (nb) {
169                 win->move (x, y);
170                 win->show_all ();
171                 win->present ();
172                 return nb->gobj();
173         }
174
175         return 0; /* what was that? */
176 }
177
178 bool
179 ARDOUR_UI::idle_ask_about_quit ()
180 {
181         if (_session && _session->dirty()) {
182                 finish ();
183         } else {
184                 /* no session or session not dirty, but still ask anyway */
185
186                 Gtk::MessageDialog msg (string_compose ("Quit %1?", PROGRAM_NAME),
187                                         false, /* no markup */
188                                         Gtk::MESSAGE_INFO,
189                                         Gtk::BUTTONS_YES_NO,
190                                         true); /* modal */
191                 msg.set_default_response (Gtk::RESPONSE_YES);
192
193                 if (msg.run() == Gtk::RESPONSE_YES) {
194                         finish ();
195                 }
196         }
197
198         /* not reached but keep the compiler happy */
199
200         return false;
201 }
202
203 bool
204 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
205 {
206         /* quit the application as soon as we go idle. If we call this here,
207          * the window manager/desktop can think we're taking too longer to
208          * handle the "delete" event
209          */
210
211         Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
212
213         return true;
214 }
215
216 static GtkNotebook*
217 tab_window_root_drop (GtkNotebook* src,
218                       GtkWidget* w,
219                       gint x,
220                       gint y,
221                       gpointer user_data)
222 {
223         return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
224 }
225
226 int
227 ARDOUR_UI::setup_windows ()
228 {
229         /* actions do not need to be defined when we load keybindings. They
230          * will be lazily discovered. But bindings do need to exist when we
231          * create windows/tabs with their own binding sets.
232          */
233
234         keyboard->setup_keybindings ();
235
236         _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
237         _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
238         _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
239
240         rc_option_editor = new RCOptionEditor;
241         rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
242
243         if (create_editor ()) {
244                 error << _("UI: cannot setup editor") << endmsg;
245                 return -1;
246         }
247
248         if (create_mixer ()) {
249                 error << _("UI: cannot setup mixer") << endmsg;
250                 return -1;
251         }
252
253         if (create_meterbridge ()) {
254                 error << _("UI: cannot setup meterbridge") << endmsg;
255                 return -1;
256         }
257
258         /* order of addition affects order seen in initial window display */
259
260         rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
261         mixer->add_to_notebook (_tabs, _("Mixer"));
262         editor->add_to_notebook (_tabs, _("Editor"));
263
264         /* all other dialogs are created conditionally */
265
266         we_have_dependents ();
267
268 #ifdef TOP_MENUBAR
269         EventBox* status_bar_event_box = manage (new EventBox);
270
271         status_bar_event_box->add (status_bar_label);
272         status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
273         status_bar_label.set_size_request (300, -1);
274
275         status_bar_label.show ();
276         status_bar_event_box->show ();
277
278         status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press));
279
280         status_bar_hpacker.pack_start (*status_bar_event_box, true, true, 6);
281         status_bar_hpacker.pack_start (menu_bar_base, false, false, 2);
282 #else
283         top_packer.pack_start (menu_bar_base, false, false);
284 #endif
285
286         main_vpacker.pack_start (top_packer, false, false);
287
288         /* now add the transport frame to the top of main window */
289
290         main_vpacker.pack_start (transport_frame, false, false);
291         main_vpacker.pack_start (_tabs, true, true);
292
293 #ifdef TOP_MENUBAR
294         main_vpacker.pack_start (status_bar_hpacker, false, false);
295 #endif
296
297         setup_transport();
298         build_menu_bar ();
299         setup_tooltips ();
300
301         _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
302
303         /* pack the main vpacker into the main window and show everything
304          */
305
306         _main_window.add (main_vpacker);
307         transport_frame.show_all ();
308
309         const XMLNode* mnode = main_window_settings ();
310
311         if (mnode) {
312                 const XMLProperty* prop;
313                 gint x = -1;
314                 gint y = -1;
315                 gint w = -1;
316                 gint h = -1;
317
318                 if ((prop = mnode->property (X_("x"))) != 0) {
319                         x = atoi (prop->value());
320                 }
321
322                 if ((prop = mnode->property (X_("y"))) != 0) {
323                         y = atoi (prop->value());
324                 }
325
326                 if ((prop = mnode->property (X_("w"))) != 0) {
327                         w = atoi (prop->value());
328                 }
329
330                 if ((prop = mnode->property (X_("h"))) != 0) {
331                         h = atoi (prop->value());
332                 }
333
334                 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
335                         _main_window.set_position (Gtk::WIN_POS_NONE);
336                 }
337
338                 if (x >= 0 && y >= 0) {
339                         _main_window.move (x, y);
340                 }
341
342                 if (w > 0 && h > 0) {
343                         _main_window.set_default_size (w, h);
344                 }
345
346                 std::string current_tab;
347
348                 if ((prop = mnode->property (X_("current-tab"))) != 0) {
349                         current_tab = prop->value();
350                 } else {
351                         current_tab = "editor";
352                 }
353                 if (mixer && current_tab == "mixer") {
354                         _tabs.set_current_page (_tabs.page_num (mixer->contents()));
355                 } else if (rc_option_editor && current_tab == "preferences") {
356                         _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
357                 } else if (editor) {
358                         _tabs.set_current_page (_tabs.page_num (editor->contents()));
359                 }
360         }
361
362         setup_toplevel_window (_main_window, "", this);
363         _main_window.show_all ();
364
365         _tabs.set_show_tabs (false);
366
367         /* It would be nice if Gtkmm had wrapped this rather than just
368          * deprecating the old set_window_creation_hook() method, but oh well...
369          */
370         g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
371
372         return 0;
373 }