fix OSX compilation
[ardour.git] / gtk2_ardour / ardour_ui_dialogs.cc
index d40195b303dc7fc831b85e528255152a5ea0ee94..e372c1e7fdf59f3b106fd1825f8b490b827cee0a 100644 (file)
 #include "ardour/control_protocol_manager.h"
 #include "ardour/profile.h"
 #include "ardour/session.h"
+
 #include "control_protocol/control_protocol.h"
 
+#include "gtkmm2ext/keyboard.h"
+#include "gtkmm2ext/utils.h"
+
 #include "actions.h"
 #include "add_route_dialog.h"
 #include "add_video_dialog.h"
 #include "gui_thread.h"
 #include "keyeditor.h"
 #include "location_ui.h"
+#include "lua_script_manager.h"
+#include "luawindow.h"
 #include "main_clock.h"
 #include "meterbridge.h"
 #include "meter_patterns.h"
+#include "monitor_section.h"
 #include "midi_tracer.h"
 #include "mixer_ui.h"
 #include "public_editor.h"
+#include "processor_box.h"
 #include "rc_option_editor.h"
 #include "route_params_ui.h"
 #include "shuttle_control.h"
@@ -62,9 +70,7 @@
 #include "time_info_box.h"
 #include "timers.h"
 
-#include <gtkmm2ext/keyboard.h>
-
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace ARDOUR;
 using namespace PBD;
@@ -326,6 +332,198 @@ ARDOUR_UI::unload_session (bool hide_stuff)
        return 0;
 }
 
+void
+ARDOUR_UI::toggle_editor_and_mixer ()
+{
+       if (editor->tabbed() && mixer->tabbed()) {
+               /* both in the same window */
+               if (_tabs.get_current_page() == _tabs.page_num (editor->contents())) {
+                       _tabs.set_current_page (_tabs.page_num (mixer->contents()));
+               } else if (_tabs.get_current_page() == _tabs.page_num (mixer->contents())) {
+                       _tabs.set_current_page (_tabs.page_num (editor->contents()));
+               } else {
+                       /* go to mixer */
+                       _tabs.set_current_page (_tabs.page_num (mixer->contents()));
+               }
+               return;
+       }
+
+
+       if (editor->tabbed() && !mixer->tabbed()) {
+               /* editor is tabbed, mixer is not */
+
+               Gtk::Window* mwin = mixer->current_toplevel ();
+
+               if (!mwin) {
+                       /* mixer's own window doesn't exist */
+                       mixer->make_visible ();
+               } else if (!mwin->is_mapped ()) {
+                       /* mixer's own window exists but isn't mapped */
+                       mixer->make_visible ();
+               } else {
+                       /* mixer window is mapped, editor is visible as tab */
+                       Gtk::Widget* f = mwin->get_focus();
+                       if (f && f->has_focus()) {
+                               /* mixer has focus, switch to editor */
+                               editor->make_visible ();
+                       } else {
+                               mixer->make_visible ();
+                       }
+               }
+               return;
+       }
+
+       if (!editor->tabbed() && mixer->tabbed()) {
+               /* mixer is tabbed, editor is not */
+
+               Gtk::Window* ewin = editor->current_toplevel ();
+
+               if (!ewin) {
+                       /* mixer's own window doesn't exist */
+                       editor->make_visible ();
+               } else if (!ewin->is_mapped ()) {
+                       /* editor's own window exists but isn't mapped */
+                       editor->make_visible ();
+               } else {
+                       /* editor window is mapped, mixer is visible as tab */
+                       Gtk::Widget* f = ewin->get_focus();
+                       if (f && f->has_focus()) {
+                               /* editor has focus, switch to mixer */
+                               mixer->make_visible ();
+                       } else {
+                               editor->make_visible ();
+                       }
+               }
+               return;
+       }
+}
+
+void
+ARDOUR_UI::step_up_through_tabs ()
+{
+       std::vector<Tabbable*> candidates;
+
+       /* this list must match the order of visibility buttons */
+
+       if (!editor->window_visible()) {
+               candidates.push_back (editor);
+       }
+
+       if (!mixer->window_visible()) {
+               candidates.push_back (mixer);
+       }
+
+       if (!rc_option_editor->window_visible()) {
+               candidates.push_back (rc_option_editor);
+       }
+
+       if (candidates.size() < 2) {
+               /* nothing to be done with zero or one visible in tabs */
+               return;
+       }
+
+       std::vector<Tabbable*>::iterator prev = candidates.end();
+       std::vector<Tabbable*>::iterator i;
+       Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
+
+       for (i = candidates.begin(); i != candidates.end(); ++i) {
+               if (w == &(*i)->contents()) {
+                       if (prev != candidates.end()) {
+                               _tabs.set_current_page (_tabs.page_num ((*prev)->contents()));
+                       } else {
+                               _tabs.set_current_page (_tabs.page_num (candidates.back()->contents()));
+                       }
+                       return;
+               }
+               prev = i;
+       }
+}
+
+void
+ARDOUR_UI::step_down_through_tabs ()
+{
+       std::vector<Tabbable*> candidates;
+
+       /* this list must match the order of visibility buttons */
+
+       if (!editor->window_visible()) {
+               candidates.push_back (editor);
+       }
+
+       if (!mixer->window_visible()) {
+               candidates.push_back (mixer);
+       }
+
+       if (!rc_option_editor->window_visible()) {
+               candidates.push_back (rc_option_editor);
+       }
+
+       if (candidates.size() < 2) {
+               /* nothing to be done with zero or one visible in tabs */
+               return;
+       }
+
+       std::vector<Tabbable*>::reverse_iterator next = candidates.rend();
+       std::vector<Tabbable*>::reverse_iterator i;
+       Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
+
+       for (i = candidates.rbegin(); i != candidates.rend(); ++i) {
+               if (w == &(*i)->contents()) {
+                       if (next != candidates.rend()) {
+                               _tabs.set_current_page (_tabs.page_num ((*next)->contents()));
+                       } else {
+                               _tabs.set_current_page (_tabs.page_num (candidates.front()->contents()));
+                       }
+                       break;
+               }
+               next = i;
+       }
+}
+
+void
+ARDOUR_UI::key_change_tabbable_visibility (Tabbable* t)
+{
+       if (!t) {
+               return;
+       }
+
+       if (t->tabbed()) {
+               _tabs.set_current_page (_tabs.page_num (t->contents()));
+       } else if (!t->fully_visible()) {
+               t->make_visible ();
+       } else {
+               _main_window.present ();
+       }
+}
+
+void
+ARDOUR_UI::button_change_tabbable_visibility (Tabbable* t)
+{
+       /* For many/most users, clicking a button in the main window will make it
+          the main/front/key window, which will change any stacking relationship they
+          were trying to modify by clicking on the button in the first
+          place. This button-aware method knows that click on
+          a button designed to show/hide a Tabbable that has its own window
+          will have made that window be obscured (as the main window comes to
+          the front). We therefore *hide* the Tabbable's window if it is even
+          partially visible, believing that this is likely because the
+          Tabbable window used to be front, the user clicked to change that,
+          and before we even get here, the main window has become front.
+       */
+
+       if (!t) {
+               return;
+       }
+
+       if (t->tabbed()) {
+               _tabs.set_current_page (_tabs.page_num (t->contents()));
+       } else if (t->visible()) {
+               t->hide();
+       } else {
+               t->make_visible ();
+       }
+}
+
 void
 ARDOUR_UI::show_tabbable (Tabbable* t)
 {
@@ -364,33 +562,78 @@ ARDOUR_UI::detach_tabbable (Tabbable* t)
        t->detach ();
 }
 
+void
+ARDOUR_UI::tabs_page_added (Widget*,guint)
+{
+       if (_tabs.get_n_pages() > 1) {
+
+               std::vector<TargetEntry> drag_target_entries;
+               drag_target_entries.push_back (TargetEntry ("tabbable"));
+
+               editor_visibility_button.drag_source_set (drag_target_entries);
+               mixer_visibility_button.drag_source_set (drag_target_entries);
+               prefs_visibility_button.drag_source_set (drag_target_entries);
+
+               editor_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (editor->name(),
+                                                                                             Pango::FontDescription ("Sans 24"),
+                                                                                             0, 0,
+                                                                                             Gdk::Color ("red")));
+               mixer_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (mixer->name(),
+                                                                                            Pango::FontDescription ("Sans 24"),
+                                                                                            0, 0,
+                                                                                            Gdk::Color ("red")));
+               prefs_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (rc_option_editor->name(),
+                                                                                            Pango::FontDescription ("Sans 24"),
+                                                                                            0, 0,
+                                                                                            Gdk::Color ("red")));
+       }
+}
+
+void
+ARDOUR_UI::tabs_page_removed (Widget*, guint)
+{
+       if (_tabs.get_n_pages() < 2) {
+               editor_visibility_button.drag_source_unset ();
+               mixer_visibility_button.drag_source_unset ();
+               prefs_visibility_button.drag_source_unset ();
+       }
+}
+
 void
 ARDOUR_UI::tabs_switch (GtkNotebookPage*, guint page)
 {
-       if (page == (guint) _tabs.page_num (editor->contents())) {
+       if (editor && (page == (guint) _tabs.page_num (editor->contents()))) {
                editor_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
+
                if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
                        mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
                }
+
                if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
                        prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
                }
-       } else if (page == (guint) _tabs.page_num (mixer->contents())) {
+       } else if (mixer && (page == (guint) _tabs.page_num (mixer->contents()))) {
+
                if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
                        editor_visibility_button.set_active_state (Gtkmm2ext::Off);
                }
+
                mixer_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
 
                if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
                        prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
                }
-       } else {
+
+       } else if (page == (guint) _tabs.page_num (rc_option_editor->contents())) {
+
                if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
                        editor_visibility_button.set_active_state (Gtkmm2ext::Off);
                }
+
                if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
                        mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
                }
+
                prefs_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
        }
 
@@ -484,7 +727,7 @@ ARDOUR_UI::tabbable_state_change (Tabbable& t)
                vis_button = &mixer_visibility_button;
                other_vis_buttons.push_back (&editor_visibility_button);
                other_vis_buttons.push_back (&prefs_visibility_button);
-       } else {
+       } else if (&t == rc_option_editor) {
                vis_button = &prefs_visibility_button;
                other_vis_buttons.push_back (&editor_visibility_button);
                other_vis_buttons.push_back (&mixer_visibility_button);
@@ -505,6 +748,10 @@ ARDOUR_UI::tabbable_state_change (Tabbable& t)
                vis_button->set_active_state (Gtkmm2ext::Off);
                break;
        }
+
+       for (std::vector<ArdourButton*>::iterator b = other_vis_buttons.begin(); b != other_vis_buttons.end(); ++b) {
+               (*b)->set_active_state (Gtkmm2ext::Off);
+       }
 }
 
 void
@@ -522,7 +769,8 @@ ARDOUR_UI::toggle_meterbridge ()
                obscuring = true;
        }
 
-       if (obscuring && (editor->own_window()->property_has_toplevel_focus() || (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
+       if (obscuring && ((editor->own_window() && editor->own_window()->property_has_toplevel_focus()) ||
+                         (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
                show = true;
        }
 
@@ -535,6 +783,28 @@ ARDOUR_UI::toggle_meterbridge ()
        }
 }
 
+void
+ARDOUR_UI::toggle_luawindow ()
+{
+       assert (editor && luawindow);
+
+       bool show = false;
+
+       if (luawindow->not_visible ()) {
+               show = true;
+       }
+       // TODO check overlap
+
+       if (show) {
+               luawindow->show_window ();
+               luawindow->present ();
+               luawindow->raise ();
+       } else {
+               luawindow->hide_window (NULL);
+       }
+}
+
+
 void
 ARDOUR_UI::new_midi_tracer_window ()
 {
@@ -564,16 +834,8 @@ ARDOUR_UI::create_key_editor ()
 {
        KeyEditor* kedit = new KeyEditor;
 
-       if (global_bindings) {
-               kedit->add_tab (_("Global"), *global_bindings);
-       }
-
-       if (editor->bindings) {
-               kedit->add_tab (_("Editing"), *editor->bindings);
-       }
-
-       if (mixer->bindings) {
-               kedit->add_tab (_("Mixing"), *mixer->bindings);
+       for (std::list<Bindings*>::iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) {
+               kedit->add_tab ((*b)->name(), **b);
        }
 
        return kedit;