diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2013-05-04 22:41:10 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2013-05-04 22:41:10 -0400 |
commit | e1b0f1bd0b03c071d2b5987e4ab75ef059e32111 (patch) | |
tree | af840860a892166cae1c1a97cb9285ab9e4523f2 /gtk2_ardour | |
parent | 2fd62f25b3202b4aa94a4afd19e9233a003f877a (diff) | |
parent | 40944574c620868b43872f64600a8a42d382a6a1 (diff) |
merge with master
Diffstat (limited to 'gtk2_ardour')
34 files changed, 1200 insertions, 1163 deletions
diff --git a/gtk2_ardour/about.h b/gtk2_ardour/about.h index dfd7213aa7..689a92d8e9 100644 --- a/gtk2_ardour/about.h +++ b/gtk2_ardour/about.h @@ -22,9 +22,11 @@ #include <gtkmm/aboutdialog.h> +#include "ardour/session_handle.h" + class ConfigInfoDialog; -class About : public Gtk::AboutDialog +class About : public Gtk::AboutDialog, public ARDOUR::SessionHandlePtr { public: About (); diff --git a/gtk2_ardour/add_route_dialog.cc b/gtk2_ardour/add_route_dialog.cc index d039f67c0e..e0e5c70798 100644 --- a/gtk2_ardour/add_route_dialog.cc +++ b/gtk2_ardour/add_route_dialog.cc @@ -49,7 +49,7 @@ using namespace ARDOUR; std::vector<std::string> AddRouteDialog::channel_combo_strings; -AddRouteDialog::AddRouteDialog (Session* s) +AddRouteDialog::AddRouteDialog () : ArdourDialog (_("Add Track or Bus")) , routes_adjustment (1, 1, 128, 1, 4) , routes_spinner (routes_adjustment) @@ -57,8 +57,6 @@ AddRouteDialog::AddRouteDialog (Session* s) , mode_label (_("Track mode:")) , instrument_label (_("Instrument:")) { - set_session (s); - set_name ("AddRouteDialog"); set_modal (true); set_skip_taskbar_hint (true); @@ -496,7 +494,7 @@ AddRouteDialog::add_route_group (RouteGroup* g) RouteGroup* AddRouteDialog::route_group () { - if (route_group_combo.get_active_row_number () == 2) { + if (!_session || route_group_combo.get_active_row_number () == 2) { return 0; } @@ -513,7 +511,9 @@ AddRouteDialog::refill_route_groups () route_group_combo.append_text (_("No Group")); - _session->foreach_route_group (sigc::mem_fun (*this, &AddRouteDialog::add_route_group)); + if (_session) { + _session->foreach_route_group (sigc::mem_fun (*this, &AddRouteDialog::add_route_group)); + } route_group_combo.set_active (2); } @@ -534,7 +534,9 @@ AddRouteDialog::group_changed () delete g; route_group_combo.set_active (2); } else { - _session->add_route_group (g); + if (_session) { + _session->add_route_group (g); + } add_route_group (g); route_group_combo.set_active (3); } diff --git a/gtk2_ardour/add_route_dialog.h b/gtk2_ardour/add_route_dialog.h index 6fe7266452..31b746ac76 100644 --- a/gtk2_ardour/add_route_dialog.h +++ b/gtk2_ardour/add_route_dialog.h @@ -45,7 +45,7 @@ class Editor; class AddRouteDialog : public ArdourDialog { public: - AddRouteDialog (ARDOUR::Session*); + AddRouteDialog (); ~AddRouteDialog (); enum TypeWanted { diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index 0279384fb5..5b10a4f2c2 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -50,10 +50,10 @@ #ifndef GTKOSX <separator/> #endif - <menuitem action='ToggleSessionOptionsEditor'/> + <menuitem action='toggle-session-options-editor'/> #ifdef GTKOSX - <menuitem action='ToggleRCOptionsEditor'/> - <menuitem action='About'/> + <menuitem action='toggle-rc-options-editor'/> + <menuitem action='toggle-about'/> #endif <separator/> <menuitem action='Quit'/> @@ -231,7 +231,7 @@ <menuitem action='set-mouse-mode-object-range'/> #ifndef GTKOSX <separator/> - <menuitem action='ToggleRCOptionsEditor'/> + <menuitem action='toggle-rc-options-editor'/> #endif </menu> @@ -510,12 +510,12 @@ <separator/> - <menuitem action='ToggleInspector'/> - <menuitem action='ToggleLocations'/> - <menuitem action='ToggleKeyEditor'/> - <menuitem action='ToggleBundleManager'/> - <menuitem action='ToggleThemeManager'/> - <menuitem action='ToggleBigClock'/> + <menuitem action='toggle-inspector'/> + <menuitem action='toggle-locations'/> + <menuitem action='toggle-key-editor'/> + <menuitem action='toggle-bundle-manager'/> + <menuitem action='toggle-theme-manager'/> + <menuitem action='toggle-big-clock'/> <menuitem action='toggle-speaker-config'/> <separator/> @@ -531,7 +531,7 @@ </menu> <menu name='Help' action='Help'> #ifndef GTKOSX - <menuitem action='About'/> + <menuitem action='toggle-about'/> #endif <menuitem action='Chat'/> <menuitem action='Manual'/> diff --git a/gtk2_ardour/ardour_dialog.cc b/gtk2_ardour/ardour_dialog.cc index 87b48d986a..cd7d0fbd55 100644 --- a/gtk2_ardour/ardour_dialog.cc +++ b/gtk2_ardour/ardour_dialog.cc @@ -23,6 +23,7 @@ #include <gtkmm2ext/doi.h> #include "ardour_dialog.h" +#include "ardour_ui.h" #include "keyboard.h" #include "splash.h" @@ -30,8 +31,6 @@ using namespace std; using namespace Gtk; using namespace Gtkmm2ext; -sigc::signal<void> ArdourDialog::CloseAllDialogs; - ArdourDialog::ArdourDialog (string title, bool modal, bool use_seperator) : Dialog (title, modal, use_seperator) , _splash_pushed (false) @@ -98,9 +97,7 @@ ArdourDialog::on_show () void ArdourDialog::init () { - set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG); set_border_width (10); - CloseAllDialogs.connect ( - sigc::bind (sigc::mem_fun (*this, &ArdourDialog::response), - RESPONSE_CANCEL)); + // set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG); + ARDOUR_UI::CloseAllDialogs.connect (sigc::bind (sigc::mem_fun (*this, &ArdourDialog::response), RESPONSE_CANCEL)); } diff --git a/gtk2_ardour/ardour_dialog.h b/gtk2_ardour/ardour_dialog.h index 1008f63000..041b62e1cd 100644 --- a/gtk2_ardour/ardour_dialog.h +++ b/gtk2_ardour/ardour_dialog.h @@ -43,8 +43,6 @@ class ArdourDialog : public Gtk::Dialog, public ARDOUR::SessionHandlePtr void on_unmap (); void on_show (); - static void close_all_dialogs () { CloseAllDialogs(); } - private: bool _splash_pushed; void init (); diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index c138fb1567..1d08d65215 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -21,18 +21,19 @@ #include "gtk2ardour-config.h" #endif -#include <stdint.h> - #include <algorithm> #include <cmath> +#include <iostream> +#include <cerrno> +#include <fstream> + +#include <boost/locale.hpp> + +#include <stdint.h> #include <fcntl.h> #include <signal.h> #include <unistd.h> #include <time.h> -#include <cerrno> -#include <fstream> - -#include <iostream> #include <sys/resource.h> #include <sys/types.h> @@ -88,6 +89,7 @@ typedef uint64_t microseconds_t; #include "ambiguous_file_dialog.h" #include "ardour_ui.h" #include "audio_clock.h" +#include "big_clock_window.h" #include "bundle_manager.h" #include "engine_dialog.h" #include "gain_meter.h" @@ -95,6 +97,7 @@ typedef uint64_t microseconds_t; #include "gui_object.h" #include "gui_thread.h" #include "keyboard.h" +#include "keyeditor.h" #include "location_ui.h" #include "main_clock.h" #include "missing_file_dialog.h" @@ -106,8 +109,11 @@ typedef uint64_t microseconds_t; #include "processor_box.h" #include "prompter.h" #include "public_editor.h" +#include "rc_option_editor.h" #include "route_time_axis.h" +#include "route_params_ui.h" #include "session_metadata_dialog.h" +#include "session_option_editor.h" #include "shuttle_control.h" #include "speaker_dialog.h" #include "splash.h" @@ -115,7 +121,6 @@ typedef uint64_t microseconds_t; #include "theme_manager.h" #include "time_axis_view_item.h" #include "utils.h" -#include "window_proxy.h" #include "video_server_dialog.h" #include "add_video_dialog.h" #include "transcode_video_dialog.h" @@ -136,6 +141,7 @@ sigc::signal<void,bool> ARDOUR_UI::Blink; sigc::signal<void> ARDOUR_UI::RapidScreenUpdate; sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate; sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock; +sigc::signal<void> ARDOUR_UI::CloseAllDialogs; ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) @@ -167,6 +173,21 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , solo_alert_button (_("solo")) , feedback_alert_button (_("feedback")) + , speaker_config_window (X_("speaker-config"), _("Speaker Configuration")) + , theme_manager (X_("theme-manager"), _("Theme Manager")) + , key_editor (X_("key-editor"), _("Key Bindings")) + , rc_option_editor (X_("rc-options-editor"), _("Preferences")) + , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses")) + , about (X_("about"), _("About")) + , location_ui (X_("locations"), _("Locations")) + , route_params (X_("inspector"), _("Tracks and Busses")) + , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this)) + , add_video_dialog (X_("add-video"), _("Add Tracks/Busses"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this)) + , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this)) + , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this)) + , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO)) + , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI)) + , error_log_button (_("Errors")) , _status_bar_visibility (X_("status-bar")) @@ -175,7 +196,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) { Gtkmm2ext::init(localedir); - about = 0; splash = 0; _startup = 0; @@ -184,36 +204,20 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) } ui_config = new UIConfiguration(); - theme_manager = new ThemeManager(); - - key_editor = 0; editor = 0; mixer = 0; editor = 0; engine = 0; _session_is_new = false; - big_clock_window = 0; - big_clock_height = 0; - big_clock_resize_in_progress = false; session_selector_window = 0; last_key_press_time = 0; - add_route_dialog = 0; - add_video_dialog = 0; video_server_process = 0; - route_params = 0; - bundle_manager = 0; - rc_option_editor = 0; - session_option_editor = 0; - location_ui = 0; open_session_selector = 0; have_configure_timeout = false; have_disk_speed_dialog_displayed = false; session_loaded = false; ignore_dual_punch = false; - original_big_clock_width = -1; - original_big_clock_height = -1; - original_big_clock_font_size = 0; roll_button.set_controllable (roll_controllable); stop_button.set_controllable (stop_controllable); @@ -307,26 +311,53 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) TimeAxisViewItem::set_constant_heights (); - /* The following must happen after ARDOUR::init() so that Config is set up */ - - location_ui = new ActionWindowProxy<LocationUIWindow> (X_("locations"), Config->extra_xml (X_("UI")), X_("ToggleLocations")); - big_clock_window = new ActionWindowProxy<Gtk::Window> (X_("bigclock"), Config->extra_xml (X_("UI")), X_("ToggleBigClock")); - speaker_config_window = new ActionWindowProxy<SpeakerDialog> (X_("speakerconf"), Config->extra_xml (X_("UI")), X_("toggle-speaker-config")); - - for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) { - _global_port_matrix[*i] = new ActionWindowProxy<GlobalPortMatrixWindow> ( - string_compose ("GlobalPortMatrix-%1", (*i).to_string()), - Config->extra_xml (X_("UI")), - string_compose ("toggle-%1-connection-manager", (*i).to_string()) - ); - } + /* load up the UI manager */ - setup_clock (); + ActionManager::init (); - SpeakerDialog* s = new SpeakerDialog (); - s->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/toggle-speaker-config"))); - speaker_config_window->set (s); + /* The following must happen after ARDOUR::init() so that Config is set up */ + const XMLNode* ui_xml = Config->extra_xml (X_("UI")); + + if (ui_xml) { + theme_manager.set_state (*ui_xml); + key_editor.set_state (*ui_xml); + rc_option_editor.set_state (*ui_xml); + session_option_editor.set_state (*ui_xml); + speaker_config_window.set_state (*ui_xml); + about.set_state (*ui_xml); + add_route_dialog.set_state (*ui_xml); + add_video_dialog.set_state (*ui_xml); + route_params.set_state (*ui_xml); + bundle_manager.set_state (*ui_xml); + location_ui.set_state (*ui_xml); + big_clock_window.set_state (*ui_xml); + audio_port_matrix.set_state (*ui_xml); + midi_port_matrix.set_state (*ui_xml); + } + + WindowManager::instance().register_window (&theme_manager); + WindowManager::instance().register_window (&key_editor); + WindowManager::instance().register_window (&rc_option_editor); + WindowManager::instance().register_window (&session_option_editor); + WindowManager::instance().register_window (&speaker_config_window); + WindowManager::instance().register_window (&about); + WindowManager::instance().register_window (&add_route_dialog); + WindowManager::instance().register_window (&add_video_dialog); + WindowManager::instance().register_window (&route_params); + WindowManager::instance().register_window (&bundle_manager); + WindowManager::instance().register_window (&location_ui); + WindowManager::instance().register_window (&big_clock_window); + WindowManager::instance().register_window (&audio_port_matrix); + WindowManager::instance().register_window (&midi_port_matrix); + + /* We need to instantiate the theme manager because it loads our + theme files. This should really change so that its window + and its functionality are separate + */ + + (void) theme_manager.get (true); + starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup)); stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown)); @@ -336,6 +367,14 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets)); } +GlobalPortMatrixWindow* +ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type) +{ + if (!_session) { + return 0; + } + return new GlobalPortMatrixWindow (_session, type); +} int ARDOUR_UI::create_engine () @@ -377,10 +416,6 @@ ARDOUR_UI::post_engine () ARDOUR::init_post_engine (); - /* load up the UI manager */ - - ActionManager::init (); - _tooltips.enable(); if (setup_windows ()) { @@ -466,10 +501,7 @@ ARDOUR_UI::~ARDOUR_UI () delete keyboard; delete editor; delete mixer; - delete add_route_dialog; - if (add_video_dialog) { - delete add_video_dialog; - } + stop_video_server(); } @@ -714,14 +746,7 @@ ARDOUR_UI::startup () goto_editor_window (); - /* Add the window proxies here; their addition may cause windows to be opened, and we want them - to be opened on top of the editor window that goto_editor_window() just opened. - */ - add_window_proxy (location_ui); - add_window_proxy (big_clock_window); - for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) { - add_window_proxy (_global_port_matrix[*i]); - } + WindowManager::instance().show_visible (); /* We have to do this here since goto_editor_window() ends up calling show_all() on the * editor window, and we may want stuff to be hidden. @@ -876,6 +901,8 @@ If you still wish to quit, please use the\n\n\ */ save_ardour_state (); + close_all_dialogs (); + loading_message (string_compose (_("Please wait while %1 cleans up..."), PROGRAM_NAME)); if (_session) { @@ -886,7 +913,6 @@ If you still wish to quit, please use the\n\n\ _session = 0; } - ArdourDialog::close_all_dialogs (); engine->stop (true); quit (); } @@ -2303,11 +2329,7 @@ ARDOUR_UI::save_state (const string & name, bool switch_to_it) { XMLNode* node = new XMLNode (X_("UI")); - for (list<WindowProxyBase*>::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) { - if (!(*i)->rc_configured()) { - node->add_child_nocopy (*((*i)->get_state ())); - } - } + WindowManager::instance().add_state (*node); node->add_child_nocopy (gui_object_state->get_state()); @@ -2943,18 +2965,6 @@ ARDOUR_UI::launch_chat () } void -ARDOUR_UI::show_about () -{ - if (about == 0) { - about = new About; - about->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response)); - } - - about->set_transient_for(*editor); - about->show_all (); -} - -void ARDOUR_UI::launch_manual () { PBD::open_uri (Config->get_tutorial_manual_url()); @@ -2967,21 +2977,6 @@ ARDOUR_UI::launch_reference () } void -ARDOUR_UI::hide_about () -{ - if (about) { - about->get_window()->set_cursor (); - about->hide (); - } -} - -void -ARDOUR_UI::about_signal_response (int /*response*/) -{ - hide_about(); -} - -void ARDOUR_UI::loading_message (const std::string& msg) { if (ARDOUR_COMMAND_LINE::no_splash) { @@ -3241,18 +3236,15 @@ ARDOUR_UI::add_route (Gtk::Window* float_window) return; } - if (add_route_dialog == 0) { - add_route_dialog = new AddRouteDialog (_session); - if (float_window) { - add_route_dialog->set_transient_for (*float_window); - } - } - if (add_route_dialog->is_visible()) { /* we're already doing this */ return; } + if (float_window) { + add_route_dialog->set_transient_for (*float_window); + } + ResponseType r = (ResponseType) add_route_dialog->run (); add_route_dialog->hide(); @@ -3443,17 +3435,15 @@ ARDOUR_UI::add_video (Gtk::Window* float_window) return; } - if (add_video_dialog == 0) { - add_video_dialog = new AddVideoDialog (_session); - if (float_window) { - add_video_dialog->set_transient_for (*float_window); - } + if (float_window) { + add_video_dialog->set_transient_for (*float_window); } if (add_video_dialog->is_visible()) { /* we're already doing this */ return; } + ResponseType r = (ResponseType) add_video_dialog->run (); add_video_dialog->hide(); if (r != RESPONSE_ACCEPT) { return; } @@ -3828,13 +3818,12 @@ ARDOUR_UI::update_transport_clocks (framepos_t pos) secondary_clock->set (pos); } - if (big_clock_window->get()) { + if (big_clock_window) { big_clock->set (pos); } ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos); } - void ARDOUR_UI::step_edit_status_change (bool yn) { @@ -3855,7 +3844,7 @@ ARDOUR_UI::record_state_changed () { ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed); - if (!_session || !big_clock_window->get()) { + if (!_session || !big_clock_window) { /* why bother - the clock isn't visible */ return; } @@ -3994,26 +3983,6 @@ ARDOUR_UI::setup_profile () } } -/** Add a window proxy to our list, so that its state will be saved. - * This call also causes the window to be created and opened if its - * state was saved as `visible'. - */ -void -ARDOUR_UI::add_window_proxy (WindowProxyBase* p) -{ - _window_proxies.push_back (p); - p->maybe_show (); -} - -/** Remove a window proxy from our list. Must be called if a WindowProxy - * is deleted, to prevent hanging pointers. - */ -void -ARDOUR_UI::remove_window_proxy (WindowProxyBase* p) -{ - _window_proxies.remove (p); -} - int ARDOUR_UI::missing_file (Session*s, std::string str, DataType type) { diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 42ce5d5863..c580209d4b 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -66,14 +66,15 @@ #include "video_timeline.h" -#include "ardour_dialog.h" #include "ardour_button.h" +#include "ardour_dialog.h" +#include "ardour_window.h" #include "editing.h" #include "nsm.h" #include "ui_config.h" -#include "window_proxy.h" #include "enums.h" #include "visibility_group.h" +#include "window_manager.h" class About; class AddRouteDialog; @@ -83,6 +84,7 @@ class SystemExec; class ArdourStartup; class ArdourKeyboard; class AudioClock; +class BigClockWindow; class BundleManager; class ButtonJoiner; class ConnectionEditor; @@ -100,7 +102,6 @@ class SpeakerDialog; class ThemeManager; class TimeInfoBox; class MidiTracer; -class WindowProxyBase; class GlobalPortMatrixWindow; class GUIObjectState; @@ -164,14 +165,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr PublicEditor& the_editor(){return *editor;} Mixer_UI* the_mixer() { return mixer; } - void toggle_key_editor (); - void toggle_location_window (); - void toggle_theme_manager (); - void toggle_bundle_manager (); - void toggle_big_clock_window (); - void toggle_speaker_config_window (); void new_midi_tracer_window (); - void toggle_route_params_window (); void toggle_editing_space(); void toggle_keep_tearoffs(); @@ -188,6 +182,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr */ static sigc::signal<void, framepos_t, bool, framepos_t> Clock; + static void close_all_dialogs () { CloseAllDialogs(); } + static sigc::signal<void> CloseAllDialogs; + XMLNode* editor_settings() const; XMLNode* mixer_settings () const; XMLNode* keyboard_settings () const; @@ -205,6 +202,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr MainClock* primary_clock; MainClock* secondary_clock; void focus_on_clock (); + AudioClock* big_clock; TimeInfoBox* time_info_box; @@ -271,9 +269,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void set_shuttle_fract (double); - void add_window_proxy (WindowProxyBase *); - void remove_window_proxy (WindowProxyBase *); - void get_process_buffers (); void drop_process_buffers (); @@ -354,25 +349,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void manage_window (Gtk::Window&); - AudioClock* big_clock; - ActionWindowProxy<Gtk::Window>* big_clock_window; - int original_big_clock_width; - int original_big_clock_height; - double original_big_clock_font_size; - - void big_clock_size_allocate (Gtk::Allocation&); - bool idle_big_clock_text_resizer (int width, int height); - void big_clock_realized (); - bool big_clock_resize_in_progress; - int big_clock_height; - void big_clock_catch_focus (); - void big_clock_reset_aspect_ratio (); - - void float_big_clock (Gtk::Window* parent); bool main_window_state_event_handler (GdkEventWindowState*, bool window_was_editor); - ActionWindowProxy<SpeakerDialog>* speaker_config_window; - void update_transport_clocks (framepos_t pos); void record_state_changed (); @@ -592,41 +570,40 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr PublicEditor *editor; int create_editor (); - RouteParams_UI *route_params; - int create_route_params (); + /* Dialogs that can be created via new<T> */ - BundleManager *bundle_manager; - void create_bundle_manager (); + WindowManager::Proxy<SpeakerDialog> speaker_config_window; + WindowManager::Proxy<ThemeManager> theme_manager; + WindowManager::Proxy<KeyEditor> key_editor; + WindowManager::Proxy<RCOptionEditor> rc_option_editor; + WindowManager::Proxy<AddRouteDialog> add_route_dialog; + WindowManager::Proxy<About> about; + WindowManager::Proxy<LocationUIWindow> location_ui; + WindowManager::Proxy<RouteParams_UI> route_params; - ActionWindowProxy<LocationUIWindow>* location_ui; - int create_location_ui (); - void handle_locations_change (ARDOUR::Location*); + /* Windows/Dialogs that require a creator method */ - ActionWindowProxy<GlobalPortMatrixWindow>* _global_port_matrix[ARDOUR::DataType::num_types]; - void toggle_global_port_matrix (ARDOUR::DataType); - - static UIConfiguration *ui_config; - ThemeManager *theme_manager; + WindowManager::ProxyWithConstructor<SessionOptionEditor> session_option_editor; + WindowManager::ProxyWithConstructor<AddVideoDialog> add_video_dialog; + WindowManager::ProxyWithConstructor<BundleManager> bundle_manager; + WindowManager::ProxyWithConstructor<BigClockWindow> big_clock_window; + WindowManager::ProxyWithConstructor<GlobalPortMatrixWindow> audio_port_matrix; + WindowManager::ProxyWithConstructor<GlobalPortMatrixWindow> midi_port_matrix; - /* Key bindings editor */ + /* creator methods */ - KeyEditor *key_editor; + SessionOptionEditor* create_session_option_editor (); + BundleManager* create_bundle_manager (); + AddVideoDialog* create_add_video_dialog (); + BigClockWindow* create_big_clock_window(); + GlobalPortMatrixWindow* create_global_port_matrix (ARDOUR::DataType); - /* RC Options window */ - - RCOptionEditor *rc_option_editor; - - SessionOptionEditor *session_option_editor; - - /* route dialog */ - - AddRouteDialog *add_route_dialog; - - /* video dialog */ + static UIConfiguration *ui_config; - AddVideoDialog *add_video_dialog; SystemExec *video_server_process; + void handle_locations_change (ARDOUR::Location*); + /* Keyboard Handling */ ArdourKeyboard* keyboard; @@ -640,7 +617,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr uint32_t rec_enabled_streams; void count_recenabled_streams (ARDOUR::Route&); - About* about; Splash* splash; void pop_back_splash (Gtk::Window&); @@ -726,8 +702,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void queue_finish (); void fontconfig_dialog (); - std::list<WindowProxyBase*> _window_proxies; - int missing_file (ARDOUR::Session*s, std::string str, ARDOUR::DataType type); int ambiguous_file (std::string file, std::string path, std::vector<std::string> hits); diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index fe44466f9b..348a87136f 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -82,8 +82,6 @@ ARDOUR_UI::setup_windows () we_have_dependents (); - theme_manager->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleThemeManager"))); - #ifdef TOP_MENUBAR HBox* status_bar_packer = manage (new HBox); EventBox* status_bar_event_box = manage (new EventBox); diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc index 7438fab9f0..5269bb93ed 100644 --- a/gtk2_ardour/ardour_ui_dependents.cc +++ b/gtk2_ardour/ardour_ui_dependents.cc @@ -85,118 +85,6 @@ ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s) s->restore_history (""); } -static bool -_hide_splash (gpointer arg) -{ - ((ARDOUR_UI*)arg)->hide_splash(); - return false; -} - -void -ARDOUR_UI::goto_editor_window () -{ - if (splash && splash->is_visible()) { - // in 2 seconds, hide the splash screen - Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000); - } - - editor->show_window (); - editor->present (); - flush_pending (); -} - -void -ARDOUR_UI::goto_mixer_window () -{ - if (!editor) { - return; - } - - Glib::RefPtr<Gdk::Window> win = editor->get_window (); - Glib::RefPtr<Gdk::Screen> screen; - - if (win) { - screen = win->get_screen(); - } else { - screen = Gdk::Screen::get_default(); - } - - if (screen && screen->get_height() < 700) { - Gtk::MessageDialog msg (_("This screen is not tall enough to display the mixer window")); - msg.run (); - return; - } - - mixer->show_window (); - mixer->present (); - flush_pending (); -} - -void -ARDOUR_UI::toggle_mixer_window () -{ - Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-mixer")); - if (!act) { - return; - } - - Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act); - - if (tact->get_active()) { - goto_mixer_window (); - } else { - mixer->hide (); - } -} - -void -ARDOUR_UI::toggle_editor_mixer () -{ - if (editor && mixer) { - - if (editor->get_screen() != mixer->get_screen()) { - // different screens, so don't do anything - return; - } - - /* See if they are obscuring each other */ - - gint ex, ey, ew, eh; - gint mx, my, mw, mh; - - editor->get_position (ex, ey); - editor->get_size (ew, eh); - - mixer->get_position (mx, my); - mixer->get_size (mw, mh); - - GdkRectangle e; - GdkRectangle m; - GdkRectangle r; - - e.x = ex; - e.y = ey; - e.width = ew; - e.height = eh; - - m.x = mx; - m.y = my; - m.width = mw; - m.height = mh; - - if (!gdk_rectangle_intersect (&e, &m, &r)) { - /* they do not intersect so do not toggle */ - return; - } - } - - if (mixer && mixer->fully_visible()) { - goto_editor_window (); - } else { - goto_mixer_window (); - } -} - /** The main editor window has been closed */ gint ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/) diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 256a1a593e..d43d1dbec6 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -29,7 +29,9 @@ #include "actions.h" #include "add_route_dialog.h" +#include "add_video_dialog.h" #include "ardour_ui.h" +#include "big_clock_window.h" #include "bundle_manager.h" #include "global_port_matrix.h" #include "gui_object.h" @@ -45,6 +47,7 @@ #include "shuttle_control.h" #include "session_option_editor.h" #include "speaker_dialog.h" +#include "splash.h" #include "sfdb_ui.h" #include "theme_manager.h" #include "time_info_box.h" @@ -62,14 +65,20 @@ ARDOUR_UI::set_session (Session *s) { SessionHandlePtr::set_session (s); - for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) { - GlobalPortMatrixWindow* w; - if ((w = _global_port_matrix[*i]->get()) != 0) { - w->set_session (s); - } + if (audio_port_matrix) { + audio_port_matrix->set_session (s); + } + + if (midi_port_matrix) { + midi_port_matrix->set_session (s); } + if (!_session) { + /* Session option editor cannot exist across change-of-session */ + session_option_editor.drop_window (); + /* Ditto for AddVideoDialog */ + add_video_dialog.drop_window (); return; } @@ -86,37 +95,12 @@ ARDOUR_UI::set_session (Session *s) } AutomationWatch::instance().set_session (s); - - if (location_ui->get()) { - location_ui->get()->set_session(s); - } - - if (speaker_config_window->get()) { - speaker_config_window->get()->set_speakers (s->get_speakers()); - } - - if (route_params) { - route_params->set_session (s); - } - - if (add_route_dialog) { - add_route_dialog->set_session (s); - } - - if (session_option_editor) { - session_option_editor->set_session (s); - } + WindowManager::instance().set_session (s); if (shuttle_box) { shuttle_box->set_session (s); } - for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) { - if (_global_port_matrix[*i]->get()) { - _global_port_matrix[*i]->get()->set_session (_session); - } - } - primary_clock->set_session (s); secondary_clock->set_session (s); big_clock->set_session (s); @@ -267,230 +251,166 @@ ARDOUR_UI::unload_session (bool hide_stuff) return 0; } -void -ARDOUR_UI::toggle_big_clock_window () +static bool +_hide_splash (gpointer arg) { - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); - - if (tact->get_active()) { - big_clock_window->get()->show_all (); - big_clock_window->get()->present (); - } else { - big_clock_window->get()->hide (); - } - } + ((ARDOUR_UI*)arg)->hide_splash(); + return false; } void -ARDOUR_UI::toggle_speaker_config_window () +ARDOUR_UI::goto_editor_window () { - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-speaker-config")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); - - if (tact->get_active()) { - speaker_config_window->get()->show_all (); - speaker_config_window->get()->present (); - } else { - speaker_config_window->get()->hide (); - } + if (splash && splash->is_visible()) { + // in 2 seconds, hide the splash screen + Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000); } + + editor->show_window (); + editor->present (); + flush_pending (); } void -ARDOUR_UI::new_midi_tracer_window () +ARDOUR_UI::goto_mixer_window () { - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer")); - if (!act) { + if (!editor) { return; } - std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin (); - while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) { - ++i; - } - - if (i == _midi_tracer_windows.end()) { - /* all our MIDITracer windows are visible; make a new one */ - MidiTracer* t = new MidiTracer (); - manage_window (*t); - t->show_all (); - _midi_tracer_windows.push_back (t); + Glib::RefPtr<Gdk::Window> win = editor->get_window (); + Glib::RefPtr<Gdk::Screen> screen; + + if (win) { + screen = win->get_screen(); } else { - /* re-use the hidden one */ - (*i)->show_all (); + screen = Gdk::Screen::get_default(); } -} - -void -ARDOUR_UI::toggle_rc_options_window () -{ - if (rc_option_editor == 0) { - rc_option_editor = new RCOptionEditor; - rc_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleRCOptionsEditor"))); - rc_option_editor->set_session (_session); + + if (screen && screen->get_height() < 700) { + Gtk::MessageDialog msg (_("This screen is not tall enough to display the mixer window")); + msg.run (); + return; } - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleRCOptionsEditor")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); - - if (tact->get_active()) { - rc_option_editor->show_all (); - rc_option_editor->present (); - } else { - rc_option_editor->hide (); - } - } + mixer->show_window (); + mixer->present (); + flush_pending (); } + void -ARDOUR_UI::toggle_session_options_window () +ARDOUR_UI::toggle_mixer_window () { - if (session_option_editor == 0) { - session_option_editor = new SessionOptionEditor (_session); - session_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleSessionOptionsEditor"))); + Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-mixer")); + if (!act) { + return; } - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleSessionOptionsEditor")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act); - - if (tact->get_active()) { - session_option_editor->show_all (); - session_option_editor->present (); - } else { - session_option_editor->hide (); - } - } -} + Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act); -int -ARDOUR_UI::create_location_ui () -{ - if (location_ui->get() == 0) { - location_ui->set (new LocationUIWindow ()); - location_ui->get()->set_session (_session); - location_ui->get()->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleLocations"))); + if (tact->get_active()) { + goto_mixer_window (); + } else { + mixer->hide (); } - return 0; } void -ARDOUR_UI::toggle_location_window () +ARDOUR_UI::toggle_editor_mixer () { - if (create_location_ui()) { - return; - } + if (editor && mixer) { - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleLocations")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); + if (editor->get_screen() != mixer->get_screen()) { + // different screens, so don't do anything + return; + } - if (tact->get_active()) { - location_ui->get()->show_all (); - location_ui->get()->present (); - } else { - location_ui->get()->hide (); + /* See if they are obscuring each other */ + + gint ex, ey, ew, eh; + gint mx, my, mw, mh; + + editor->get_position (ex, ey); + editor->get_size (ew, eh); + + mixer->get_position (mx, my); + mixer->get_size (mw, mh); + + GdkRectangle e; + GdkRectangle m; + GdkRectangle r; + + e.x = ex; + e.y = ey; + e.width = ew; + e.height = eh; + + m.x = mx; + m.y = my; + m.width = mw; + m.height = mh; + + if (!gdk_rectangle_intersect (&e, &m, &r)) { + /* they do not intersect so do not toggle */ + return; } } + + if (mixer && mixer->fully_visible()) { + goto_editor_window (); + } else { + goto_mixer_window (); + } } void -ARDOUR_UI::toggle_key_editor () +ARDOUR_UI::new_midi_tracer_window () { - if (key_editor == 0) { - key_editor = new KeyEditor; - key_editor->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleKeyEditor"))); + RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer")); + if (!act) { + return; } - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleKeyEditor")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); - - if (tact->get_active()) { - key_editor->show_all (); - key_editor->present (); - } else { - key_editor->hide (); - } + std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin (); + while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) { + ++i; } -} -void -ARDOUR_UI::toggle_theme_manager () -{ - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleThemeManager")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); - - if (tact->get_active()) { - theme_manager->show_all (); - theme_manager->present (); - } else { - theme_manager->hide (); - } + if (i == _midi_tracer_windows.end()) { + /* all our MIDITracer windows are visible; make a new one */ + MidiTracer* t = new MidiTracer (); + manage_window (*t); + t->show_all (); + _midi_tracer_windows.push_back (t); + } else { + /* re-use the hidden one */ + (*i)->show_all (); } } -void +BundleManager* ARDOUR_UI::create_bundle_manager () { - if (bundle_manager == 0) { - bundle_manager = new BundleManager (_session); - bundle_manager->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBundleManager"))); - } + return new BundleManager (_session); } -void -ARDOUR_UI::toggle_bundle_manager () +AddVideoDialog* +ARDOUR_UI::create_add_video_dialog () { - create_bundle_manager (); - - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBundleManager")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act); - - if (tact->get_active()) { - bundle_manager->show_all (); - bundle_manager->present (); - } else { - bundle_manager->hide (); - } - } + return new AddVideoDialog (_session); } -int -ARDOUR_UI::create_route_params () +SessionOptionEditor* +ARDOUR_UI::create_session_option_editor () { - if (route_params == 0) { - route_params = new RouteParams_UI (); - route_params->set_session (_session); - route_params->signal_unmap().connect (sigc::bind(sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleInspector"))); - } - return 0; + return new SessionOptionEditor (_session); } -void -ARDOUR_UI::toggle_route_params_window () +BigClockWindow* +ARDOUR_UI::create_big_clock_window () { - if (create_route_params ()) { - return; - } - - RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleInspector")); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); - - if (tact->get_active()) { - route_params->show_all (); - route_params->present (); - } else { - route_params->hide (); - } - } + return new BigClockWindow (*big_clock); } void @@ -512,14 +432,18 @@ ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { - float_big_clock (editor); + if (big_clock_window) { + big_clock_window->set_transient_for (*editor); + } } } else { if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { - float_big_clock (mixer); + if (big_clock_window) { + big_clock_window->set_transient_for (*mixer); + } } } diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 3d3dacd868..9d1e8c3d8a 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -52,7 +52,7 @@ #include "mixer_ui.h" #include "startup.h" #include "utils.h" -#include "window_proxy.h" +#include "window_manager.h" #include "global_port_matrix.h" #include "location_ui.h" #include "main_clock.h" @@ -229,42 +229,14 @@ ARDOUR_UI::install_actions () ActionManager::register_toggle_action (common_actions, X_("toggle-mixer"), S_("Window|Mixer"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_mixer_window)); ActionManager::register_action (common_actions, X_("toggle-editor-mixer"), _("Toggle Editor+Mixer"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_editor_mixer)); - ActionManager::register_toggle_action (common_actions, X_("ToggleRCOptionsEditor"), _("Preferences"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_rc_options_window)); - ActionManager::register_toggle_action (common_actions, X_("ToggleSessionOptionsEditor"), _("Properties"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_session_options_window)); - act = ActionManager::register_toggle_action (common_actions, X_("ToggleInspector"), _("Tracks and Busses"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_route_params_window)); - ActionManager::session_sensitive_actions.push_back (act); - ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_toggle_action (common_actions, X_("ToggleLocations"), _("Locations"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_location_window)); - ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_toggle_action (common_actions, X_("ToggleBigClock"), _("Big Clock"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_big_clock_window)); - ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_toggle_action (common_actions, X_("toggle-speaker-config"), _("Speaker Configuration"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_speaker_config_window)); - ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_toggle_action (common_actions, X_("toggle-audio-connection-manager"), _("Audio Connection Manager"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::toggle_global_port_matrix), ARDOUR::DataType::AUDIO)); - ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_toggle_action (common_actions, X_("toggle-midi-connection-manager"), _("MIDI Connection Manager"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::toggle_global_port_matrix), ARDOUR::DataType::MIDI)); - ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window)); ActionManager::session_sensitive_actions.push_back (act); - ActionManager::register_action (common_actions, X_("About"), _("About"), sigc::mem_fun(*this, &ARDOUR_UI::show_about)); ActionManager::register_action (common_actions, X_("Chat"), _("Chat"), sigc::mem_fun(*this, &ARDOUR_UI::launch_chat)); /** TRANSLATORS: This is `Manual' in the sense of an instruction book that tells a user how to use Ardour */ ActionManager::register_action (common_actions, X_("Manual"), S_("Help|Manual"), mem_fun(*this, &ARDOUR_UI::launch_manual)); ActionManager::register_action (common_actions, X_("Reference"), _("Reference"), mem_fun(*this, &ARDOUR_UI::launch_reference)); - ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_theme_manager)); - ActionManager::register_toggle_action (common_actions, X_("ToggleKeyEditor"), _("Key Bindings"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_key_editor)); - ActionManager::register_toggle_action (common_actions, X_("ToggleBundleManager"), _("Bundle Manager"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_bundle_manager)); -#if 0 - act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal, (ARDOUR::RouteGroup *) 0, 1)); - ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (common_actions, X_("AddAudioBus"), _("Add Audio Bus"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::session_add_audio_bus), 1, 1, (ARDOUR::RouteGroup *) 0, 1)); - ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (common_actions, X_("AddMIDITrack"), _("Add MIDI Track"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::session_add_midi_track), (ARDOUR::RouteGroup *) 0, 1)); - ActionManager::session_sensitive_actions.push_back (act); - //act = ActionManager::register_action (common_actions, X_("AddMidiBus"), _("Add Midi Bus"), sigc::mem_fun(*this, &ARDOUR_UI::session_add_midi_bus)); - //ActionManager::session_sensitive_actions.push_back (act); -#endif act = ActionManager::register_action (common_actions, X_("Save"), _("Save"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""), false)); ActionManager::session_sensitive_actions.push_back (act); ActionManager::write_sensitive_actions.push_back (act); @@ -621,137 +593,6 @@ ARDOUR_UI::use_menubar_as_top_menubar () } void -ARDOUR_UI::big_clock_catch_focus () -{ - PublicEditor::instance().reset_focus (); -} - -void -ARDOUR_UI::setup_clock () -{ - ARDOUR_UI::Clock.connect (sigc::mem_fun (big_clock, &AudioClock::set)); - - big_clock->set_corner_radius (0.0); - big_clock->mode_changed.connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_reset_aspect_ratio)); - - big_clock_window->set (new Window (WINDOW_TOPLEVEL), false); - - big_clock_window->get()->set_keep_above (true); - big_clock_window->get()->set_border_width (0); - big_clock_window->get()->add (*big_clock); - - big_clock_window->get()->set_title (_("Big Clock")); - big_clock_window->get()->signal_realize().connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_realized)); - big_clock_window->get()->signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), big_clock_window->get()), false); - big_clock_window->get()->signal_size_allocate().connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_size_allocate)); - - big_clock_window->get()->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBigClock"))); - big_clock_window->get()->signal_unmap().connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_catch_focus)); - - manage_window (*big_clock_window->get()); -} - -void -ARDOUR_UI::big_clock_reset_aspect_ratio () -{ - Gtk::Requisition req; - big_clock->size_request (req); - float aspect = req.width/(float)req.height; - Gdk::Geometry geom; - - geom.min_aspect = aspect; - geom.max_aspect = aspect; - - big_clock_window->get()->set_geometry_hints (*big_clock, geom, Gdk::HINT_ASPECT); -} - -void -ARDOUR_UI::big_clock_realized () -{ - int x, y, w, d; - - set_decoration (big_clock_window->get(), (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH)); - big_clock_window->get()->get_window()->get_geometry (x, y, w, big_clock_height, d); - - big_clock_reset_aspect_ratio (); - - original_big_clock_height = big_clock_height; - original_big_clock_width = w; - - Pango::FontDescription fd (big_clock->get_style()->get_font()); - original_big_clock_font_size = fd.get_size (); - - if (!fd.get_size_is_absolute ()) { - original_big_clock_font_size /= PANGO_SCALE; - } - - big_clock_window->setup (); -} - -void -ARDOUR_UI::float_big_clock (Gtk::Window* parent) -{ - if (big_clock_window->get()) { - if (parent) { - big_clock_window->get()->set_transient_for (*parent); - } else { - gtk_window_set_transient_for (big_clock_window->get()->gobj(), (GtkWindow*) 0); - } - } -} - -void -ARDOUR_UI::big_clock_size_allocate (Gtk::Allocation&) -{ - if (!big_clock_resize_in_progress) { - Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::idle_big_clock_text_resizer), 0, 0)); - big_clock_resize_in_progress = true; - } -} - -bool -ARDOUR_UI::idle_big_clock_text_resizer (int, int) -{ - big_clock_resize_in_progress = false; - - Glib::RefPtr<Gdk::Window> win = big_clock_window->get()->get_window(); - Pango::FontDescription fd (big_clock->get_style()->get_font()); - int current_size = fd.get_size (); - int x, y, w, h, d; - - if (!fd.get_size_is_absolute ()) { - current_size /= PANGO_SCALE; - } - - win->get_geometry (x, y, w, h, d); - - double scale = min (((double) w / (double) original_big_clock_width), - ((double) h / (double) original_big_clock_height)); - - int size = (int) lrintf (original_big_clock_font_size * scale); - - if (size != current_size) { - - string family = fd.get_family(); - char buf[family.length()+16]; - snprintf (buf, family.length()+16, "%s %d", family.c_str(), size); - - try { - Pango::FontDescription fd (buf); - Glib::RefPtr<Gtk::RcStyle> rcstyle = big_clock->get_modifier_style (); - rcstyle->set_font (fd); - big_clock->modify_style (rcstyle); - } - - catch (...) { - /* oh well, do nothing */ - } - } - - return false; -} - -void ARDOUR_UI::save_ardour_state () { if (!keyboard || !mixer || !editor) { @@ -769,11 +610,9 @@ ARDOUR_UI::save_ardour_state () XMLNode* window_node = new XMLNode (X_("UI")); window_node->add_property (_status_bar_visibility.get_state_name().c_str(), _status_bar_visibility.get_state_value ()); - for (list<WindowProxyBase*>::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) { - if ((*i)->rc_configured()) { - window_node->add_child_nocopy (*((*i)->get_state ())); - } - } + /* Windows */ + + WindowManager::instance().add_state (*window_node); /* tearoffs */ @@ -815,14 +654,14 @@ ARDOUR_UI::save_ardour_state () if (_session) { _session->add_instant_xml (enode); _session->add_instant_xml (mnode); - if (location_ui->get ()) { - _session->add_instant_xml (location_ui->get()->ui().get_state ()); + if (location_ui) { + _session->add_instant_xml (location_ui->ui().get_state ()); } } else { Config->add_instant_xml (enode); Config->add_instant_xml (mnode); - if (location_ui->get ()) { - Config->add_instant_xml (location_ui->get()->ui().get_state ()); + if (location_ui) { + Config->add_instant_xml (location_ui->ui().get_state ()); } } @@ -830,28 +669,6 @@ ARDOUR_UI::save_ardour_state () } void -ARDOUR_UI::toggle_global_port_matrix (ARDOUR::DataType t) -{ - std::string const action = string_compose ("toggle-%1-connection-manager", t.to_string ()); - - if (_global_port_matrix[t]->get() == 0) { - _global_port_matrix[t]->set (new GlobalPortMatrixWindow (_session, t)); - _global_port_matrix[t]->get()->signal_unmap().connect(sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), string_compose (X_("<Actions>/Common/%1"), action))); - } - - RefPtr<Action> act = ActionManager::get_action (X_("Common"), action.c_str()); - if (act) { - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act); - - if (tact->get_active()) { - _global_port_matrix[t]->get()->present (); - } else { - _global_port_matrix[t]->get()->hide (); - } - } -} - -void ARDOUR_UI::resize_text_widgets () { set_size_request_to_display_given_text (cpu_load_label, "DSP: 100.0%", 2, 2); diff --git a/gtk2_ardour/ardour_ui_mixer.cc b/gtk2_ardour/ardour_ui_mixer.cc index aacffa9d20..2604e8215b 100644 --- a/gtk2_ardour/ardour_ui_mixer.cc +++ b/gtk2_ardour/ardour_ui_mixer.cc @@ -23,8 +23,10 @@ is to cut down on the nasty compile times for these classes. */ +#include "actions.h" #include "ardour_ui.h" #include "mixer_ui.h" + #include "i18n.h" using namespace ARDOUR; diff --git a/gtk2_ardour/ardour_window.cc b/gtk2_ardour/ardour_window.cc index 6330ecd6ac..f16032dc74 100644 --- a/gtk2_ardour/ardour_window.cc +++ b/gtk2_ardour/ardour_window.cc @@ -23,6 +23,7 @@ #include <gtkmm2ext/doi.h> #include "ardour_window.h" +#include "ardour_ui.h" #include "keyboard.h" using namespace std; @@ -83,8 +84,12 @@ ArdourWindow::init () (a) utility & dialog windows are considered to be part of the same level (b) they will float above normal windows without any particular effort + (c) present()-ing them will make a utility float over a dialog or + vice versa. */ set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); + + ARDOUR_UI::CloseAllDialogs.connect (sigc::mem_fun (*this, &ArdourWindow::hide)); } diff --git a/gtk2_ardour/big_clock_window.cc b/gtk2_ardour/big_clock_window.cc new file mode 100644 index 0000000000..7a96293b05 --- /dev/null +++ b/gtk2_ardour/big_clock_window.cc @@ -0,0 +1,156 @@ +/* + Copyright (C) 20002-2013 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <algorithm> +#include <string> + +#include "ardour_ui.h" +#include "audio_clock.h" +#include "big_clock_window.h" +#include "public_editor.h" +#include "utils.h" + +#include "i18n.h" + +using std::min; +using std::string; + +BigClockWindow::BigClockWindow (AudioClock& c) + : ArdourWindow (_("Big Clock")) + , clock (c) + , resize_in_progress (false) + , original_height (0) + , original_width (0) + , original_font_size (0) +{ + ARDOUR_UI::Clock.connect (sigc::mem_fun (clock, &AudioClock::set)); + + clock.set_corner_radius (0.0); + clock.mode_changed.connect (sigc::mem_fun (*this, &BigClockWindow::reset_aspect_ratio)); + + set_keep_above (true); + set_border_width (0); + add (clock); + clock.show_all (); +} + +void +BigClockWindow::on_unmap () +{ + PublicEditor::instance().reset_focus (); +} + +bool +BigClockWindow::on_key_press_event (GdkEventKey* ev) +{ + return relay_key_press (ev, this); +} + +void +BigClockWindow::on_realize () +{ + int x, y, w, d, h; + + ArdourWindow::on_realize (); + + get_window()->set_decorations (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH); + get_window()->get_geometry (x, y, w, h, d); + + reset_aspect_ratio (); + + original_height = h; + original_width = w; + + Pango::FontDescription fd (clock.get_style()->get_font()); + original_font_size = fd.get_size (); + + if (!fd.get_size_is_absolute ()) { + original_font_size /= PANGO_SCALE; + } +} + +void +BigClockWindow::on_size_allocate (Gtk::Allocation& alloc) +{ + ArdourWindow::on_size_allocate (alloc); + + if (!resize_in_progress) { + Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &BigClockWindow::text_resizer), 0, 0)); + resize_in_progress = true; + } +} + +void +BigClockWindow::reset_aspect_ratio () +{ + Gtk::Requisition req; + + clock.size_request (req); + + float aspect = req.width/(float)req.height; + Gdk::Geometry geom; + + geom.min_aspect = aspect; + geom.max_aspect = aspect; + + set_geometry_hints (clock, geom, Gdk::HINT_ASPECT); +} + +bool +BigClockWindow::text_resizer (int, int) +{ + resize_in_progress = false; + + Glib::RefPtr<Gdk::Window> win = get_window(); + Pango::FontDescription fd (clock.get_style()->get_font()); + int current_size = fd.get_size (); + int x, y, w, h, d; + + if (!fd.get_size_is_absolute ()) { + current_size /= PANGO_SCALE; + } + + win->get_geometry (x, y, w, h, d); + + double scale = min (((double) w / (double) original_width), + ((double) h / (double) original_height)); + + int size = (int) lrintf (original_font_size * scale); + + if (size != current_size) { + + string family = fd.get_family(); + char buf[family.length()+16]; + snprintf (buf, family.length()+16, "%s %d", family.c_str(), size); + + try { + Pango::FontDescription fd (buf); + Glib::RefPtr<Gtk::RcStyle> rcstyle = clock.get_modifier_style (); + rcstyle->set_font (fd); + clock.modify_style (rcstyle); + } + + catch (...) { + /* oh well, do nothing */ + } + } + + return false; +} + diff --git a/gtk2_ardour/big_clock_window.h b/gtk2_ardour/big_clock_window.h new file mode 100644 index 0000000000..c1a5b0ebee --- /dev/null +++ b/gtk2_ardour/big_clock_window.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2013 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __bigclock_window_h__ +#define __bigclock_window_h__ + +#include "ardour_window.h" + +class AudioClock; + +class BigClockWindow : public ArdourWindow +{ + public: + BigClockWindow (AudioClock&); + + private: + AudioClock& clock; + bool resize_in_progress; + int original_height; + int original_width; + int original_font_size; + + void on_size_allocate (Gtk::Allocation&); + void on_realize (); + void on_unmap (); + bool on_key_press_event (GdkEventKey*); + + bool text_resizer (int, int); + void reset_aspect_ratio (); +}; + +#endif // __ardour_window_h__ + diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 0647b17089..e7fcc11a3f 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -57,7 +57,6 @@ #include "enums.h" #include "editor_items.h" #include "region_selection.h" -#include "window_proxy.h" namespace Gtkmm2ext { class TearOff; diff --git a/gtk2_ardour/mnemonic-us.bindings.in b/gtk2_ardour/mnemonic-us.bindings.in index ef596478fc..aff175857c 100644 --- a/gtk2_ardour/mnemonic-us.bindings.in +++ b/gtk2_ardour/mnemonic-us.bindings.in @@ -158,13 +158,13 @@ This mode provides many different operations on both regions and control points, @mmode|MouseMode/set-mouse-mode-object|o|object mode @sess|Main/Open|<@PRIMARY@>o|open an existing session @sess|Main/Recent|<@PRIMARY@><@TERTIARY@>o|open a recent session -@wvis|Common/ToggleOptionsEditor|<@WINDOW@>o|toggle preferences dialog +@wvis|Window/toggle-session-options-editor|<@WINDOW@>o|toggle preferences dialog @rop|Region/naturalize-region|<@SECONDARY@>o|move to original position @trans|Editor/set-playhead|p|set playhead position @select|Editor/select-all-before-playhead|<@PRIMARY@>p|all before playhead -@wvis|Common/ToggleRCOptionsEditor|<@PRIMARY@><@TERTIARY@>p|toggle preferences dialog -@wvis|Common/toggle-audio-connection-manager|<@WINDOW@>p|toggle global audio patchbay -@wvis|Common/toggle-midi-connection-manager|<@WINDOW@><@TERTIARY@>p|toggle global midi patchbay +@wvis|Window/toggle-rc-options-editor|<@PRIMARY@><@TERTIARY@>p|toggle preferences dialog +@wvis|Window/toggle-audio-connection-manager|<@WINDOW@>p|toggle global audio patchbay +@wvis|Window/toggle-midi-connection-manager|<@WINDOW@><@TERTIARY@>p|toggle global midi patchbay @midi|MIDI/panic|<@PRIMARY@><@SECONDARY@>p|MIDI panic (stop all notes etc) @select|Editor/select-all-after-playhead|<@TERTIARY@><@PRIMARY@>p|all after playhead @@ -194,10 +194,10 @@ This mode provides many different operations on both regions and control points, @epp|Region/play-selected-regions|h|play selected region(s) @eep|Region/trim-front|j|trim front @eep|Region/trim-back|k|trim back -@wvis|Common/ToggleKeyEditor|<@WINDOW@>k|toggle key bindings editor +@wvis|Window/toggle-key-editor|<@WINDOW@>k|toggle key bindings editor @trans|Transport/Loop|l|loop play (the loop range) @select|Editor/select-all-in-loop-range|<@PRIMARY@>l|select all in loop range -@wvis|Common/ToggleLocations|<@WINDOW@>l| toggle locations dialog +@wvis|Window/toggle-locations|<@WINDOW@>l| toggle locations dialog ;; BOTTOM ROW @@ -209,12 +209,12 @@ This mode provides many different operations on both regions and control points, @edit|Editor/editor-cut|<@PRIMARY@>x|cut @-group|Editor/crop|c|some text @edit|Editor/editor-copy|<@PRIMARY@>c|copy -@wvis|Common/ToggleColorManager|<@WINDOW@>c|toggle color manager +@wvis|Window/toggle-theme-manager|<@WINDOW@>c|toggle color manager @rop|Region/set-region-sync-position|v|set region sync point @edit|Editor/editor-paste|<@PRIMARY@>v|paste @-group|Editor/brush-at-mouse|<@PRIMARY@>b|some text @trans|Editor/track-record-enable-toggle|<@TERTIARY@>b|toggle track rec-enable -@wvis|Common/ToggleBigClock|<@WINDOW@>b|toggle big clock +@wvis|Window/toggle-big-clock|<@WINDOW@>b|toggle big clock @rop|Region/normalize-region|n|normalize @sess|Main/AddTrackBus|<@PRIMARY@><@TERTIARY@>n|add track(s) or bus(ses) @sess|Main/New|<@PRIMARY@>n|open a new session diff --git a/gtk2_ardour/nsm.cc b/gtk2_ardour/nsm.cc index a208d4a3b2..18d88fec0a 100644 --- a/gtk2_ardour/nsm.cc +++ b/gtk2_ardour/nsm.cc @@ -42,10 +42,10 @@ NSM_Client::command_save(char **out_msg) } int -NSM_Client::command_open(const char *name, - const char */*display_name*/, - const char *client_id, - char **/*out_msg*/) +NSM_Client::command_open(const char* name, + const char* /*display_name*/, + const char* client_id, + char** /*out_msg*/) { int r = ERR_OK; diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc index 811c443373..1768bff1a7 100644 --- a/gtk2_ardour/option_editor.cc +++ b/gtk2_ardour/option_editor.cc @@ -342,7 +342,7 @@ OptionEditor::OptionEditor (Configuration* c, std::string const & t) using namespace Notebook_Helpers; set_default_size (300, 300); - set_wmclass (X_("ardour_preferences"), PROGRAM_NAME); + // set_wmclass (X_("ardour_preferences"), PROGRAM_NAME); set_name ("Preferences"); add_events (Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK); diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index 8868279cf5..943a7a8bce 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -168,42 +168,6 @@ PluginUIWindow::~PluginUIWindow () } void -PluginUIWindow::on_map () -{ - Window::on_map (); -} - -bool -PluginUIWindow::on_enter_notify_event (GdkEventCrossing *ev) -{ - Keyboard::the_keyboard().enter_window (ev, this); - return false; -} - -bool -PluginUIWindow::on_leave_notify_event (GdkEventCrossing *ev) -{ - Keyboard::the_keyboard().leave_window (ev, this); - return false; -} - -bool -PluginUIWindow::on_focus_in_event (GdkEventFocus *ev) -{ - Window::on_focus_in_event (ev); - //Keyboard::the_keyboard().magic_widget_grab_focus (); - return false; -} - -bool -PluginUIWindow::on_focus_out_event (GdkEventFocus *ev) -{ - Window::on_focus_out_event (ev); - //Keyboard::the_keyboard().magic_widget_drop_focus (); - return false; -} - -void PluginUIWindow::on_show () { set_role("plugin_ui"); diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h index be03e6ede4..cf86f3e1bb 100644 --- a/gtk2_ardour/plugin_ui.h +++ b/gtk2_ardour/plugin_ui.h @@ -294,15 +294,10 @@ class PluginUIWindow : public ArdourWindow void set_title(const std::string& title); - bool on_enter_notify_event (GdkEventCrossing*); - bool on_leave_notify_event (GdkEventCrossing*); - bool on_focus_in_event (GdkEventFocus*); - bool on_focus_out_event (GdkEventFocus*); bool on_key_press_event (GdkEventKey*); bool on_key_release_event (GdkEventKey*); void on_show (); void on_hide (); - void on_map (); private: std::string _title; diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index 335861883c..07bb0cadde 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -1020,6 +1020,22 @@ ProcessorBox::processor_operation (ProcessorOperation op) } } +ProcessorWindowProxy* +ProcessorBox::find_window_proxy (boost::shared_ptr<Processor> processor) const +{ + for (list<ProcessorWindowProxy*>::const_iterator i = _processor_window_info.begin(); i != _processor_window_info.end(); ++i) { + boost::shared_ptr<Processor> p = (*i)->processor().lock(); + + if (p && p == processor) { + return (*i); + } + } + + return 0; +} + + + bool ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry* child) { @@ -1034,13 +1050,16 @@ ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry* if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) { if (_session->engine().connected()) { + /* XXX giving an error message here is hard, because we may be in the midst of a button press */ + if (Config->get_use_plugin_own_gui ()) { - toggle_edit_processor (processor); + edit_processor (processor); } else { - toggle_edit_generic_processor (processor); + generic_edit_processor (processor); } } + ret = true; } else if (processor && ev->button == 1 && selected) { @@ -1345,7 +1364,7 @@ ProcessorBox::redisplay_processors () _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display)); - for (list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin(); i != _processor_window_proxies.end(); ++i) { + for (list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin(); i != _processor_window_info.end(); ++i) { (*i)->marked = false; } @@ -1353,15 +1372,15 @@ ProcessorBox::redisplay_processors () /* trim dead wood from the processor window proxy list */ - list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin(); - while (i != _processor_window_proxies.end()) { + list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin(); + while (i != _processor_window_info.end()) { list<ProcessorWindowProxy*>::iterator j = i; ++j; if (!(*i)->marked) { - ARDOUR_UI::instance()->remove_window_proxy (*i); + WindowManager::instance().remove (*i); delete *i; - _processor_window_proxies.erase (i); + _processor_window_info.erase (i); } i = j; @@ -1381,8 +1400,8 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w) return; } - list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin (); - while (i != _processor_window_proxies.end()) { + list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin (); + while (i != _processor_window_info.end()) { boost::shared_ptr<Processor> t = (*i)->processor().lock (); @@ -1410,10 +1429,15 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w) ProcessorWindowProxy* wp = new ProcessorWindowProxy ( string_compose ("%1-%2-%3", loc, _route->id(), p->id()), - _session->extra_xml (X_("UI")), this, w); + const XMLNode* ui_xml = _session->extra_xml (X_("UI")); + + if (ui_xml) { + wp->set_state (*ui_xml); + } + wp->marked = true; /* if the processor already has an existing UI, @@ -1423,11 +1447,11 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w) void* existing_ui = p->get_ui (); if (existing_ui) { - wp->set (static_cast<Gtk::Window*>(existing_ui)); + wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui))); } - _processor_window_proxies.push_back (wp); - ARDOUR_UI::instance()->add_window_proxy (wp); + _processor_window_info.push_back (wp); + WindowManager::instance().register_window (wp); } void @@ -2015,8 +2039,8 @@ ProcessorBox::one_processor_can_be_edited () return (i != selection.end()); } -void -ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor) +Gtk::Window* +ProcessorBox::get_editor_window (boost::shared_ptr<Processor> processor) { boost::shared_ptr<Send> send; boost::shared_ptr<InternalSend> internal_send; @@ -2028,7 +2052,7 @@ ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor) if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) { if (boost::dynamic_pointer_cast<AudioTrack> (_route)->freeze_state() == AudioTrack::Frozen) { - return; + return 0; } } @@ -2041,7 +2065,7 @@ ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor) } else if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) { if (!_session->engine().connected()) { - return; + return 0; } if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) { @@ -2062,11 +2086,11 @@ ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor) if (boost::dynamic_pointer_cast<InternalReturn> (retrn)) { /* no GUI for these */ - return; + return 0; } if (!_session->engine().connected()) { - return; + return 0; } boost::shared_ptr<Return> retrn = boost::dynamic_pointer_cast<Return> (processor); @@ -2096,7 +2120,7 @@ ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor) if (w == 0) { - plugin_ui = new PluginUIWindow (plugin_insert); + plugin_ui = new PluginUIWindow (plugin_insert, false, Config->get_use_plugin_own_gui()); plugin_ui->set_title (generate_processor_title (plugin_insert)); set_processor_ui (plugin_insert, plugin_ui); @@ -2111,7 +2135,7 @@ ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor) if (!_session->engine().connected()) { MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible")); msg.run (); - return; + return 0; } PortInsertWindow *io_selector; @@ -2129,35 +2153,23 @@ ProcessorBox::toggle_edit_processor (boost::shared_ptr<Processor> processor) gidget = io_selector; } - if (gidget) { - if (gidget->is_visible()) { - gidget->hide (); - } else { - gidget->show_all (); - gidget->present (); - } - } + return gidget; } -/** Toggle a generic (Ardour-generated) plugin UI */ -void -ProcessorBox::toggle_edit_generic_processor (boost::shared_ptr<Processor> processor) +Gtk::Window* +ProcessorBox::get_generic_editor_window (boost::shared_ptr<Processor> processor) { boost::shared_ptr<PluginInsert> plugin_insert = boost::dynamic_pointer_cast<PluginInsert>(processor); + if (!plugin_insert) { - return; + return 0; } - PluginUIWindow* plugin_ui = new PluginUIWindow (plugin_insert, true, false); - plugin_ui->set_title(generate_processor_title (plugin_insert)); + PluginUIWindow* win = new PluginUIWindow (plugin_insert, true, false); + win->set_title (generate_processor_title (plugin_insert)); - if (plugin_ui->is_visible()) { - plugin_ui->hide(); - } else { - plugin_ui->show_all(); - plugin_ui->present(); - } + return win; } void @@ -2237,7 +2249,7 @@ ProcessorBox::rb_edit_generic () return; } - _current_processor_box->for_selected_processors (&ProcessorBox::toggle_edit_generic_processor); + _current_processor_box->for_selected_processors (&ProcessorBox::generic_edit_processor); } void @@ -2413,7 +2425,35 @@ ProcessorBox::rb_edit () return; } - _current_processor_box->for_selected_processors (&ProcessorBox::toggle_edit_processor); + _current_processor_box->for_selected_processors (&ProcessorBox::edit_processor); +} + +void +ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor) +{ + if (!processor) { + return; + } + + ProcessorWindowProxy* proxy = find_window_proxy (processor); + + if (proxy) { + proxy->toggle (); + } +} + +void +ProcessorBox::generic_edit_processor (boost::shared_ptr<Processor> processor) +{ + if (!processor) { + return; + } + + ProcessorWindowProxy* proxy = find_window_proxy (processor); + + if (proxy) { + proxy->toggle (); + } } void @@ -2479,8 +2519,8 @@ ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi) Window * ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const { - list<ProcessorWindowProxy*>::const_iterator i = _processor_window_proxies.begin (); - while (i != _processor_window_proxies.end()) { + list<ProcessorWindowProxy*>::const_iterator i = _processor_window_info.begin (); + while (i != _processor_window_info.end()) { boost::shared_ptr<Processor> t = (*i)->processor().lock (); if (t && t == p) { return (*i)->get (); @@ -2499,14 +2539,14 @@ ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const void ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w) { - list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin (); + list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin (); p->set_ui (w); - while (i != _processor_window_proxies.end()) { + while (i != _processor_window_info.end()) { boost::shared_ptr<Processor> t = (*i)->processor().lock (); if (t && t == p) { - (*i)->set (w); + (*i)->use_window (*w); return; } @@ -2583,29 +2623,60 @@ ProcessorBox::update_gui_object_state (ProcessorEntry* entry) entry->add_control_state (proc); } -ProcessorWindowProxy::ProcessorWindowProxy ( - string const & name, - XMLNode const * node, - ProcessorBox* box, - boost::weak_ptr<Processor> processor - ) - : WindowProxy<Gtk::Window> (name, node) +ProcessorWindowProxy::ProcessorWindowProxy (string const & name, ProcessorBox* box, boost::weak_ptr<Processor> processor) + : WindowManager::ProxyBase (name, string()) , marked (false) , _processor_box (box) , _processor (processor) + , is_custom (false) { } +ARDOUR::SessionHandlePtr* +ProcessorWindowProxy::session_handle() +{ + /* we don't care */ + return 0; +} -void -ProcessorWindowProxy::show () +Gtk::Window* +ProcessorWindowProxy::get (bool create) { boost::shared_ptr<Processor> p = _processor.lock (); + if (!p) { - return; + return 0; } + + if (_window && (is_custom != Config->get_use_plugin_own_gui ())) { + /* drop existing window - wrong type */ + drop_window (); + } + + if (!_window) { + if (!create) { + return 0; + } + + _window = _processor_box->get_editor_window (p); + is_custom = Config->get_use_plugin_own_gui(); - _processor_box->toggle_edit_processor (p); + if (_window) { + setup (); + } + } + + return _window; } +void +ProcessorWindowProxy::toggle () +{ + if (_window && (is_custom != Config->get_use_plugin_own_gui ())) { + /* drop existing window - wrong type */ + drop_window (); + } + + WindowManager::ProxyBase::toggle (); +} diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h index 157cdbf27e..44d6a0ab6a 100644 --- a/gtk2_ardour/processor_box.h +++ b/gtk2_ardour/processor_box.h @@ -53,8 +53,8 @@ #include "io_selector.h" #include "send_ui.h" #include "enums.h" -#include "window_proxy.h" #include "ardour_button.h" +#include "window_manager.h" class MotionController; class PluginSelector; @@ -75,28 +75,26 @@ namespace ARDOUR { class ProcessorBox; -/** A WindowProxy for Processor UI windows; it knows how to ask a ProcessorBox - * to create a UI window for a particular processor. - */ -class ProcessorWindowProxy : public WindowProxy<Gtk::Window> +class ProcessorWindowProxy : public WindowManager::ProxyBase { -public: - ProcessorWindowProxy (std::string const &, XMLNode const *, ProcessorBox *, boost::weak_ptr<ARDOUR::Processor>); + public: + ProcessorWindowProxy (std::string const &, ProcessorBox *, boost::weak_ptr<ARDOUR::Processor>); - void show (); - bool rc_configured () const { - return false; - } + Gtk::Window* get (bool create = false); + + boost::weak_ptr<ARDOUR::Processor> processor () const { + return _processor; + } - boost::weak_ptr<ARDOUR::Processor> processor () const { - return _processor; - } + ARDOUR::SessionHandlePtr* session_handle(); + void toggle(); - bool marked; + bool marked; -private: - ProcessorBox* _processor_box; - boost::weak_ptr<ARDOUR::Processor> _processor; + private: + ProcessorBox* _processor_box; + boost::weak_ptr<ARDOUR::Processor> _processor; + bool is_custom; }; class ProcessorEntry : public Gtkmm2ext::DnDVBoxChild, public sigc::trackable @@ -255,9 +253,15 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD void hide_things (); + /* Everything except a WindowProxy object should use this to get the window */ Gtk::Window* get_processor_ui (boost::shared_ptr<ARDOUR::Processor>) const; - void toggle_edit_processor (boost::shared_ptr<ARDOUR::Processor>); - void toggle_edit_generic_processor (boost::shared_ptr<ARDOUR::Processor>); + + /* a WindowProxy object can use this */ + Gtk::Window* get_editor_window (boost::shared_ptr<ARDOUR::Processor>); + Gtk::Window* get_generic_editor_window (boost::shared_ptr<ARDOUR::Processor>); + + void edit_processor (boost::shared_ptr<ARDOUR::Processor>); + void generic_edit_processor (boost::shared_ptr<ARDOUR::Processor>); void update_gui_object_state (ProcessorEntry *); @@ -393,7 +397,9 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD void route_property_changed (const PBD::PropertyChange&); std::string generate_processor_title (boost::shared_ptr<ARDOUR::PluginInsert> pi); - std::list<ProcessorWindowProxy*> _processor_window_proxies; + std::list<ProcessorWindowProxy*> _processor_window_info; + ProcessorWindowProxy* find_window_proxy (boost::shared_ptr<ARDOUR::Processor>) const; + void set_processor_ui (boost::shared_ptr<ARDOUR::Processor>, Gtk::Window *); void maybe_add_processor_to_ui_list (boost::weak_ptr<ARDOUR::Processor>); diff --git a/gtk2_ardour/shuttle_control.cc b/gtk2_ardour/shuttle_control.cc index fa2c48bde3..1d150f73d6 100644 --- a/gtk2_ardour/shuttle_control.cc +++ b/gtk2_ardour/shuttle_control.cc @@ -31,6 +31,7 @@ #include "gtkmm2ext/utils.h" #include "gtkmm2ext/rgb_macros.h" +#include "actions.h" #include "ardour_ui.h" #include "rgb_macros.h" #include "shuttle_control.h" diff --git a/gtk2_ardour/startup.cc b/gtk2_ardour/startup.cc index 72c7d5e8b5..6f0b1cfaab 100644 --- a/gtk2_ardour/startup.cc +++ b/gtk2_ardour/startup.cc @@ -129,8 +129,6 @@ ArdourStartup::ArdourStartup (bool require_new, const std::string& session_name, set_default_icon_list (window_icons); } - set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG); - #ifdef __APPLE__ setup_prerelease_page (); #endif diff --git a/gtk2_ardour/step_entry.cc b/gtk2_ardour/step_entry.cc index 927c6f0324..fd53fd55ff 100644 --- a/gtk2_ardour/step_entry.cc +++ b/gtk2_ardour/step_entry.cc @@ -470,8 +470,6 @@ StepEntry::StepEntry (StepEditor& seditor) r = RefPtr<RadioAction>::cast_dynamic (act); assert (r); r->set_active (true); - - set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG); } StepEntry::~StepEntry() diff --git a/gtk2_ardour/video_image_frame.cc b/gtk2_ardour/video_image_frame.cc index c892bacfa6..e9520634bb 100644 --- a/gtk2_ardour/video_image_frame.cc +++ b/gtk2_ardour/video_image_frame.cc @@ -226,7 +226,7 @@ http_get_thread (void *arg) { void VideoImageFrame::http_download_done (char *data){ if (queued_request) { - http_maybe_get_again(); + http_get_again(want_video_frame_number); return; } @@ -253,7 +253,7 @@ VideoImageFrame::http_download_done (char *data){ usleep(20000); if (queued_request) { - http_maybe_get_again(); + http_get_again(want_video_frame_number); } pthread_mutex_unlock(&request_lock); } @@ -283,7 +283,7 @@ VideoImageFrame::http_get(framepos_t fn) { } void -VideoImageFrame::http_maybe_get_again() { +VideoImageFrame::http_get_again(framepos_t /*fn*/) { pthread_mutex_lock(&queue_lock); queued_request=false; req_video_frame_number=want_video_frame_number; diff --git a/gtk2_ardour/video_image_frame.h b/gtk2_ardour/video_image_frame.h index 1fe543dce5..0823839f5a 100644 --- a/gtk2_ardour/video_image_frame.h +++ b/gtk2_ardour/video_image_frame.h @@ -94,7 +94,7 @@ class VideoImageFrame : public sigc::trackable void http_get(framepos_t fn); - void http_maybe_get_again(); + void http_get_again(framepos_t fn); framepos_t req_video_frame_number; framepos_t want_video_frame_number; diff --git a/gtk2_ardour/window_manager.cc b/gtk2_ardour/window_manager.cc new file mode 100644 index 0000000000..f50fe444a8 --- /dev/null +++ b/gtk2_ardour/window_manager.cc @@ -0,0 +1,329 @@ +/* + Copyright (C) 2013 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <gtkmm/window.h> + +#include "pbd/xml++.h" + +#include "ardour/session_handle.h" + +#include "gtkmm2ext/visibility_tracker.h" + +#include "actions.h" +#include "window_manager.h" + +#include "i18n.h" + +using std::string; + +WindowManager* WindowManager::_instance = 0; + +WindowManager& +WindowManager::instance () +{ + if (!_instance) { + _instance = new WindowManager; + } + return *_instance; +} + +WindowManager::WindowManager () +{ +} + +void +WindowManager::register_window (ProxyBase* info) +{ + _windows.push_back (info); + + if (!info->menu_name().empty()) { + + if (!window_actions) { + window_actions = Gtk::ActionGroup::create (X_("Window")); + ActionManager::add_action_group (window_actions); + } + + info->set_action (ActionManager::register_action (window_actions, info->action_name().c_str(), info->menu_name().c_str(), + sigc::bind (sigc::mem_fun (*this, &WindowManager::toggle_window), info))); + } +} + +void +WindowManager::remove (const ProxyBase* info) +{ + for (Windows::iterator i = _windows.begin(); i != _windows.end(); ++i) { + if ((*i) == info) { + _windows.erase (i); + return; + } + } +} + +void +WindowManager::toggle_window (ProxyBase* proxy) +{ + if (proxy) { + proxy->toggle (); + } +} + +void +WindowManager::show_visible() const +{ + for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) { + if ((*i)->visible()) { + (*i)->show_all (); + (*i)->present (); + } + } +} + +void +WindowManager::add_state (XMLNode& root) const +{ + for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) { + root.add_child_nocopy ((*i)->get_state()); + } +} + +void +WindowManager::set_session (ARDOUR::Session* s) +{ + for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) { + ARDOUR::SessionHandlePtr* sp = (*i)->session_handle (); + if (sp) { + sp->set_session (s); + } + } +} + +/*-----------------------*/ + +WindowManager::ProxyBase::ProxyBase (const string& name, const std::string& menu_name) + : _name (name) + , _menu_name (menu_name) + , _window (0) + , _visible (false) + , _x_off (-1) + , _y_off (-1) + , _width (-1) + , _height (-1) + , vistracker (0) +{ +} + +WindowManager::ProxyBase::ProxyBase (const string& name, const std::string& menu_name, const XMLNode& node) + : _name (name) + , _menu_name (menu_name) + , _window (0) + , _visible (false) + , _x_off (-1) + , _y_off (-1) + , _width (-1) + , _height (-1) + , vistracker (0) +{ + set_state (node); +} + +WindowManager::ProxyBase::~ProxyBase () +{ + delete vistracker; +} + +void +WindowManager::ProxyBase::set_state (const XMLNode& node) +{ + XMLNodeList children = node.children (); + + XMLNodeList::const_iterator i = children.begin (); + + while (i != children.end()) { + XMLProperty* prop = (*i)->property (X_("name")); + if ((*i)->name() == X_("Window") && prop && prop->value() == _name) { + break; + } + + ++i; + } + + if (i != children.end()) { + + XMLProperty* prop; + + if ((prop = (*i)->property (X_("visible"))) != 0) { + _visible = PBD::string_is_affirmative (prop->value ()); + } + + if ((prop = (*i)->property (X_("x-off"))) != 0) { + _x_off = atoi (prop->value().c_str()); + } + if ((prop = (*i)->property (X_("y-off"))) != 0) { + _y_off = atoi (prop->value().c_str()); + } + if ((prop = (*i)->property (X_("x-size"))) != 0) { + _width = atoi (prop->value().c_str()); + } + if ((prop = (*i)->property (X_("y-size"))) != 0) { + _height = atoi (prop->value().c_str()); + } + } + + /* if we have a window already, reset its properties */ + + if (_window) { + setup (); + } +} + +void +WindowManager::ProxyBase::set_action (Glib::RefPtr<Gtk::Action> act) +{ + _action = act; +} + +std::string +WindowManager::ProxyBase::action_name() const +{ + return string_compose (X_("toggle-%1"), _name); +} + +void +WindowManager::ProxyBase::toggle() +{ + if (!_window) { + (void) get (true); + assert (_window); + /* XXX this is a hack - the window object should really + ensure its components are all visible. sigh. + */ + _window->show_all(); + /* we'd like to just call this and nothing else */ + _window->present (); + } else { + vistracker->cycle_visibility (); + } +} + +XMLNode& +WindowManager::ProxyBase::get_state () const +{ + XMLNode* node = new XMLNode (X_("Window")); + char buf[32]; + + node->add_property (X_("name"), _name); + + if (_window && vistracker) { + + /* we have a window, so use current state */ + + _visible = vistracker->partially_visible (); + _window->get_position (_x_off, _y_off); + _window->get_size (_width, _height); + } + + node->add_property (X_("visible"), _visible? X_("yes") : X_("no")); + + snprintf (buf, sizeof (buf), "%d", _x_off); + node->add_property (X_("x-off"), buf); + snprintf (buf, sizeof (buf), "%d", _y_off); + node->add_property (X_("y-off"), buf); + snprintf (buf, sizeof (buf), "%d", _width); + node->add_property (X_("x-size"), buf); + snprintf (buf, sizeof (buf), "%d", _height); + node->add_property (X_("y-size"), buf); + + return *node; +} + +void +WindowManager::ProxyBase::drop_window () +{ + if (_window) { + _window->hide (); + delete _window; + _window = 0; + delete vistracker; + vistracker = 0; + } +} + +void +WindowManager::ProxyBase::use_window (Gtk::Window& win) +{ + drop_window (); + _window = &win; + setup (); +} + +void +WindowManager::ProxyBase::setup () +{ + assert (_window); + + vistracker = new Gtkmm2ext::VisibilityTracker (*_window); + + if (_width != -1 && _height != -1) { + _window->set_default_size (_width, _height); + } + + if (_x_off != -1 && _y_off != -1) { + _window->move (_x_off, _y_off); + } +} + +void +WindowManager::ProxyBase::show () +{ + Gtk::Window* win = get (true); + win->show (); +} + +void +WindowManager::ProxyBase::maybe_show () +{ + if (_visible) { + show (); + } +} + +void +WindowManager::ProxyBase::show_all () +{ + Gtk::Window* win = get (true); + win->show_all (); +} + + +void +WindowManager::ProxyBase::present () +{ + Gtk::Window* win = get (true); + win->show_all (); + win->present (); +} + +void +WindowManager::ProxyBase::hide () +{ + Gtk::Window* win = get (false); + if (win) { + win->hide (); + } +} + diff --git a/gtk2_ardour/window_manager.h b/gtk2_ardour/window_manager.h new file mode 100644 index 0000000000..fb65a8d088 --- /dev/null +++ b/gtk2_ardour/window_manager.h @@ -0,0 +1,194 @@ +/* + Copyright (C) 2013 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __gtk2_ardour_window_manager_h__ +#define __gtk2_ardour_window_manager_h__ + +#include <string> +#include <map> + +#include <boost/function.hpp> +#include <glibmm/refptr.h> +#include <sigc++/trackable.h> + +class XMLNode; + +namespace Gtk { + class Window; + class Action; +} + +namespace Gtkmm2ext { + class VisibilityTracker; +} + +namespace ARDOUR { + class Session; + class SessionHandlePtr; +} + +class WindowManager +{ + public: + static WindowManager& instance(); + + class ProxyBase : public sigc::trackable { + public: + ProxyBase (const std::string& name, const std::string& menu_name); + ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode&); + virtual ~ProxyBase(); + + void show (); + void show_all (); + void hide (); + void present (); + void maybe_show (); + + bool visible() const { return _visible; } + const std::string& name() const { return _name; } + const std::string& menu_name() const { return _menu_name; } + + std::string action_name() const; + void set_action (Glib::RefPtr<Gtk::Action>); + Glib::RefPtr<Gtk::Action> action() const { return _action; }; + + void drop_window (); + void use_window (Gtk::Window&); + + virtual Gtk::Window* get (bool create = false) = 0; + + virtual void toggle (); + + void set_state (const XMLNode&); + XMLNode& get_state () const; + + virtual ARDOUR::SessionHandlePtr* session_handle () = 0; + + operator bool() const { return _window != 0; } + + protected: + std::string _name; + std::string _menu_name; + Glib::RefPtr<Gtk::Action> _action; + Gtk::Window* _window; + mutable bool _visible; ///< true if the window should be visible on startup + mutable int _x_off; ///< x position + mutable int _y_off; ///< y position + mutable int _width; ///< width + mutable int _height; ///< height + Gtkmm2ext::VisibilityTracker* vistracker; + + void setup (); + }; + + template<typename T> + class ProxyWithConstructor: public ProxyBase { + public: + ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c) + : ProxyBase (name, menu_name) , creator (c) {} + + ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c, const XMLNode* node) + : ProxyBase (name, menu_name, node) , creator (c) {} + + Gtk::Window* get (bool create = false) { + if (!_window) { + if (!create) { + return 0; + } + + _window = creator (); + + if (_window) { + setup (); + } + } + + return _window; + } + + T* operator->() { + return dynamic_cast<T*> (get (true)); + } + + ARDOUR::SessionHandlePtr* session_handle () { + /* may return null */ + return dynamic_cast<T*> (_window); + } + + private: + boost::function<T*()> creator; + }; + + template<typename T> + class Proxy : public ProxyBase { + public: + Proxy (const std::string& name, const std::string& menu_name) + : ProxyBase (name, menu_name) {} + + Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node) + : ProxyBase (name, menu_name, node) {} + + Gtk::Window* get (bool create = false) { + if (!_window) { + if (!create) { + return 0; + } + + _window = new T (); + + if (_window) { + setup (); + } + } + + return _window; + } + + T* operator->() { + /* make return null */ + return dynamic_cast<T*> (_window); + } + + ARDOUR::SessionHandlePtr* session_handle () { + return dynamic_cast<T*> (get()); + } + + private: + boost::function<T*()> creator; + }; + + void register_window (ProxyBase*); + void remove (const ProxyBase*); + void toggle_window (ProxyBase*); + void show_visible () const; + void set_session (ARDOUR::Session*); + void add_state (XMLNode&) const; + + private: + typedef std::list<ProxyBase*> Windows; + Windows _windows; + Glib::RefPtr<Gtk::ActionGroup> window_actions; + + WindowManager(); + ~WindowManager(); + + static WindowManager* _instance; +}; + +#endif /* __gtk2_ardour_window_manager_h__ */ diff --git a/gtk2_ardour/window_proxy.cc b/gtk2_ardour/window_proxy.cc deleted file mode 100644 index 99da166af0..0000000000 --- a/gtk2_ardour/window_proxy.cc +++ /dev/null @@ -1,157 +0,0 @@ -/* - Copyright (C) 2010 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include <gtkmm/window.h> -#include "window_proxy.h" - -#include "pbd/convert.h" - -#include "i18n.h" - -using namespace std; - -/** WindowProxyBase constructor. - * @param name Unique internal name for this window. - * @param node <UI> node containing <Window> children, the appropriate one of which is used - * to set up this object. - */ -WindowProxyBase::WindowProxyBase (string const & name, XMLNode const * node) - : _name (name) - , _visible (false) - , _x_off (-1) - , _y_off (-1) - , _width (-1) - , _height (-1) -{ - if (!node) { - return; - } - - XMLNodeList children = node->children (); - - XMLNodeList::const_iterator i = children.begin (); - while (i != children.end()) { - XMLProperty* prop = (*i)->property (X_("name")); - if ((*i)->name() == X_("Window") && prop && prop->value() == _name) { - break; - } - - ++i; - } - - if (i != children.end()) { - - XMLProperty* prop; - - if ((prop = (*i)->property (X_("visible"))) != 0) { - _visible = PBD::string_is_affirmative (prop->value ()); - } - - if ((prop = (*i)->property (X_("x-off"))) != 0) { - _x_off = atoi (prop->value().c_str()); - } - if ((prop = (*i)->property (X_("y-off"))) != 0) { - _y_off = atoi (prop->value().c_str()); - } - if ((prop = (*i)->property (X_("x-size"))) != 0) { - _width = atoi (prop->value().c_str()); - } - if ((prop = (*i)->property (X_("y-size"))) != 0) { - _height = atoi (prop->value().c_str()); - } - } -} - -/** Show this window if it was configured as visible. This should - * be called at session startup only. - */ -void -WindowProxyBase::maybe_show () -{ - if (_visible) { - show (); - } -} - -/** Set up our window's position and size */ -void -WindowProxyBase::setup () -{ - Gtk::Window* window = get_gtk_window (); - if (!window) { - return; - } - - if (_width != -1 && _height != -1) { - window->set_default_size (_width, _height); - } - - if (_x_off != -1 && _y_off != -1) { - window->move (_x_off, _y_off); - } -} - -XMLNode * -WindowProxyBase::get_state () const -{ - bool v = _visible; - int x = _x_off; - int y = _y_off; - int w = _width; - int h = _height; - - /* If the window has been created, get its current state; otherwise use - the state that we started off with. - */ - - Gtk::Window* gtk_window = get_gtk_window (); - if (gtk_window) { - v = gtk_window->is_visible (); - - Glib::RefPtr<Gdk::Window> gdk_window = gtk_window->get_window (); - if (gdk_window) { - gdk_window->get_position (x, y); - gdk_window->get_size (w, h); - } - - } - - return state_node (v, x, y, w, h); -} - - -XMLNode * -WindowProxyBase::state_node (bool v, int x, int y, int w, int h) const -{ - XMLNode* node = new XMLNode (X_("Window")); - node->add_property (X_("name"), _name); - node->add_property (X_("visible"), v ? X_("yes") : X_("no")); - - char buf[32]; - snprintf (buf, sizeof (buf), "%d", x); - node->add_property (X_("x-off"), buf); - snprintf (buf, sizeof (buf), "%d", y); - node->add_property (X_("y-off"), buf); - snprintf (buf, sizeof (buf), "%d", w); - node->add_property (X_("x-size"), buf); - snprintf (buf, sizeof (buf), "%d", h); - node->add_property (X_("y-size"), buf); - - return node; -} diff --git a/gtk2_ardour/window_proxy.h b/gtk2_ardour/window_proxy.h deleted file mode 100644 index 10ff25ced6..0000000000 --- a/gtk2_ardour/window_proxy.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - Copyright (C) 2010 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __ardour_window_proxy_h__ -#define __ardour_window_proxy_h__ - -#include <gtkmm/action.h> -#include <gtkmm/toggleaction.h> -#include "actions.h" - -class XMLNode; - -/** A class to proxy for a window that may not have been created yet. - * It allows the management of visibility, position and size state - * so that it can be saved and restored across session loads. - * - * Subclasses of WindowProxy handle windows that are created in different - * ways. - */ - -class WindowProxyBase -{ -public: - WindowProxyBase (std::string const &, XMLNode const *); - virtual ~WindowProxyBase () {} - - std::string name () const { - return _name; - } - - void maybe_show (); - XMLNode* get_state () const; - void setup (); - - /** Show this window */ - virtual void show () = 0; - - /** @return true if the configuration for this window should be - * global (ie across all sessions), otherwise false if it should - * be session-specific. - */ - virtual bool rc_configured () const = 0; - - virtual Gtk::Window* get_gtk_window () const = 0; - -private: - XMLNode* state_node (bool, int, int, int, int) const; - - std::string _name; ///< internal unique name for this window - bool _visible; ///< true if the window should be visible on startup - int _x_off; ///< x position - int _y_off; ///< y position - int _width; ///< width - int _height; ///< height -}; - -/** Templated WindowProxy which contains a pointer to the window that is proxying for */ -template <class T> -class WindowProxy : public WindowProxyBase -{ -public: - WindowProxy (std::string const & name, XMLNode const * node) - : WindowProxyBase (name, node) - , _window (0) - { - - } - - Gtk::Window* get_gtk_window () const { - return _window; - } - - T* get () const { - return _window; - } - - /** Set the window and maybe set it up. To be used after initial window creation */ - void set (T* w, bool s = true) { - _window = w; - if (s) { - setup (); - } - } - -private: - T* _window; -}; - -/** WindowProxy for windows that are created in response to a GTK Action being set active. - * Templated on the type of the window. - */ -template <class T> -class ActionWindowProxy : public WindowProxy<T> -{ -public: - /** ActionWindowProxy constructor. - * @param name Unique internal name for this window. - * @param node <UI> node containing <Window> children, the appropriate one of which is used - * to set up this object. - * @param action Name of the ToggleAction that controls this window's visibility. - */ - ActionWindowProxy (std::string const & name, XMLNode const * node, std::string const & action) - : WindowProxy<T> (name, node) - , _action (action) - { - - } - - void show () { - /* Set the appropriate action active so that the window gets shown */ - Glib::RefPtr<Gtk::Action> act = ActionManager::get_action ("Common", _action.c_str()); - if (act) { - Glib::RefPtr<Gtk::ToggleAction> tact = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic (act); - assert (tact); - tact->set_active (true); - } - } - - bool rc_configured () const { - return true; - } - -private: - std::string _action; -}; - -#endif diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 90417bf2c1..c473a4569b 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -52,6 +52,7 @@ gtk2_ardour_sources = [ 'automation_streamview.cc', 'automation_time_axis.cc', 'axis_view.cc', + 'big_clock_window.cc', 'bundle_manager.cc', 'button_joiner.cc', 'clock_group.cc', @@ -233,7 +234,7 @@ gtk2_ardour_sources = [ 'version.cc', 'visibility_group.cc', 'volume_controller.cc', - 'window_proxy.cc', + 'window_manager.cc', # video-timeline related sources: 'video_image_frame.cc', 'add_video_dialog.cc', |