first compilable version of tabbable design.

I would have loved to split this apart, but there are just so many interrelated changes,
it makes little sense and would be a huge effort that would break future git bisect
use because so many intermediate commits would not compile
This commit is contained in:
Paul Davis 2015-07-07 22:12:21 -04:00
parent 85eee3b09d
commit 9010262bed
42 changed files with 1007 additions and 1117 deletions

View file

@ -48,6 +48,7 @@
#include "pbd/error.h" #include "pbd/error.h"
#include "pbd/basename.h" #include "pbd/basename.h"
#include "pbd/compose.h" #include "pbd/compose.h"
#include "pbd/convert.h"
#include "pbd/failed_constructor.h" #include "pbd/failed_constructor.h"
#include "pbd/enumwriter.h" #include "pbd/enumwriter.h"
#include "pbd/memento_command.h" #include "pbd/memento_command.h"
@ -110,6 +111,7 @@ typedef uint64_t microseconds_t;
#include "audio_clock.h" #include "audio_clock.h"
#include "audio_region_view.h" #include "audio_region_view.h"
#include "big_clock_window.h" #include "big_clock_window.h"
#include "binding_owners.h"
#include "bundle_manager.h" #include "bundle_manager.h"
#include "duplicate_routes_dialog.h" #include "duplicate_routes_dialog.h"
#include "engine_dialog.h" #include "engine_dialog.h"
@ -224,8 +226,12 @@ libxml_structured_error_func (void* /* parsing_context*/,
ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
<<<<<<< HEAD
: Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp) : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
=======
: Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
>>>>>>> first compilable version of tabbable design.
, session_loaded (false) , session_loaded (false)
, gui_object_state (new GUIObjectState) , gui_object_state (new GUIObjectState)
, primary_clock (new MainClock (X_("primary"), X_("transport"), true )) , primary_clock (new MainClock (X_("primary"), X_("transport"), true ))
@ -262,13 +268,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
, save_as_dialog (0) , save_as_dialog (0)
, meterbridge (0) , meterbridge (0)
, rc_option_editor (0) , rc_option_editor (0)
, open_session_selector (0)
, _numpad_locate_happening (false)
, _session_is_new (false)
, last_key_press_time (0)
, save_as_dialog (0)
, meterbridge (0)
, rc_option_editor (0)
, speaker_config_window (X_("speaker-config"), _("Speaker Configuration")) , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
, key_editor (X_("key-editor"), _("Key Bindings")) , key_editor (X_("key-editor"), _("Key Bindings"))
, add_route_dialog (X_("add-routes"), _("Add Tracks/Busses")) , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
@ -414,20 +413,24 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
const XMLNode* ui_xml = Config->extra_xml (X_("UI")); const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
if (ui_xml) { if (ui_xml) {
key_editor.set_state (*ui_xml); key_editor.set_state (*ui_xml, 0);
// rc_option_editor.set_state (*ui_xml); session_option_editor.set_state (*ui_xml, 0);
session_option_editor.set_state (*ui_xml); speaker_config_window.set_state (*ui_xml, 0);
speaker_config_window.set_state (*ui_xml); about.set_state (*ui_xml, 0);
about.set_state (*ui_xml); add_route_dialog.set_state (*ui_xml, 0);
add_route_dialog.set_state (*ui_xml); add_video_dialog.set_state (*ui_xml, 0);
add_video_dialog.set_state (*ui_xml); route_params.set_state (*ui_xml, 0);
route_params.set_state (*ui_xml); bundle_manager.set_state (*ui_xml, 0);
bundle_manager.set_state (*ui_xml); location_ui.set_state (*ui_xml, 0);
location_ui.set_state (*ui_xml); big_clock_window.set_state (*ui_xml, 0);
big_clock_window.set_state (*ui_xml); audio_port_matrix.set_state (*ui_xml, 0);
audio_port_matrix.set_state (*ui_xml); midi_port_matrix.set_state (*ui_xml, 0);
midi_port_matrix.set_state (*ui_xml); export_video_dialog.set_state (*ui_xml, 0);
export_video_dialog.set_state (*ui_xml);
/* tabbables */
// rc_option_editor->set_state (*ui_xml, 0);
// editor->set_state (*ui_xml, 0);
// mixer->set_state (*ui_xml, 0);
} }
WM::Manager::instance().register_window (&key_editor); WM::Manager::instance().register_window (&key_editor);
@ -540,7 +543,7 @@ was not fast enough. Try to restart\n\
the audio backend and save the session."), PROGRAM_NAME); the audio backend and save the session."), PROGRAM_NAME);
} }
MessageDialog msg (*editor, msgstr); MessageDialog msg (_main_window, msgstr);
pop_back_splash (msg); pop_back_splash (msg);
msg.run (); msg.run ();
@ -1104,7 +1107,6 @@ ARDOUR_UI::check_memory_locking ()
pop_back_splash (msg); pop_back_splash (msg);
editor->ensure_float (msg);
msg.run (); msg.run ();
if (cb.get_active()) { if (cb.get_active()) {
@ -1150,7 +1152,7 @@ ARDOUR_UI::finish()
/* use the default name */ /* use the default name */
if (save_state_canfail ("")) { if (save_state_canfail ("")) {
/* failed - don't quit */ /* failed - don't quit */
MessageDialog msg (*editor, MessageDialog msg (_main_window,
string_compose (_("\ string_compose (_("\
%1 was unable to save your session.\n\n\ %1 was unable to save your session.\n\n\
If you still wish to quit, please use the\n\n\ If you still wish to quit, please use the\n\n\
@ -1765,7 +1767,7 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out
} }
catch (...) { catch (...) {
MessageDialog msg (*editor, MessageDialog msg (_main_window,
string_compose (_("There are insufficient ports available\n\ string_compose (_("There are insufficient ports available\n\
to create a new track or bus.\n\ to create a new track or bus.\n\
You should save %1, exit and\n\ You should save %1, exit and\n\
@ -1826,7 +1828,7 @@ ARDOUR_UI::session_add_audio_route (
} }
catch (...) { catch (...) {
MessageDialog msg (*editor, MessageDialog msg (_main_window,
string_compose (_("There are insufficient ports available\n\ string_compose (_("There are insufficient ports available\n\
to create a new track or bus.\n\ to create a new track or bus.\n\
You should save %1, exit and\n\ You should save %1, exit and\n\
@ -1972,7 +1974,7 @@ ARDOUR_UI::transport_record (bool roll)
switch (_session->record_status()) { switch (_session->record_status()) {
case Session::Disabled: case Session::Disabled:
if (_session->ntracks() == 0) { if (_session->ntracks() == 0) {
MessageDialog msg (*editor, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu.")); MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
msg.run (); msg.run ();
return; return;
} }
@ -3522,7 +3524,7 @@ ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* lis
removed = rep.paths.size(); removed = rep.paths.size();
if (removed == 0) { if (removed == 0) {
MessageDialog msgd (*editor, MessageDialog msgd (_main_window,
_("No files were ready for clean-up"), _("No files were ready for clean-up"),
true, true,
Gtk::MESSAGE_INFO, Gtk::MESSAGE_INFO,
@ -4344,7 +4346,7 @@ void
ARDOUR_UI::halt_on_xrun_message () ARDOUR_UI::halt_on_xrun_message ()
{ {
cerr << "HALT on xrun\n"; cerr << "HALT on xrun\n";
MessageDialog msg (*editor, _("Recording was stopped because your system could not keep up.")); MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
msg.run (); msg.run ();
} }
@ -4373,7 +4375,7 @@ ARDOUR_UI::disk_overrun_handler ()
if (!have_disk_speed_dialog_displayed) { if (!have_disk_speed_dialog_displayed) {
have_disk_speed_dialog_displayed = true; have_disk_speed_dialog_displayed = true;
MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\ MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
The disk system on your computer\n\ The disk system on your computer\n\
was not able to keep up with %1.\n\ was not able to keep up with %1.\n\
\n\ \n\
@ -4508,7 +4510,7 @@ ARDOUR_UI::disk_underrun_handler ()
if (!have_disk_speed_dialog_displayed) { if (!have_disk_speed_dialog_displayed) {
have_disk_speed_dialog_displayed = true; have_disk_speed_dialog_displayed = true;
MessageDialog* msg = new MessageDialog ( MessageDialog* msg = new MessageDialog (
*editor, string_compose (_("The disk system on your computer\n\ _main_window, string_compose (_("The disk system on your computer\n\
was not able to keep up with %1.\n\ was not able to keep up with %1.\n\
\n\ \n\
Specifically, it failed to read data from disk\n\ Specifically, it failed to read data from disk\n\
@ -4532,12 +4534,7 @@ ARDOUR_UI::session_dialog (std::string msg)
MessageDialog* d; MessageDialog* d;
if (editor) { d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
} else {
d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
}
d->show_all (); d->show_all ();
d->run (); d->run ();
delete d; delete d;
@ -5063,15 +5060,110 @@ ARDOUR_UI::hide_application ()
} }
void void
ARDOUR_UI::cancel_solo () ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
{ {
if (_session) { /* icons, titles, WM stuff */
if (_session->soloing()) {
_session->set_solo (_session->get_routes(), false); static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
} else if (_session->listening()) {
_session->set_listen (_session->get_routes(), false); if (window_icons.empty()) {
Glib::RefPtr<Gdk::Pixbuf> icon;
if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
window_icons.push_back (icon);
}
if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
window_icons.push_back (icon);
}
if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
window_icons.push_back (icon);
}
if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
window_icons.push_back (icon);
}
}
if (!window_icons.empty()) {
window.set_default_icon_list (window_icons);
}
Gtkmm2ext::WindowTitle title (Glib::get_application_name());
title += name;
window.set_title (title.get_string());
window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
window.set_flags (CAN_FOCUS);
window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
}
bool
ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* window)
{
switch (ev->type) {
case GDK_KEY_PRESS:
return key_press_handler (ev, window);
default:
break;
}
return key_release_handler (ev, window);
}
bool
ARDOUR_UI::key_press_handler (GdkEventKey* ev, Gtk::Window* event_window)
{
if (event_window == &_main_window) {
/* find current tab contents */
Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
/* see if it uses the ardour binding system */
HasBindings* bindable;
if ((bindable = dynamic_cast<HasBindings*> (w)) != 0) {
KeyboardKey k (ev->state, ev->keyval);
return bindable->bindings().activate (k, Bindings::Press);
} else {
/* no bindings in current tab, use baroque GTK mechanism */
return key_press_focus_accelerator_handler (_main_window, ev);
} }
_session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window } else {
/* no window supplied, try our own bindings */
KeyboardKey k (ev->state, ev->keyval);
return _global_bindings.activate (k, Bindings::Press);
}
}
bool
ARDOUR_UI::key_release_handler (GdkEventKey* ev, Gtk::Window* event_window)
{
if (event_window == &_main_window) {
/* find current tab contents */
Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
/* see if it uses the ardour binding system */
HasBindings* bindable;
if ((bindable = dynamic_cast<HasBindings*> (w)) != 0) {
KeyboardKey k (ev->state, ev->keyval);
return bindable->bindings().activate (k, Bindings::Release);
} else {
/* no bindings in current tab, use baroque GTK mechanism */
return key_press_focus_accelerator_handler (_main_window, ev);
}
} else {
/* no window supplied, try our own bindings */
KeyboardKey k (ev->state, ev->keyval);
return _global_bindings.activate (k, Bindings::Release);
>>>>>>> first compilable version of tabbable design.
} }
} }

View file

@ -53,10 +53,12 @@
#include <gtkmm/menubar.h> #include <gtkmm/menubar.h>
#include <gtkmm/textbuffer.h> #include <gtkmm/textbuffer.h>
#include <gtkmm/adjustment.h> #include <gtkmm/adjustment.h>
#include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/click_box.h> #include "gtkmm2ext/gtk_ui.h"
#include <gtkmm2ext/stateful_button.h> #include "gtkmm2ext/click_box.h"
#include <gtkmm2ext/bindable_button.h> #include "gtkmm2ext/stateful_button.h"
#include "gtkmm2ext/bindable_button.h"
#include "gtkmm2ext/bindings.h"
#include "ardour/ardour.h" #include "ardour/ardour.h"
#include "ardour/types.h" #include "ardour/types.h"
@ -321,14 +323,23 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void hide_application (); void hide_application ();
Gtk::Notebook& tabs(); Gtk::Notebook& tabs();
Gtk::Window& main_window () { return _main_window; }
void setup_toplevel_window (Gtk::Window&, const std::string& name, void* owner);
/* called from a static C function */ /* called from a static C function */
Gtk::Notebook* tab_window_root_drop (GtkNotebook* src, GtkNotebook* tab_window_root_drop (GtkNotebook* src,
GtkWidget* w, GtkWidget* w,
gint x, gint x,
gint y, gint y,
gpointer user_data); gpointer user_data);
bool tabbed_window_state_event_handler (GdkEventWindowState*, void* object);
bool key_press_handler (GdkEventKey*, Gtk::Window* event_window);
bool key_release_handler (GdkEventKey*, Gtk::Window* event_window);
protected: protected:
friend class PublicEditor; friend class PublicEditor;
@ -349,13 +360,21 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void toggle_session_options_window (); void toggle_session_options_window ();
private: private:
Mixer_UI* mixer; Gtk::Window _main_window;
NSM_Client* nsm; Gtk::VBox main_vpacker;
bool _was_dirty; Gtk::HBox status_bar_hpacker;
bool _mixer_on_top; Gtk::Notebook _tabs;
bool _initial_verbose_plugin_scan; PublicEditor* editor;
bool first_time_engine_run; Mixer_UI* mixer;
Gtk::Tooltips _tooltips;
NSM_Client* nsm;
bool _was_dirty;
bool _mixer_on_top;
bool _initial_verbose_plugin_scan;
bool first_time_engine_run;
Gtkmm2ext::Bindings _global_bindings;
void goto_editor_window (); void goto_editor_window ();
void goto_mixer_window (); void goto_mixer_window ();
void toggle_mixer_window (); void toggle_mixer_window ();
@ -397,8 +416,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void start_clocking (); void start_clocking ();
void stop_clocking (); void stop_clocking ();
bool main_window_state_event_handler (GdkEventWindowState*, bool window_was_editor);
void update_transport_clocks (framepos_t pos); void update_transport_clocks (framepos_t pos);
void record_state_changed (); void record_state_changed ();
@ -627,17 +644,16 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void setup_order_hint (AddRouteDialog::InsertAt); void setup_order_hint (AddRouteDialog::InsertAt);
int create_mixer (); int create_mixer ();
PublicEditor *editor;
int create_editor (); int create_editor ();
Meterbridge *meterbridge; Meterbridge *meterbridge;
int create_meterbridge (); int create_meterbridge ();
RCOptionEditor* rc_option_editor;
Gtk::HBox rc_option_editor_placeholder;
/* Dialogs that can be created via new<T> */ /* Dialogs that can be created via new<T> */
RCOptionEditor* rc_option_editor;
Gtk::HBox rc_option_editor_placeholder;
WM::Proxy<SpeakerDialog> speaker_config_window; WM::Proxy<SpeakerDialog> speaker_config_window;
WM::Proxy<KeyEditor> key_editor; WM::Proxy<KeyEditor> key_editor;
WM::Proxy<AddRouteDialog> add_route_dialog; WM::Proxy<AddRouteDialog> add_route_dialog;
@ -811,6 +827,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void grab_focus_after_dialog (); void grab_focus_after_dialog ();
void tabs_switch (GtkNotebookPage*, guint page_number); void tabs_switch (GtkNotebookPage*, guint page_number);
bool key_event_handler (GdkEventKey*, Gtk::Window* window);
}; };
#endif /* __ardour_gui_h__ */ #endif /* __ardour_gui_h__ */

View file

@ -74,12 +74,7 @@ tab_window_root_drop (GtkNotebook* src,
gint y, gint y,
gpointer user_data) gpointer user_data)
{ {
Gtk::Notebook* nb = ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data); return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
if (nb) {
return nb->gobj();
} else {
return 0;
}
} }
int int
@ -125,24 +120,39 @@ ARDOUR_UI::setup_windows ()
top_packer.pack_start (menu_bar_base, false, false); top_packer.pack_start (menu_bar_base, false, false);
#endif #endif
editor->add_toplevel_menu (top_packer); main_vpacker.pack_start (top_packer);
editor->add_transport_frame (transport_frame); /* now add the transport frame to the top of main window */
editor->tabs().append_page (rc_option_editor_placeholder, _("Preferences"));
main_vpacker.pack_start (transport_frame, false, false);
main_vpacker.pack_start (_tabs, true, true);
editor->tabs().signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch)); #ifdef TOP_MENUBAR
main_vpacker.pack_start (status_bar_hpacker, false, false);
#endif
setup_transport();
build_menu_bar ();
setup_tooltips ();
/* pack the main vpacker into the main window and show everything
*/
_main_window.add (main_vpacker);
transport_frame.show_all ();
_main_window.show_all ();
setup_toplevel_window (_main_window, "", this);
rc_option_editor = new RCOptionEditor;
rc_option_editor->add_to_notebook (_tabs, _("Preferences"), 2);
_tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
/* It would be nice if Gtkmm had wrapped this rather than just /* It would be nice if Gtkmm had wrapped this rather than just
* deprecating the old set_window_creation_hook() method, but oh well... * deprecating the old set_window_creation_hook() method, but oh well...
*/ */
g_signal_connect (editor->tabs().gobj(), "create-window", g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
(GCallback) ::tab_window_root_drop, this);
setup_transport();
build_menu_bar ();
setup_tooltips ();
return 0; return 0;
} }
@ -517,7 +527,6 @@ ARDOUR_UI::setup_transport ()
void void
ARDOUR_UI::detach_tearoff (Box* b, Widget* w) ARDOUR_UI::detach_tearoff (Box* b, Widget* w)
{ {
// editor->ensure_float (transport_tearoff->tearoff_window());
b->remove (*w); b->remove (*w);
} }

View file

@ -61,8 +61,8 @@ ARDOUR_UI::we_have_dependents ()
editor->setup_tooltips (); editor->setup_tooltips ();
editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks)); editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
std::cerr << "Mixer page = " << editor->tabs().append_page (*mixer, _("Mixer")) << std::endl; editor->add_to_notebook (_tabs, _("Editor"), 1);
editor->tabs().set_tab_detachable (*mixer); mixer->add_to_notebook (_tabs, _("Mixer"), 1);
/* all actions are defined */ /* all actions are defined */
@ -104,7 +104,7 @@ ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
#endif #endif
} }
Gtk::Notebook* GtkNotebook*
ARDOUR_UI::tab_window_root_drop (GtkNotebook* src, ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
GtkWidget* w, GtkWidget* w,
gint x, gint x,
@ -112,20 +112,34 @@ ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
gpointer) gpointer)
{ {
using namespace std; using namespace std;
Gtk::Notebook* nb = 0;
Gtk::Window* win = 0;
if (w == GTK_WIDGET(mixer->gobj())) { if (w == GTK_WIDGET(mixer->contents().gobj())) {
/* Mixer */ /* Mixer */
cerr << "Call use own window\n"; cerr << "Call use own window, mixer\n";
Gtk::Notebook* nb = mixer->use_own_window (); nb = mixer->tab_root_drop ();
Gtk::Window* win = (Gtk::Window*) nb->get_toplevel (); win = mixer->own_window ();
win->move (x, y); } else if (w == GTK_WIDGET(editor->contents().gobj())) {
win->present ();
/* Editor */
cerr << "Call use own window, editor\n";
nb = editor->tab_root_drop ();
win = editor->own_window ();
return nb;
} }
return 0; if (nb) {
win->move (x, y);
win->show_all ();
win->present ();
return nb->gobj();
}
return 0; /* what was that? */
} }

View file

@ -334,11 +334,18 @@ ARDOUR_UI::goto_editor_window ()
Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000); Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
} }
if (!editor->window_visible()) {
/* goto tab */
editor->show_tab ();
return;
}
editor->show_window (); editor->show_window ();
editor->present (); editor->present ();
/* mixer should now be on top */
if (UIConfiguration::instance().get_transients_follow_front()) { /* editor should now be on top */
WM::Manager::instance().set_transient_for (editor); if (UIConfiguration::instance()->get_transients_follow_front()) {
WM::Manager::instance().set_transient_for (editor->own_window());
} }
_mixer_on_top = false; _mixer_on_top = false;
} }
@ -348,9 +355,9 @@ ARDOUR_UI::goto_mixer_window ()
{ {
Glib::RefPtr<Gdk::Window> win; Glib::RefPtr<Gdk::Window> win;
Glib::RefPtr<Gdk::Screen> screen; Glib::RefPtr<Gdk::Screen> screen;
if (editor) { if (editor && editor->own_window()) {
win = editor->get_window (); win = editor->own_window ()->get_window();
} }
if (win) { if (win) {
@ -387,23 +394,28 @@ ARDOUR_UI::toggle_mixer_window ()
bool show = false; bool show = false;
bool obscuring = false; bool obscuring = false;
if (mixer->not_visible ()) { if (!mixer->window_visible() || editor->window_visible()) {
show = true; return;
}
else if ( (!editor->not_visible () && ARDOUR_UI_UTILS::windows_overlap (editor, mixer))
|| (!meterbridge->not_visible () && ARDOUR_UI_UTILS::windows_overlap (meterbridge, mixer))
) {
obscuring = true;
} }
if (obscuring && (editor->property_has_toplevel_focus() || meterbridge->property_has_toplevel_focus())) {
if (!mixer->window_visible ()) {
show = true;
} else if ( (!editor->not_visible () && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), mixer->own_window()))
|| (!meterbridge->not_visible () && ARDOUR_UI_UTILS::windows_overlap (meterbridge, mixer->own_window()))
) {
obscuring = true;
}
if (obscuring && (editor->own_window()->property_has_toplevel_focus() || meterbridge->property_has_toplevel_focus())) {
show = true; show = true;
} }
if (show) { if (show) {
goto_mixer_window (); goto_mixer_window ();
} else { } else {
mixer->hide_window ((GdkEventAny*)0); mixer->own_window()->hide ();
} }
} }
@ -417,14 +429,12 @@ ARDOUR_UI::toggle_meterbridge ()
if (meterbridge->not_visible ()) { if (meterbridge->not_visible ()) {
show = true; show = true;
} } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
else if ( (!editor->not_visible() && ARDOUR_UI_UTILS::windows_overlap (editor, meterbridge)) (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
|| (!mixer->not_visible () && ARDOUR_UI_UTILS::windows_overlap (meterbridge, mixer))
) {
obscuring = true; obscuring = true;
} }
if (obscuring && (editor->property_has_toplevel_focus() || mixer->property_has_toplevel_focus())) { if (obscuring && (editor->own_window()->property_has_toplevel_focus() || (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
show = true; show = true;
} }
@ -442,25 +452,29 @@ ARDOUR_UI::toggle_editor_mixer ()
{ {
bool obscuring = false; bool obscuring = false;
if (editor && mixer) { if (!mixer->window_visible() || !editor->window_visible()) {
if (ARDOUR_UI_UTILS::windows_overlap (editor, mixer)) { return;
}
if (editor && mixer && mixer->own_window()) {
if (ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), mixer->own_window())) {
obscuring = true; obscuring = true;
} }
} }
if (mixer && !mixer->not_visible() && mixer->property_has_toplevel_focus()) { if (mixer && !mixer->not_visible() && mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()) {
if (obscuring) { if (obscuring) {
goto_editor_window(); goto_editor_window();
} }
} else if (editor && !editor->not_visible() && editor->property_has_toplevel_focus()) { } else if (editor && editor->window_visible() && editor->own_window()->property_has_toplevel_focus()) {
if (obscuring) { if (obscuring) {
goto_mixer_window(); goto_mixer_window();
} }
} else if (mixer && mixer->not_visible()) { } else if (mixer) {
if (obscuring) { if (obscuring) {
goto_mixer_window (); goto_mixer_window ();
} }
} else if (editor && editor->not_visible()) { } else if (editor) {
if (obscuring) { if (obscuring) {
goto_editor_window (); goto_editor_window ();
} }
@ -535,23 +549,23 @@ ARDOUR_UI::handle_locations_change (Location *)
} }
bool bool
ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor) ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
{ {
if (window_was_editor) { if (object == editor) {
if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
(ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
if (big_clock_window) { if (big_clock_window) {
big_clock_window->set_transient_for (*editor); big_clock_window->set_transient_for (*editor->own_window());
} }
} }
} else { } else if (object == mixer) {
if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
(ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
if (big_clock_window) { if (big_clock_window) {
// big_clock_window->set_transient_for (*mixer); big_clock_window->set_transient_for (*mixer->own_window());
} }
} }
} }

View file

@ -86,7 +86,6 @@ ARDOUR_UI::create_editor ()
} }
editor->Realized.connect (sigc::mem_fun (*this, &ARDOUR_UI::editor_realized)); editor->Realized.connect (sigc::mem_fun (*this, &ARDOUR_UI::editor_realized));
editor->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), true));
editor->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), editor)); editor->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), editor));
return 0; return 0;
@ -730,5 +729,5 @@ ARDOUR_UI::xrun_button_release (GdkEventButton* ev)
Gtk::Notebook& Gtk::Notebook&
ARDOUR_UI::tabs() ARDOUR_UI::tabs()
{ {
return editor->tabs(); return _tabs;
} }

View file

@ -47,7 +47,6 @@ ARDOUR_UI::create_mixer ()
return -1; return -1;
} }
mixer->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), false));
mixer->signal_event().connect (sigc::bind (sigc::ptr_fun (&Gtkmm2ext::Keyboard::catch_user_event_for_pre_dialog_focus), mixer)); mixer->signal_event().connect (sigc::bind (sigc::ptr_fun (&Gtkmm2ext::Keyboard::catch_user_event_for_pre_dialog_focus), mixer));
return 0; return 0;
@ -66,8 +65,6 @@ ARDOUR_UI::create_meterbridge ()
return -1; return -1;
} }
meterbridge->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), false));
return 0; return 0;
} }

View file

@ -0,0 +1,43 @@
/*
Copyright (C) 2015 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 __gtk_ardour_binding_owners_h__
#define __gtk_ardour_binding_owners_h__
#include <gtkmm/box.h>
#include "gtkmm2ext/bindings.h"
class HasBindings {
public:
HasBindings (Gtkmm2ext::Bindings& b) : _bindings (b) {}
Gtkmm2ext::Bindings bindings() const { return _bindings; }
protected:
Gtkmm2ext::Bindings& _bindings;
};
class VBoxWithBindings : public Gtk::VBox, public HasBindings
{
public:
VBoxWithBindings (Gtkmm2ext::Bindings& b) : HasBindings (b) {}
};
#endif /* __gtk_ardour_binding_owners_h__ */

View file

@ -252,10 +252,86 @@ pane_size_watcher (Paned* pane)
} }
Editor::Editor () Editor::Editor ()
: _join_object_range_state (JOIN_OBJECT_RANGE_NONE) : PublicEditor (global_hpacker)
, editor_mixer_strip_width (Wide)
, constructed (false)
, _playlist_selector (0)
, no_save_visual (false)
, leftmost_frame (0)
, samples_per_pixel (2048)
, zoom_focus (ZoomFocusPlayhead)
, mouse_mode (MouseObject)
, pre_internal_snap_type (SnapToBeat)
, pre_internal_snap_mode (SnapOff)
, internal_snap_type (SnapToBeat)
, internal_snap_mode (SnapOff)
, _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
, _notebook_shrunk (false)
, location_marker_color (0)
, location_range_color (0)
, location_loop_color (0)
, location_punch_color (0)
, location_cd_marker_color (0)
, entered_marker (0)
, _show_marker_lines (false)
, clicked_axisview (0)
, clicked_routeview (0)
, clicked_regionview (0)
, clicked_selection (0)
, clicked_control_point (0)
, button_release_can_deselect (true)
, _mouse_changed_selection (false) , _mouse_changed_selection (false)
/* time display buttons */ , region_edit_menu_split_item (0)
, region_edit_menu_split_multichannel_item (0)
, track_region_edit_playlist_menu (0)
, track_edit_playlist_submenu (0)
, track_selection_edit_playlist_submenu (0)
, _popup_region_menu_item (0)
, global_vpacker (key_bindings)
, _track_canvas (0)
, _track_canvas_viewport (0)
, within_track_canvas (false)
, _verbose_cursor (0)
, logo_item (0)
, tempo_group (0)
, meter_group (0)
, marker_group (0)
, range_marker_group (0)
, transport_marker_group (0)
, cd_marker_group (0)
, _time_markers_group (0)
, hv_scroll_group (0)
, h_scroll_group (0)
, cursor_scroll_group (0)
, no_scroll_group (0)
, _trackview_group (0)
, _drag_motion_group (0)
, _canvas_drop_zone (0)
, no_ruler_shown_update (false)
, ruler_grabbed_widget (0)
, ruler_dialog (0)
, minsec_mark_interval (0)
, minsec_mark_modulo (0)
, minsec_nmarks (0)
, timecode_mark_modulo (0)
, timecode_nmarks (0)
, _samples_ruler_interval (0)
, bbt_bars (0)
, bbt_nmarks (0)
, bbt_bar_helper_on (0)
, bbt_accent_modulo (0)
, timecode_ruler (0)
, bbt_ruler (0)
, samples_ruler (0)
, minsec_ruler (0)
, visible_timebars (0)
, editor_ruler_menu (0)
, tempo_bar (0)
, meter_bar (0)
, marker_bar (0)
, range_marker_bar (0)
, transport_marker_bar (0)
, cd_marker_bar (0)
, minsec_label (_("Mins:Secs")) , minsec_label (_("Mins:Secs"))
, bbt_label (_("Bars:Beats")) , bbt_label (_("Bars:Beats"))
, timecode_label (_("Timecode")) , timecode_label (_("Timecode"))
@ -267,73 +343,139 @@ Editor::Editor ()
, transport_mark_label (_("Loop/Punch Ranges")) , transport_mark_label (_("Loop/Punch Ranges"))
, cd_mark_label (_("CD Markers")) , cd_mark_label (_("CD Markers"))
, videotl_label (_("Video Timeline")) , videotl_label (_("Video Timeline"))
, videotl_group (0)
, playhead_cursor (0)
, edit_packer (4, 4, true) , edit_packer (4, 4, true)
/* the values here don't matter: layout widgets
reset them as needed.
*/
, vertical_adjustment (0.0, 0.0, 10.0, 400.0) , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
, horizontal_adjustment (0.0, 0.0, 1e16) , horizontal_adjustment (0.0, 0.0, 1e16)
, unused_adjustment (0.0, 0.0, 10.0, 400.0) , unused_adjustment (0.0, 0.0, 10.0, 400.0)
, controls_layout (unused_adjustment, vertical_adjustment) , controls_layout (unused_adjustment, vertical_adjustment)
, _scroll_callbacks (0)
/* tool bar related */ , _visible_canvas_width (0)
, _visible_canvas_height (0)
, toolbar_selection_clock_table (2,3) , _full_canvas_height (0)
, edit_controls_left_menu (0)
, edit_controls_right_menu (0)
, last_update_frame (0)
, cut_buffer_start (0)
, cut_buffer_length (0)
, button_bindings (0)
, last_paste_pos (0)
, paste_count (0)
, sfbrowser (0)
, current_interthread_info (0)
, analysis_window (0)
, select_new_marker (false)
, last_scrub_x (0)
, scrubbing_direction (0)
, scrub_reversals (0)
, scrub_reverse_distance (0)
, have_pending_keyboard_selection (false)
, pending_keyboard_selection_start (0)
, _snap_type (SnapToBeat)
, _snap_mode (SnapOff)
, snap_threshold (5.0)
, ignore_gui_changes (false)
, _drags (new DragManager (this))
, lock_dialog (0)
, last_event_time { 0, 0 }
, _dragging_playhead (false)
, _dragging_edit_point (false)
, _show_measures (true)
, _follow_playhead (true)
, _stationary_playhead (false)
, _maximised (false)
, tempo_lines (0)
, global_rect_group (0)
, time_line_group (0)
, tempo_or_meter_marker_menu (0)
, marker_menu (0)
, range_marker_menu (0)
, transport_marker_menu (0)
, new_transport_marker_menu (0)
, cd_marker_menu (0)
, marker_menu_item (0)
, bbt_beat_subdivision (4)
, _visible_track_count (-1)
, toolbar_selection_clock_table (2,3)
, _mouse_mode_tearoff (0) , _mouse_mode_tearoff (0)
, automation_mode_button (_("mode")) , automation_mode_button (_("mode"))
, _zoom_tearoff (0) , _zoom_tearoff (0)
, _tools_tearoff (0) , _tools_tearoff (0)
, _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
, _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10))) , selection (new Selection (this))
, cut_buffer (new Selection (this))
, _selection_memento (new SelectionMemento())
, _all_region_actions_sensitized (false)
, _ignore_region_action (false)
, _last_region_menu_was_main (false)
, _ignore_follow_edits (false)
, cd_marker_bar_drag_rect (0)
, range_bar_drag_rect (0)
, transport_bar_drag_rect (0)
, transport_bar_range_rect (0)
, transport_bar_preroll_rect (0)
, transport_bar_postroll_rect (0)
, transport_loop_range_rect (0)
, transport_punch_range_rect (0)
, transport_punchin_line (0)
, transport_punchout_line (0)
, transport_preroll_rect (0)
, transport_postroll_rect (0)
, temp_location (0)
, rubberband_rect (0)
, _route_groups (0)
, _routes (0)
, _regions (0)
, _snapshots (0)
, _locations (0)
, autoscroll_horizontal_allowed (false)
, autoscroll_vertical_allowed (false)
, autoscroll_cnt (0)
, autoscroll_widget (0)
, show_gain_after_trim (false)
, selection_op_cmd_depth (0) , selection_op_cmd_depth (0)
, selection_op_history_it (0) , selection_op_history_it (0)
, current_timefx (0)
/* nudge */ , current_mixer_strip (0)
, show_editor_mixer_when_tracks_arrive (false)
, nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true)) , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
, meters_running(false) , current_stepping_trackview (0)
, last_track_height_step_timestamp (0)
, entered_track (0)
, entered_regionview (0)
, clear_entered_track (false)
, _edit_point (EditAtMouse)
, meters_running (false)
, rhythm_ferret (0)
, _have_idled (false)
, resize_idle_id (-1)
, _pending_resize_amount (0)
, _pending_resize_view (0)
, _pending_locate_request (false) , _pending_locate_request (false)
, _pending_initial_locate (false) , _pending_initial_locate (false)
, _summary (0)
, _group_tabs (0)
, _last_motion_y (0)
, layering_order_editor (0)
, _last_cut_copy_source_track (0) , _last_cut_copy_source_track (0)
, _region_selection_change_updates_region_list (true) , _region_selection_change_updates_region_list (true)
, _cursors (0)
, _following_mixer_selection (false) , _following_mixer_selection (false)
, _control_point_toggled_on_press (false) , _control_point_toggled_on_press (false)
, _stepping_axis_view (0) , _stepping_axis_view (0)
, quantize_dialog (0) , quantize_dialog (0)
, _main_menu_disabler (0) , _main_menu_disabler (0)
{ {
constructed = false;
/* we are a singleton */ /* we are a singleton */
PublicEditor::_instance = this; PublicEditor::_instance = this;
_have_idled = false; _have_idled = false;
selection = new Selection (this);
cut_buffer = new Selection (this);
_selection_memento = new SelectionMemento ();
selection_op_history.clear(); selection_op_history.clear();
before.clear(); before.clear();
clicked_regionview = 0;
clicked_axisview = 0;
clicked_routeview = 0;
clicked_selection = 0;
clicked_control_point = 0;
last_update_frame = 0;
last_paste_pos = 0;
paste_count = 0;
_drags = new DragManager (this);
lock_dialog = 0;
ruler_dialog = 0;
current_mixer_strip = 0;
tempo_lines = 0;
snap_type_strings = I18N (_snap_type_strings); snap_type_strings = I18N (_snap_type_strings);
snap_mode_strings = I18N (_snap_mode_strings); snap_mode_strings = I18N (_snap_mode_strings);
zoom_focus_strings = I18N (_zoom_focus_strings); zoom_focus_strings = I18N (_zoom_focus_strings);
@ -351,78 +493,17 @@ Editor::Editor ()
build_snap_type_menu(); build_snap_type_menu();
build_edit_point_menu(); build_edit_point_menu();
snap_threshold = 5.0; location_marker_color = ARDOUR_UI::config()->color ("location marker");
bbt_beat_subdivision = 4; location_range_color = ARDOUR_UI::config()->color ("location range");
_visible_canvas_width = 0; location_cd_marker_color = ARDOUR_UI::config()->color ("location cd marker");
_visible_canvas_height = 0; location_loop_color = ARDOUR_UI::config()->color ("location loop");
autoscroll_horizontal_allowed = false; location_punch_color = ARDOUR_UI::config()->color ("location punch");
autoscroll_vertical_allowed = false;
logo_item = 0;
analysis_window = 0; timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
current_interthread_info = 0;
_show_measures = true;
_maximised = false;
show_gain_after_trim = false;
have_pending_keyboard_selection = false;
_follow_playhead = true;
_stationary_playhead = false;
editor_ruler_menu = 0;
no_ruler_shown_update = false;
marker_menu = 0;
range_marker_menu = 0;
marker_menu_item = 0;
tempo_or_meter_marker_menu = 0;
transport_marker_menu = 0;
new_transport_marker_menu = 0;
editor_mixer_strip_width = Wide;
show_editor_mixer_when_tracks_arrive = false;
region_edit_menu_split_multichannel_item = 0;
region_edit_menu_split_item = 0;
temp_location = 0;
leftmost_frame = 0;
mouse_mode = MouseObject;
current_stepping_trackview = 0;
entered_track = 0;
entered_regionview = 0;
entered_marker = 0;
clear_entered_track = false;
current_timefx = 0;
playhead_cursor = 0;
button_release_can_deselect = true;
_dragging_playhead = false;
_dragging_edit_point = false;
select_new_marker = false;
rhythm_ferret = 0;
layering_order_editor = 0;
no_save_visual = false;
resize_idle_id = -1;
within_track_canvas = false;
scrubbing_direction = 0;
sfbrowser = 0;
location_marker_color = UIConfiguration::instance().color ("location marker");
location_range_color = UIConfiguration::instance().color ("location range");
location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
location_loop_color = UIConfiguration::instance().color ("location loop");
location_punch_color = UIConfiguration::instance().color ("location punch");
zoom_focus = ZoomFocusPlayhead;
_edit_point = EditAtMouse;
_visible_track_count = -1;
samples_per_pixel = 2048; /* too early to use reset_zoom () */
timebar_height = std::max(12., ceil (15. * UIConfiguration::instance().get_ui_scale()));
TimeAxisView::setup_sizes (); TimeAxisView::setup_sizes ();
ArdourMarker::setup_sizes (timebar_height); ArdourMarker::setup_sizes (timebar_height);
_scroll_callbacks = 0;
bbt_label.set_name ("EditorRulerLabel"); bbt_label.set_name ("EditorRulerLabel");
bbt_label.set_size_request (-1, (int)timebar_height); bbt_label.set_size_request (-1, (int)timebar_height);
bbt_label.set_alignment (1.0, 0.5); bbt_label.set_alignment (1.0, 0.5);
@ -660,20 +741,8 @@ Editor::Editor ()
global_vpacker.pack_start (top_hbox, false, false); global_vpacker.pack_start (top_hbox, false, false);
global_vpacker.pack_start (*hbox, true, true); global_vpacker.pack_start (*hbox, true, true);
global_hpacker.pack_start (global_vpacker, true, true); global_hpacker.pack_start (global_vpacker, true, true);
set_name ("EditorWindow");
add_accel_group (ActionManager::ui_manager->get_accel_group());
status_bar_hpacker.show ();
_tabs.append_page (global_hpacker, _("Editor"));
_tabs.show ();
vpacker.pack_end (status_bar_hpacker, false, false);
vpacker.pack_end (_tabs, true, true);
/* register actions now so that set_state() can find them and set toggles/checks etc */ /* register actions now so that set_state() can find them and set toggles/checks etc */
register_actions (); register_actions ();
@ -684,19 +753,6 @@ Editor::Editor ()
setup_toolbar (); setup_toolbar ();
set_zoom_focus (zoom_focus);
set_visible_track_count (_visible_track_count);
_snap_type = SnapToBeat;
set_snap_to (_snap_type);
_snap_mode = SnapOff;
set_snap_mode (_snap_mode);
set_mouse_mode (MouseObject, true);
pre_internal_snap_type = _snap_type;
pre_internal_snap_mode = _snap_mode;
internal_snap_type = _snap_type;
internal_snap_mode = _snap_mode;
set_edit_point_preference (EditAtMouse, true);
_playlist_selector = new PlaylistSelector(); _playlist_selector = new PlaylistSelector();
_playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector))); _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
@ -712,39 +768,6 @@ Editor::Editor ()
fade_context_menu.set_name ("ArdourContextMenu"); fade_context_menu.set_name ("ArdourContextMenu");
/* icons, titles, WM stuff */
list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
Glib::RefPtr<Gdk::Pixbuf> icon;
if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
window_icons.push_back (icon);
}
if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
window_icons.push_back (icon);
}
if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
window_icons.push_back (icon);
}
if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
window_icons.push_back (icon);
}
if (!window_icons.empty()) {
// set_icon_list (window_icons);
set_default_icon_list (window_icons);
}
WindowTitle title(Glib::get_application_name());
title += _("Editor");
set_title (title.get_string());
set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
add (vpacker);
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released)); Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
/* allow external control surfaces/protocols to do various things */ /* allow external control surfaces/protocols to do various things */
@ -845,21 +868,6 @@ Editor::button_settings () const
return node; return node;
} }
void
Editor::add_toplevel_menu (Container& cont)
{
vpacker.pack_start (cont, false, false);
cont.show_all ();
}
void
Editor::add_transport_frame (Container& cont)
{
global_vpacker.pack_start (cont, false, false);
global_vpacker.reorder_child (cont, 0);
cont.show_all ();
}
bool bool
Editor::get_smart_mode () const Editor::get_smart_mode () const
{ {
@ -929,44 +937,6 @@ Editor::set_entered_track (TimeAxisView* tav)
} }
} }
void
Editor::show_window ()
{
if (!is_visible ()) {
DisplaySuspender ds;
show_all ();
/* XXX: this is a bit unfortunate; it would probably
be nicer if we could just call show () above rather
than needing the show_all ()
*/
/* re-hide stuff if necessary */
editor_list_button_toggled ();
parameter_changed ("show-summary");
parameter_changed ("show-group-tabs");
parameter_changed ("show-zoom-tools");
/* now reset all audio_time_axis heights, because widgets might need
to be re-hidden
*/
TimeAxisView *tv;
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
tv = (static_cast<TimeAxisView*>(*i));
tv->reset_height ();
}
if (current_mixer_strip) {
current_mixer_strip->hide_things ();
current_mixer_strip->parameter_changed ("mixer-element-visibility");
}
}
present ();
}
void void
Editor::instant_save () Editor::instant_save ()
{ {
@ -1159,14 +1129,11 @@ Editor::access_action (std::string action_group, std::string action_item)
void void
Editor::on_realize () Editor::on_realize ()
{ {
Window::on_realize ();
Realized (); Realized ();
if (UIConfiguration::instance().get_lock_gui_after_seconds()) { if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
start_lock_event_timing (); start_lock_event_timing ();
} }
signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
} }
void void
@ -1186,7 +1153,9 @@ Editor::generic_event_handler (GdkEvent* ev)
case GDK_MOTION_NOTIFY: case GDK_MOTION_NOTIFY:
case GDK_KEY_PRESS: case GDK_KEY_PRESS:
case GDK_KEY_RELEASE: case GDK_KEY_RELEASE:
gettimeofday (&last_event_time, 0); if (contents().is_mapped()) {
gettimeofday (&last_event_time, 0);
}
break; break;
case GDK_LEAVE_NOTIFY: case GDK_LEAVE_NOTIFY:
@ -1283,8 +1252,12 @@ Editor::center_screen_internal (framepos_t frame, float page)
void void
Editor::update_title () Editor::update_title ()
{ {
ENSURE_GUI_THREAD (*this, &Editor::update_title) ENSURE_GUI_THREAD (*this, &Editor::update_title);
if (!own_window()) {
return;
}
if (_session) { if (_session) {
bool dirty = _session->dirty(); bool dirty = _session->dirty();
@ -1302,7 +1275,7 @@ Editor::update_title ()
WindowTitle title(session_name); WindowTitle title(session_name);
title += Glib::get_application_name(); title += Glib::get_application_name();
set_title (title.get_string()); own_window()->set_title (title.get_string());
} else { } else {
/* ::session_going_away() will have taken care of it */ /* ::session_going_away() will have taken care of it */
} }
@ -2203,55 +2176,14 @@ Editor::set_edit_point_preference (EditPoint ep, bool force)
} }
int int
Editor::set_state (const XMLNode& node, int /*version*/) Editor::set_state (const XMLNode& node, int version)
{ {
const XMLProperty* prop; const XMLProperty* prop;
XMLNode* geometry;
int x, y;
Gdk::Geometry g;
set_id (node); set_id (node);
g.base_width = default_width; Tabbable::set_state (node, version);
g.base_height = default_height;
x = 1;
y = 1;
if ((geometry = find_named_node (node, "geometry")) != 0) {
XMLProperty* prop;
if ((prop = geometry->property("x_size")) == 0) {
prop = geometry->property ("x-size");
}
if (prop) {
g.base_width = atoi(prop->value());
}
if ((prop = geometry->property("y_size")) == 0) {
prop = geometry->property ("y-size");
}
if (prop) {
g.base_height = atoi(prop->value());
}
if ((prop = geometry->property ("x_pos")) == 0) {
prop = geometry->property ("x-pos");
}
if (prop) {
x = atoi (prop->value());
}
if ((prop = geometry->property ("y_pos")) == 0) {
prop = geometry->property ("y-pos");
}
if (prop) {
y = atoi (prop->value());
}
}
set_default_size (g.base_width, g.base_height);
move (x, y);
if (_session && (prop = node.property ("playhead"))) { if (_session && (prop = node.property ("playhead"))) {
framepos_t pos; framepos_t pos;
sscanf (prop->value().c_str(), "%" PRIi64, &pos); sscanf (prop->value().c_str(), "%" PRIi64, &pos);
@ -2475,99 +2407,82 @@ Editor::set_state (const XMLNode& node, int /*version*/)
XMLNode& XMLNode&
Editor::get_state () Editor::get_state ()
{ {
XMLNode* node = new XMLNode ("Editor"); XMLNode& node (Tabbable::get_state());
char buf[32]; char buf[32];
id().print (buf, sizeof (buf)); id().print (buf, sizeof (buf));
node->add_property ("id", buf); node.add_property ("id", buf);
if (is_realized()) { #if 0
Glib::RefPtr<Gdk::Window> win = get_window(); // need to save this somehow
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
geometry->add_property("edit-horizontal-pane-pos", string(buf));
geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
geometry->add_property("edit-vertical-pane-pos", string(buf));
#endif
maybe_add_mixer_strip_width (node);
int x, y, width, height; node.add_property ("zoom-focus", enum_2_string (zoom_focus));
win->get_root_origin(x, y);
win->get_size(width, height);
XMLNode* geometry = new XMLNode ("geometry");
snprintf(buf, sizeof(buf), "%d", width);
geometry->add_property("x-size", string(buf));
snprintf(buf, sizeof(buf), "%d", height);
geometry->add_property("y-size", string(buf));
snprintf(buf, sizeof(buf), "%d", x);
geometry->add_property("x-pos", string(buf));
snprintf(buf, sizeof(buf), "%d", y);
geometry->add_property("y-pos", string(buf));
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
geometry->add_property("edit-horizontal-pane-pos", string(buf));
geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
geometry->add_property("edit-vertical-pane-pos", string(buf));
node->add_child_nocopy (*geometry);
}
maybe_add_mixer_strip_width (*node);
node->add_property ("zoom-focus", enum_2_string (zoom_focus));
snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel); snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
node->add_property ("zoom", buf); node.add_property ("zoom", buf);
node->add_property ("snap-to", enum_2_string (_snap_type)); node.add_property ("snap-to", enum_2_string (_snap_type));
node->add_property ("snap-mode", enum_2_string (_snap_mode)); node.add_property ("snap-mode", enum_2_string (_snap_mode));
node->add_property ("internal-snap-to", enum_2_string (internal_snap_type)); node.add_property ("internal-snap-to", enum_2_string (internal_snap_type));
node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode)); node.add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type)); node.add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode)); node.add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
node->add_property ("edit-point", enum_2_string (_edit_point)); node.add_property ("edit-point", enum_2_string (_edit_point));
snprintf (buf, sizeof(buf), "%d", _visible_track_count); snprintf (buf, sizeof(buf), "%d", _visible_track_count);
node->add_property ("visible-track-count", buf); node.add_property ("visible-track-count", buf);
snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ()); snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
node->add_property ("playhead", buf); node.add_property ("playhead", buf);
snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame); snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
node->add_property ("left-frame", buf); node.add_property ("left-frame", buf);
snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ()); snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
node->add_property ("y-origin", buf); node.add_property ("y-origin", buf);
node->add_property ("show-measures", _show_measures ? "yes" : "no"); node.add_property ("show-measures", _show_measures ? "yes" : "no");
node->add_property ("maximised", _maximised ? "yes" : "no"); node.add_property ("maximised", _maximised ? "yes" : "no");
node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); node.add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no"); node.add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ())); node.add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
node->add_property ("mouse-mode", enum2str(mouse_mode)); node.add_property ("mouse-mode", enum2str(mouse_mode));
node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no"); node.add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer")); Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
if (act) { if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no"); node.add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
} }
act = ActionManager::get_action (X_("Editor"), X_("show-editor-list")); act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
if (act) { if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no"); node.add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
} }
snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ()); snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
node->add_property (X_("editor-list-page"), buf); node.add_property (X_("editor-list-page"), buf);
if (button_bindings) { if (button_bindings) {
XMLNode* bb = new XMLNode (X_("Buttons")); XMLNode* bb = new XMLNode (X_("Buttons"));
button_bindings->save (*bb); button_bindings->save (*bb);
node->add_child_nocopy (*bb); node.add_child_nocopy (*bb);
} }
node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no"); node.add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
node->add_child_nocopy (selection->get_state ()); node.add_child_nocopy (selection->get_state ());
node->add_child_nocopy (_regions->get_state ()); node.add_child_nocopy (_regions->get_state ());
snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration()); snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
node->add_property ("nudge-clock-value", buf); node.add_property ("nudge-clock-value", buf);
return *node; return node;
} }
/** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
@ -3835,7 +3750,7 @@ bool
Editor::edit_controls_button_release (GdkEventButton* ev) Editor::edit_controls_button_release (GdkEventButton* ev)
{ {
if (Keyboard::is_context_menu_event (ev)) { if (Keyboard::is_context_menu_event (ev)) {
ARDOUR_UI::instance()->add_route (this); ARDOUR_UI::instance()->add_route (current_toplevel());
} else if (ev->button == 1) { } else if (ev->button == 1) {
selection->clear_tracks (); selection->clear_tracks ();
} }
@ -3895,12 +3810,6 @@ Editor::cycle_zoom_focus ()
} }
} }
void
Editor::ensure_float (Window& win)
{
win.set_transient_for (*this);
}
void void
Editor::pane_allocation_handler (Allocation &alloc, Paned* which) Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
{ {
@ -4292,7 +4201,7 @@ Editor::maximise_editing_space ()
return; return;
} }
fullscreen (); current_toplevel()->fullscreen ();
_maximised = true; _maximised = true;
} }
@ -4304,7 +4213,7 @@ Editor::restore_editing_space ()
return; return;
} }
unfullscreen(); current_toplevel()->unfullscreen();
_maximised = false; _maximised = false;
} }
@ -4377,13 +4286,14 @@ Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
bool bool
Editor::on_key_press_event (GdkEventKey* ev) Editor::on_key_press_event (GdkEventKey* ev)
{ {
return key_press_focus_accelerator_handler (*this, ev); return key_press_focus_accelerator_handler (*current_toplevel(), ev);
} }
bool bool
Editor::on_key_release_event (GdkEventKey* ev) Editor::on_key_release_event (GdkEventKey* ev)
{ {
return Gtk::Window::on_key_release_event (ev); return false;
// return Gtk::Window::on_key_release_event (ev);
// return key_press_focus_accelerator_handler (*this, ev); // return key_press_focus_accelerator_handler (*this, ev);
} }
@ -5091,7 +5001,7 @@ Editor::first_idle ()
if (track_views.size() > 1) { if (track_views.size() > 1) {
Timers::TimerSuspender t; Timers::TimerSuspender t;
dialog = new MessageDialog ( dialog = new MessageDialog (
*this, *current_toplevel(),
string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME), string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
true true
); );
@ -5664,7 +5574,7 @@ Editor::super_rapid_screen_update ()
/* METERING / MIXER STRIPS */ /* METERING / MIXER STRIPS */
/* update track meters, if required */ /* update track meters, if required */
if (is_mapped() && meters_running) { if (contents().is_mapped() && meters_running) {
RouteTimeAxisView* rtv; RouteTimeAxisView* rtv;
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) { if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
@ -5794,12 +5704,15 @@ Editor::session_going_away ()
stop_step_editing (); stop_step_editing ();
/* get rid of any existing editor mixer strip */ if (own_window()) {
WindowTitle title(Glib::get_application_name()); /* get rid of any existing editor mixer strip */
title += _("Editor");
WindowTitle title(Glib::get_application_name());
set_title (title.get_string()); title += _("Editor");
own_window()->set_title (title.get_string());
}
SessionHandlePtr::session_going_away (); SessionHandlePtr::session_going_away ();
} }
@ -6031,3 +5944,55 @@ Editor::ui_parameter_changed (string parameter)
} }
} }
} }
Gtk::Window*
Editor::use_own_window ()
{
bool new_window = !own_window();
Gtk::Window* win = Tabbable::use_own_window ();
if (win && new_window) {
win->set_name ("EditorWindow");
win->add_accel_group (ActionManager::ui_manager->get_accel_group());
ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
// win->signal_realize().connect (*this, &Editor::on_realize);
win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
update_title ();
}
DisplaySuspender ds;
contents().show_all ();
/* XXX: this is a bit unfortunate; it would probably
be nicer if we could just call show () above rather
than needing the show_all ()
*/
/* re-hide stuff if necessary */
editor_list_button_toggled ();
parameter_changed ("show-summary");
parameter_changed ("show-group-tabs");
parameter_changed ("show-zoom-tools");
/* now reset all audio_time_axis heights, because widgets might need
to be re-hidden
*/
TimeAxisView *tv;
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
tv = (static_cast<TimeAxisView*>(*i));
tv->reset_height ();
}
if (current_mixer_strip) {
current_mixer_strip->hide_things ();
current_mixer_strip->parameter_changed ("mixer-element-visibility");
}
return win;
}

View file

@ -54,6 +54,7 @@
#include "ardour_button.h" #include "ardour_button.h"
#include "ardour_dialog.h" #include "ardour_dialog.h"
#include "ardour_dropdown.h" #include "ardour_dropdown.h"
#include "binding_owners.h"
#include "public_editor.h" #include "public_editor.h"
#include "editing.h" #include "editing.h"
#include "enums.h" #include "enums.h"
@ -143,6 +144,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void set_session (ARDOUR::Session *); void set_session (ARDOUR::Session *);
ARDOUR::Session* session() const { return _session; } ARDOUR::Session* session() const { return _session; }
Gtk::Window* use_own_window ();
void first_idle (); void first_idle ();
virtual bool have_idled () const { return _have_idled; } virtual bool have_idled () const { return _have_idled; }
@ -286,10 +289,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
bool process_midi_export_dialog (MidiExportDialog& dialog, boost::shared_ptr<ARDOUR::MidiRegion> midi_region); bool process_midi_export_dialog (MidiExportDialog& dialog, boost::shared_ptr<ARDOUR::MidiRegion> midi_region);
void add_transport_frame (Gtk::Container&);
void add_toplevel_menu (Gtk::Container&);
Gtk::HBox& get_status_bar_packer() { return status_bar_hpacker; }
void set_zoom_focus (Editing::ZoomFocus); void set_zoom_focus (Editing::ZoomFocus);
Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; } Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; }
framecnt_t get_current_zoom () const { return samples_per_pixel; } framecnt_t get_current_zoom () const { return samples_per_pixel; }
@ -367,8 +366,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void ensure_float (Gtk::Window&); void ensure_float (Gtk::Window&);
void show_window ();
void scroll_tracks_down_line (); void scroll_tracks_down_line ();
void scroll_tracks_up_line (); void scroll_tracks_up_line ();
@ -561,6 +558,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void color_handler (); void color_handler ();
bool constructed; bool constructed;
Gtkmm2ext::Bindings key_bindings;
// to keep track of the playhead position for control_scroll // to keep track of the playhead position for control_scroll
boost::optional<framepos_t> _control_scroll_target; boost::optional<framepos_t> _control_scroll_target;
@ -783,8 +781,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void timeaxisview_deleted (TimeAxisView *); void timeaxisview_deleted (TimeAxisView *);
Gtk::HBox global_hpacker; Gtk::HBox global_hpacker;
Gtk::VBox global_vpacker; VBoxWithBindings global_vpacker;
Gtk::VBox vpacker;
/* Cursor stuff. Do not use directly, use via CursorContext. */ /* Cursor stuff. Do not use directly, use via CursorContext. */
friend class CursorContext; friend class CursorContext;
@ -820,13 +817,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
Gtk::VBox time_bars_vbox; Gtk::VBox time_bars_vbox;
ArdourCanvas::Pixbuf *logo_item; ArdourCanvas::Pixbuf *logo_item;
#if 0
/* these will be needed when we have canvas rulers */
ArdourCanvas::Container *minsec_group;
ArdourCanvas::Container *bbt_group;
ArdourCanvas::Container *timecode_group;
ArdourCanvas::Container *frame_group;
#endif
ArdourCanvas::Container *tempo_group; ArdourCanvas::Container *tempo_group;
ArdourCanvas::Container *meter_group; ArdourCanvas::Container *meter_group;
@ -1193,7 +1183,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void load_bindings (); void load_bindings ();
Gtkmm2ext::ActionMap editor_action_map; Gtkmm2ext::ActionMap editor_action_map;
Gtkmm2ext::Bindings key_bindings;
/* CUT/COPY/PASTE */ /* CUT/COPY/PASTE */
@ -1867,10 +1856,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
ArdourCanvas::Rectangle* cd_marker_bar_drag_rect; ArdourCanvas::Rectangle* cd_marker_bar_drag_rect;
ArdourCanvas::Rectangle* range_bar_drag_rect; ArdourCanvas::Rectangle* range_bar_drag_rect;
ArdourCanvas::Rectangle* transport_bar_drag_rect; ArdourCanvas::Rectangle* transport_bar_drag_rect;
#ifdef GTKOSX
ArdourCanvas::Rectangle *bogus_background_rect;
#endif
ArdourCanvas::Rectangle *transport_bar_range_rect; ArdourCanvas::Rectangle *transport_bar_range_rect;
ArdourCanvas::Rectangle *transport_bar_preroll_rect; ArdourCanvas::Rectangle *transport_bar_preroll_rect;
ArdourCanvas::Rectangle *transport_bar_postroll_rect; ArdourCanvas::Rectangle *transport_bar_postroll_rect;
@ -2128,8 +2113,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void history_changed (); void history_changed ();
Gtk::HBox status_bar_hpacker;
Editing::EditPoint _edit_point; Editing::EditPoint _edit_point;
ArdourDropdown edit_point_selector; ArdourDropdown edit_point_selector;

View file

@ -2062,11 +2062,8 @@ Editor::register_region_actions ()
sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint) sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)
); );
Glib::RefPtr<Action> a = reg_sens (_region_actions, "choose-top-region", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), false)); reg_sens (_region_actions, "choose-top-region", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), false));
a->set_accel_group (get_accel_group ()); reg_sens (_region_actions, "choose-top-region-context-menu", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), true));
a = reg_sens (_region_actions, "choose-top-region-context-menu", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), true));
a->set_accel_group (get_accel_group ());
_all_region_actions_sensitized = true; _all_region_actions_sensitized = true;

View file

@ -39,7 +39,7 @@ Editor::start_updating_meters ()
{ {
RouteTimeAxisView* rtv; RouteTimeAxisView* rtv;
if (is_mapped() && _session) { if (contents().is_mapped() && _session) {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) { if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
rtv->reset_meter (); rtv->reset_meter ();
@ -57,7 +57,7 @@ Editor::stop_updating_meters ()
meters_running = false; meters_running = false;
if (is_mapped() && _session) { if (contents().is_mapped() && _session) {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) { if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
rtv->hide_meter (); rtv->hide_meter ();

View file

@ -500,7 +500,13 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
void void
Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers) Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
{ {
if (!UIConfiguration::instance().get_autoscroll_editor () || autoscroll_active ()) { Gtk::Window* toplevel = dynamic_cast<Gtk::Window*>(contents().get_toplevel());
if (!toplevel) {
return;
}
if (!UIConfiguration::instance()->get_autoscroll_editor () || autoscroll_active ()) {
return; return;
} }
@ -557,7 +563,7 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
int x, y; int x, y;
Gdk::ModifierType mask; Gdk::ModifierType mask;
get_window()->get_pointer (x, y, mask); toplevel->get_window()->get_pointer (x, y, mask);
if ((allow_horiz && ((x < scrolling_boundary.x0 && leftmost_frame > 0) || x >= scrolling_boundary.x1)) || if ((allow_horiz && ((x < scrolling_boundary.x0 && leftmost_frame > 0) || x >= scrolling_boundary.x1)) ||
(allow_vert && ((y < scrolling_boundary.y0 && vertical_adjustment.get_value() > 0)|| y >= scrolling_boundary.y1))) { (allow_vert && ((y < scrolling_boundary.y0 && vertical_adjustment.get_value() > 0)|| y >= scrolling_boundary.y1))) {
@ -578,8 +584,13 @@ Editor::autoscroll_canvas ()
Gdk::ModifierType mask; Gdk::ModifierType mask;
frameoffset_t dx = 0; frameoffset_t dx = 0;
bool no_stop = false; bool no_stop = false;
Gtk::Window* toplevel = dynamic_cast<Gtk::Window*>(contents().get_toplevel());
get_window()->get_pointer (x, y, mask); if (!toplevel) {
return false;
}
toplevel->get_window()->get_pointer (x, y, mask);
VisualChange vc; VisualChange vc;
bool vertical_motion = false; bool vertical_motion = false;
@ -682,7 +693,7 @@ Editor::autoscroll_canvas ()
int cx; int cx;
int cy; int cy;
translate_coordinates (*_track_canvas, x, y, cx, cy); toplevel->translate_coordinates (*_track_canvas, x, y, cx, cy);
/* clamp x and y to remain within the autoscroll boundary, /* clamp x and y to remain within the autoscroll boundary,
* which is defined in window coordinates * which is defined in window coordinates
@ -733,8 +744,8 @@ Editor::autoscroll_canvas ()
x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1); x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1);
} }
y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1); y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1);
translate_coordinates (*_track_canvas_viewport, x, y, cx, cy); toplevel->translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy)); ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
ev.x = d.x; ev.x = d.x;

View file

@ -3767,7 +3767,7 @@ MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i)
assert (_marker); assert (_marker);
_points.push_back (ArdourCanvas::Duple (0, 0)); _points.push_back (ArdourCanvas::Duple (0, 0));
_points.push_back (ArdourCanvas::Duple (0, physical_screen_height (_editor->get_window()))); _points.push_back (ArdourCanvas::Duple (0, physical_screen_height (_editor->current_toplevel()->get_window())));
} }
MarkerDrag::~MarkerDrag () MarkerDrag::~MarkerDrag ()
@ -5139,7 +5139,7 @@ RangeMarkerBarDrag::RangeMarkerBarDrag (Editor* e, ArdourCanvas::Item* i, Operat
_drag_rect = new ArdourCanvas::Rectangle (_editor->time_line_group, _drag_rect = new ArdourCanvas::Rectangle (_editor->time_line_group,
ArdourCanvas::Rect (0.0, 0.0, 0.0, ArdourCanvas::Rect (0.0, 0.0, 0.0,
physical_screen_height (_editor->get_window()))); physical_screen_height (_editor->current_toplevel()->get_window())));
_drag_rect->hide (); _drag_rect->hide ();
_drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag rect")); _drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag rect"));

View file

@ -78,7 +78,7 @@ Editor::show_editor_mixer (bool yn)
show_editor_mixer_when_tracks_arrive = false; show_editor_mixer_when_tracks_arrive = false;
if (yn) { if (yn) {
Glib::RefPtr<Gdk::Window> win = get_window (); Glib::RefPtr<Gdk::Window> win = current_toplevel()->get_window ();
Glib::RefPtr<Gdk::Screen> screen; Glib::RefPtr<Gdk::Screen> screen;
if (win) { if (win) {

View file

@ -2782,7 +2782,7 @@ Editor::rename_region ()
return; return;
} }
ArdourDialog d (*this, _("Rename Region"), true, false); ArdourDialog d (*current_toplevel(), _("Rename Region"), true, false);
Entry entry; Entry entry;
Label label (_("New name:")); Label label (_("New name:"));
HBox hbox; HBox hbox;
@ -7597,7 +7597,7 @@ Editor::fit_tracks (TrackViewList & tracks)
double first_y_pos = DBL_MAX; double first_y_pos = DBL_MAX;
if (h < TimeAxisView::preset_height (HeightSmall)) { if (h < TimeAxisView::preset_height (HeightSmall)) {
MessageDialog msg (*this, _("There are too many tracks to fit in the current window")); MessageDialog msg (*current_toplevel(), _("There are too many tracks to fit in the current window"));
/* too small to be displayed */ /* too small to be displayed */
return; return;
} }

View file

@ -27,7 +27,7 @@
#include "i18n.h" #include "i18n.h"
FloatingTextEntry::FloatingTextEntry (const std::string& initial_contents) FloatingTextEntry::FloatingTextEntry (Gtk::Window* parent, const std::string& initial_contents)
: Gtk::Window (Gtk::WINDOW_POPUP) : Gtk::Window (Gtk::WINDOW_POPUP)
, entry_changed (false) , entry_changed (false)
{ {
@ -44,7 +44,10 @@ FloatingTextEntry::FloatingTextEntry (const std::string& initial_contents)
entry.signal_activate().connect (sigc::mem_fun (*this, &FloatingTextEntry::activated)); entry.signal_activate().connect (sigc::mem_fun (*this, &FloatingTextEntry::activated));
entry.signal_key_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::key_press)); entry.signal_key_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::key_press));
entry.signal_button_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::button_press)); entry.signal_button_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::button_press));
PublicEditor::instance ().signal_focus_out_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::entry_focus_out));
if (parent) {
parent->signal_focus_out_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::entry_focus_out));
}
add (entry); add (entry);
} }

View file

@ -26,7 +26,7 @@
class FloatingTextEntry : public Gtk::Window class FloatingTextEntry : public Gtk::Window
{ {
public: public:
FloatingTextEntry (const std::string& initial_contents); FloatingTextEntry (Gtk::Window* parent, const std::string& initial_contents);
sigc::signal1<void,std::string> use_text; sigc::signal1<void,std::string> use_text;

View file

@ -256,7 +256,7 @@ Meterbridge::on_key_press_event (GdkEventKey* ev)
if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) { if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
return true; return true;
} }
return forward_key_press (ev); return relay_key_press (ev);
} }
bool bool

View file

@ -89,8 +89,7 @@ Mixer_UI::instance ()
} }
Mixer_UI::Mixer_UI () Mixer_UI::Mixer_UI ()
: _parent_window (0) : Tabbable (_content, _("Mixer"))
, _visible (false)
, no_track_list_redisplay (false) , no_track_list_redisplay (false)
, in_group_row_change (false) , in_group_row_change (false)
, track_menu (0) , track_menu (0)
@ -237,19 +236,16 @@ Mixer_UI::Mixer_UI ()
list_hpane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::pane_allocation_handler), list_hpane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::pane_allocation_handler),
static_cast<Gtk::Paned*> (&list_hpane))); static_cast<Gtk::Paned*> (&list_hpane)));
pack_start (list_hpane, true, true); _content.pack_start (list_hpane, true, true);
set_name ("MixerWindow");
update_title (); update_title ();
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
route_group_display_button_box->show(); route_group_display_button_box->show();
route_group_add_button->show(); route_group_add_button->show();
route_group_remove_button->show(); route_group_remove_button->show();
show (); _content.show ();
_content.set_name ("MixerWindow");
global_hpacker.show(); global_hpacker.show();
scroller.show(); scroller.show();
@ -299,15 +295,6 @@ Mixer_UI::track_editor_selection ()
PublicEditor::instance().get_selection().TracksChanged.connect (sigc::mem_fun (*this, &Mixer_UI::follow_editor_selection)); PublicEditor::instance().get_selection().TracksChanged.connect (sigc::mem_fun (*this, &Mixer_UI::follow_editor_selection));
} }
void
Mixer_UI::ensure_float (Window& win)
{
if (_parent_window) {
win.set_transient_for (*_parent_window);
}
}
Gtk::Notebook* Gtk::Notebook*
Mixer_UI::use_own_window () Mixer_UI::use_own_window ()
{ {
@ -418,7 +405,6 @@ Mixer_UI::hide_window (GdkEventAny *ev)
return true; return true;
} }
void void
Mixer_UI::add_strips (RouteList& routes) Mixer_UI::add_strips (RouteList& routes)
{ {
@ -871,7 +857,7 @@ Mixer_UI::set_session (Session* sess)
refill_favorite_plugins(); refill_favorite_plugins();
XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
set_state (*node); set_state (*node, 0);
update_title (); update_title ();
@ -1022,13 +1008,38 @@ Mixer_UI::stop_updating ()
void void
Mixer_UI::fast_update_strips () Mixer_UI::fast_update_strips ()
{ {
if (is_mapped () && _session) { if (_content.is_mapped () && _session) {
for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) { for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
(*i)->fast_update (); (*i)->fast_update ();
} }
} }
} }
void
Mixer_UI::show_window ()
{
Tabbable::show_window ();
/* show/hide group tabs as required */
parameter_changed ("show-group-tabs");
/* now reset each strips width so the right widgets are shown */
MixerStrip* ms;
TreeModel::Children rows = track_model->children();
TreeModel::Children::iterator ri;
for (ri = rows.begin(); ri != rows.end(); ++ri) {
ms = (*ri)[track_columns.strip];
ms->set_width_enum (ms->get_width_enum (), ms->width_owner());
/* Fix visibility of mixer strip stuff */
ms->parameter_changed (X_("mixer-element-visibility"));
}
/* force focus into main area */
scroller_base.grab_focus ();
}
void void
Mixer_UI::set_all_strips_visibility (bool yn) Mixer_UI::set_all_strips_visibility (bool yn)
{ {
@ -1699,23 +1710,6 @@ Mixer_UI::set_strip_width (Width w, bool save)
} }
} }
void
Mixer_UI::set_window_pos_and_size ()
{
if (_parent_window) {
_parent_window->resize (m_width, m_height);
_parent_window->move (m_root_x, m_root_y);
}
}
void
Mixer_UI::get_window_pos_and_size ()
{
if (_parent_window) {
_parent_window->get_position(m_root_x, m_root_y);
_parent_window->get_size(m_width, m_height);
}
}
struct PluginStateSorter { struct PluginStateSorter {
public: public:
@ -1740,7 +1734,7 @@ private:
}; };
int int
Mixer_UI::set_state (const XMLNode& node) Mixer_UI::set_state (const XMLNode& node, int version)
{ {
const XMLProperty* prop; const XMLProperty* prop;
XMLNode* geometry; XMLNode* geometry;
@ -1792,8 +1786,6 @@ Mixer_UI::set_state (const XMLNode& node)
} }
} }
set_window_pos_and_size ();
if ((prop = node.property ("narrow-strips"))) { if ((prop = node.property ("narrow-strips"))) {
if (string_is_affirmative (prop->value())) { if (string_is_affirmative (prop->value())) {
set_strip_width (Narrow); set_strip_width (Narrow);
@ -1854,7 +1846,7 @@ Mixer_UI::set_state (const XMLNode& node)
} }
XMLNode& XMLNode&
Mixer_UI::get_state (void) Mixer_UI::get_state ()
{ {
XMLNode* node = new XMLNode ("Mixer"); XMLNode* node = new XMLNode ("Mixer");
@ -1891,11 +1883,8 @@ Mixer_UI::get_state (void)
} }
node->add_property ("narrow-strips", _strip_width == Narrow ? "yes" : "no"); node->add_property ("narrow-strips", _strip_width == Narrow ? "yes" : "no");
node->add_property ("show-mixer", _visible ? "yes" : "no"); node->add_property ("show-mixer", _visible ? "yes" : "no");
node->add_property ("show-mixer-list", _show_mixer_list ? "yes" : "no"); node->add_property ("show-mixer-list", _show_mixer_list ? "yes" : "no");
node->add_property ("maximised", _maximised ? "yes" : "no"); node->add_property ("maximised", _maximised ? "yes" : "no");
store_current_favorite_order (); store_current_favorite_order ();
@ -2171,6 +2160,10 @@ Mixer_UI::new_track_or_bus ()
void void
Mixer_UI::update_title () Mixer_UI::update_title ()
{ {
if (!own_window()) {
return;
}
if (_session) { if (_session) {
string n; string n;
@ -2207,7 +2200,7 @@ Mixer_UI::strip_by_x (int x)
for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) { for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) {
int x1, x2, y; int x1, x2, y;
(*i)->translate_coordinates (*this, 0, 0, x1, y); (*i)->translate_coordinates (_content, 0, 0, x1, y);
x2 = x1 + (*i)->get_width(); x2 = x1 + (*i)->get_width();
if (x >= x1 && x <= x2) { if (x >= x1 && x <= x2) {
@ -2267,7 +2260,7 @@ Mixer_UI::toggle_midi_input_active (bool flip_others)
void void
Mixer_UI::maximise_mixer_space () Mixer_UI::maximise_mixer_space ()
{ {
if (_maximised) { if (!own_window()) {
return; return;
} }
@ -2277,12 +2270,15 @@ Mixer_UI::maximise_mixer_space ()
win->fullscreen (); win->fullscreen ();
_maximised = true; _maximised = true;
} }
_window->fullscreen ();
_maximised = true;
} }
void void
Mixer_UI::restore_mixer_space () Mixer_UI::restore_mixer_space ()
{ {
if (!_maximised) { if (!own_window()) {
return; return;
} }
@ -2292,6 +2288,9 @@ Mixer_UI::restore_mixer_space ()
win->unfullscreen(); win->unfullscreen();
_maximised = false; _maximised = false;
} }
own_window()->unfullscreen();
_maximised = false;
} }
void void

View file

@ -42,13 +42,13 @@
#include "ardour/plugin.h" #include "ardour/plugin.h"
#include "ardour/plugin_manager.h" #include "ardour/plugin_manager.h"
<<<<<<< HEAD
#include "gtkmm2ext/visibility_tracker.h" #include "gtkmm2ext/visibility_tracker.h"
#include "gtkmm2ext/dndtreeview.h" #include "gtkmm2ext/dndtreeview.h"
#include "gtkmm2ext/treeutils.h" #include "gtkmm2ext/treeutils.h"
======= #include "gtkmm2ext/tabbable.h"
>>>>>>> the basics of tabbed
#include "enums.h" #include "enums.h"
#include "mixer_actor.h" #include "mixer_actor.h"
@ -62,7 +62,6 @@ class PluginSelector;
class MixerGroupTabs; class MixerGroupTabs;
class MonitorSection; class MonitorSection;
<<<<<<< HEAD
class PluginTreeStore : public Gtk::TreeStore class PluginTreeStore : public Gtk::TreeStore
{ {
public: public:
@ -76,20 +75,15 @@ protected:
virtual bool row_drop_possible_vfunc (const Gtk::TreeModel::Path&, const Gtk::SelectionData&) const; virtual bool row_drop_possible_vfunc (const Gtk::TreeModel::Path&, const Gtk::SelectionData&) const;
}; };
class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor, public Gtkmm2ext::VisibilityTracker class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor, public Gtkmm2ext::VisibilityTracker
=======
class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor
>>>>>>> the basics of tabbed
{ {
public: public:
static Mixer_UI* instance(); static Mixer_UI* instance();
~Mixer_UI(); ~Mixer_UI();
Gtk::Window* own_window() const { return _parent_window; } Gtk::Window* use_own_window ();
Gtk::Notebook* use_own_window(); void show_window ();
bool visible() const { return _visible; }
void set_session (ARDOUR::Session *); void set_session (ARDOUR::Session *);
void track_editor_selection (); void track_editor_selection ();
@ -101,22 +95,18 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO
void unselect_strip_in_display (MixerStrip*); void unselect_strip_in_display (MixerStrip*);
void select_strip_in_display (MixerStrip*); void select_strip_in_display (MixerStrip*);
XMLNode& get_state (void); XMLNode& get_state ();
int set_state (const XMLNode& ); int set_state (const XMLNode&, int /* version */);
void show_mixer_list (bool yn); void show_mixer_list (bool yn);
void show_monitor_section (bool); void show_monitor_section (bool);
void show_window ();
bool hide_window (GdkEventAny *ev);
void show_strip (MixerStrip *); void show_strip (MixerStrip *);
void hide_strip (MixerStrip *); void hide_strip (MixerStrip *);
void maximise_mixer_space(); void maximise_mixer_space();
void restore_mixer_space(); void restore_mixer_space();
void ensure_float (Gtk::Window&);
MonitorSection* monitor_section() const { return _monitor_section; } MonitorSection* monitor_section() const { return _monitor_section; }
void deselect_all_strip_processors(); void deselect_all_strip_processors();
@ -124,23 +114,22 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO
void select_none (); void select_none ();
bool window_not_visible () const;
protected: protected:
void set_route_targets_for_operation (); void set_route_targets_for_operation ();
private: private:
Mixer_UI (); Mixer_UI ();
static Mixer_UI* _instance; static Mixer_UI* _instance;
Gtk::VBox _content;
Gtk::Window* _parent_window; Gtk::HBox global_hpacker;
bool _visible; Gtk::VBox global_vpacker;
Gtk::ScrolledWindow scroller;
Gtk::HBox global_hpacker; Gtk::EventBox scroller_base;
Gtk::VBox global_vpacker; Gtk::HBox scroller_hpacker;
Gtk::ScrolledWindow scroller; Gtk::VBox mixer_scroller_vpacker;
Gtk::EventBox scroller_base; Gtk::VBox list_vpacker;
Gtk::HBox scroller_hpacker;
Gtk::VBox mixer_scroller_vpacker;
Gtk::VBox list_vpacker;
Gtk::Label group_display_button_label; Gtk::Label group_display_button_label;
Gtk::Button group_display_button; Gtk::Button group_display_button;
Gtk::ScrolledWindow track_display_scroller; Gtk::ScrolledWindow track_display_scroller;
@ -373,7 +362,7 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO
======= =======
void create_own_window (); void create_own_window ();
>>>>>>> the basics of tabbed >>>>>>> the basics of tabbed
/// true if we are in fullscreen mode /// true if we are in fullscreen mode
bool _maximised; bool _maximised;
@ -383,5 +372,3 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO
}; };
#endif /* __ardour_mixer_ui_h__ */ #endif /* __ardour_mixer_ui_h__ */

View file

@ -466,7 +466,7 @@ MonitorSection::MonitorSection (Session* s)
_tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL); _tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
} }
_tearoff->tearoff_window().set_title (X_("Monitor")); _tearoff->tearoff_window().set_title (X_("Monitor"));
_tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false); _tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), (Gtk::Window*) 0), false);
update_output_display (); update_output_display ();
update_processor_box (); update_processor_box ();

View file

@ -1013,7 +1013,7 @@ Panner2dWindow::set_width ()
bool bool
Panner2dWindow::on_key_press_event (GdkEventKey* event) Panner2dWindow::on_key_press_event (GdkEventKey* event)
{ {
return relay_key_press (event, &PublicEditor::instance()); return relay_key_press (event, 0);
} }
bool bool

View file

@ -374,7 +374,7 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event)
no widgets in this window that we want to have no widgets in this window that we want to have
key focus. key focus.
*/ */
return relay_key_press (event, &PublicEditor::instance()); return relay_key_press (event, 0);
} else { } else {
return relay_key_press (event, this); return relay_key_press (event, this);
} }

View file

@ -2002,7 +2002,7 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
const XMLNode* ui_xml = _session->extra_xml (X_("UI")); const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
if (ui_xml) { if (ui_xml) {
wp->set_state (*ui_xml); wp->set_state (*ui_xml, 0);
} }
void* existing_ui = p->get_ui (); void* existing_ui = p->get_ui ();
@ -3305,7 +3305,7 @@ ProcessorWindowProxy::session_handle()
} }
XMLNode& XMLNode&
ProcessorWindowProxy::get_state () const ProcessorWindowProxy::get_state ()
{ {
XMLNode *node; XMLNode *node;
node = &ProxyBase::get_state(); node = &ProxyBase::get_state();
@ -3313,8 +3313,8 @@ ProcessorWindowProxy::get_state () const
return *node; return *node;
} }
void int
ProcessorWindowProxy::set_state (const XMLNode& node) ProcessorWindowProxy::set_state (const XMLNode& node, int /*version*/)
{ {
XMLNodeList children = node.children (); XMLNodeList children = node.children ();
XMLNodeList::const_iterator i = children.begin (); XMLNodeList::const_iterator i = children.begin ();
@ -3333,7 +3333,7 @@ ProcessorWindowProxy::set_state (const XMLNode& node)
} }
} }
ProxyBase::set_state(node); return ProxyBase::set_state (node, 0);
} }
Gtk::Window* Gtk::Window*

View file

@ -78,31 +78,31 @@ class ProcessorBox;
class ProcessorWindowProxy : public WM::ProxyBase class ProcessorWindowProxy : public WM::ProxyBase
{ {
public: public:
ProcessorWindowProxy (std::string const &, ProcessorBox *, boost::weak_ptr<ARDOUR::Processor>); ProcessorWindowProxy (std::string const &, ProcessorBox *, boost::weak_ptr<ARDOUR::Processor>);
~ProcessorWindowProxy(); ~ProcessorWindowProxy();
Gtk::Window* get (bool create = false); Gtk::Window* get (bool create = false);
boost::weak_ptr<ARDOUR::Processor> processor () const { boost::weak_ptr<ARDOUR::Processor> processor () const {
return _processor; return _processor;
} }
ARDOUR::SessionHandlePtr* session_handle(); ARDOUR::SessionHandlePtr* session_handle();
void toggle(); void toggle();
void set_custom_ui_mode(bool use_custom) { want_custom = use_custom; } void set_custom_ui_mode(bool use_custom) { want_custom = use_custom; }
void set_state (const XMLNode&); int set_state (const XMLNode&, int);
XMLNode& get_state () const; XMLNode& get_state ();
private: private:
ProcessorBox* _processor_box; ProcessorBox* _processor_box;
boost::weak_ptr<ARDOUR::Processor> _processor; boost::weak_ptr<ARDOUR::Processor> _processor;
bool is_custom; bool is_custom;
bool want_custom; bool want_custom;
bool _valid; bool _valid;
void processor_going_away (); void processor_going_away ();
PBD::ScopedConnection going_away_connection; PBD::ScopedConnection going_away_connection;
}; };
class ProcessorEntry : public Gtkmm2ext::DnDVBoxChild, public sigc::trackable class ProcessorEntry : public Gtkmm2ext::DnDVBoxChild, public sigc::trackable

View file

@ -19,6 +19,8 @@
#include "public_editor.h" #include "public_editor.h"
#include "i18n.h"
PublicEditor* PublicEditor::_instance = 0; PublicEditor* PublicEditor::_instance = 0;
const int PublicEditor::window_border_width = 12; const int PublicEditor::window_border_width = 12;
@ -28,9 +30,8 @@ const int PublicEditor::horizontal_spacing = 6;
sigc::signal<void> PublicEditor::DropDownKeys; sigc::signal<void> PublicEditor::DropDownKeys;
PublicEditor::PublicEditor () PublicEditor::PublicEditor (Gtk::Widget& content)
: Window (Gtk::WINDOW_TOPLEVEL) : Tabbable (content, _("Editor"))
, VisibilityTracker (*((Gtk::Window*)this))
, _suspend_route_redisplay_counter (0) , _suspend_route_redisplay_counter (0)
{ {
} }

View file

@ -43,6 +43,7 @@
#include "canvas/fwd.h" #include "canvas/fwd.h"
#include "gtkmm2ext/actions.h" #include "gtkmm2ext/actions.h"
#include "gtkmm2ext/tabbable.h"
#include "gtkmm2ext/visibility_tracker.h" #include "gtkmm2ext/visibility_tracker.h"
#include "editing.h" #include "editing.h"
@ -105,9 +106,9 @@ using ARDOUR::framecnt_t;
* of PublicEditor need not be recompiled if private methods or member variables * of PublicEditor need not be recompiled if private methods or member variables
* change. * change.
*/ */
class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, public Gtkmm2ext::VisibilityTracker { class PublicEditor : public Gtkmm2ext::Tabbable {
public: public:
PublicEditor (); PublicEditor (Gtk::Widget& content);
virtual ~PublicEditor (); virtual ~PublicEditor ();
/** @return Singleton PublicEditor instance */ /** @return Singleton PublicEditor instance */
@ -232,8 +233,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void export_range () = 0; virtual void export_range () = 0;
virtual void register_actions () = 0; virtual void register_actions () = 0;
virtual void add_transport_frame (Gtk::Container&) = 0;
virtual void add_toplevel_menu (Gtk::Container&) = 0;
virtual void set_zoom_focus (Editing::ZoomFocus) = 0; virtual void set_zoom_focus (Editing::ZoomFocus) = 0;
virtual Editing::ZoomFocus get_zoom_focus () const = 0; virtual Editing::ZoomFocus get_zoom_focus () const = 0;
virtual framecnt_t get_current_zoom () const = 0; virtual framecnt_t get_current_zoom () const = 0;
@ -267,8 +266,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
/** @return true if the playhead is currently being dragged, otherwise false */ /** @return true if the playhead is currently being dragged, otherwise false */
virtual bool dragging_playhead () const = 0; virtual bool dragging_playhead () const = 0;
virtual void ensure_float (Gtk::Window&) = 0;
virtual void show_window () = 0;
virtual framepos_t leftmost_sample() const = 0; virtual framepos_t leftmost_sample() const = 0;
virtual framecnt_t current_page_samples() const = 0; virtual framecnt_t current_page_samples() const = 0;
virtual double visible_canvas_height () const = 0; virtual double visible_canvas_height () const = 0;
@ -442,11 +439,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
PBD::Signal0<void> SnapChanged; PBD::Signal0<void> SnapChanged;
PBD::Signal0<void> MouseModeChanged; PBD::Signal0<void> MouseModeChanged;
Gtk::Notebook& tabs() { return _tabs; }
protected: protected:
Gtk::Notebook _tabs;
friend class DisplaySuspender; friend class DisplaySuspender;
virtual void suspend_route_redisplay () = 0; virtual void suspend_route_redisplay () = 0;
virtual void resume_route_redisplay () = 0; virtual void resume_route_redisplay () = 0;

View file

@ -1720,6 +1720,7 @@ private:
RCOptionEditor::RCOptionEditor () RCOptionEditor::RCOptionEditor ()
: OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME)) : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
, Tabbable (*this, _("Preferences"))
, _rc_config (Config) , _rc_config (Config)
, _mixer_strip_visibility ("mixer-element-visibility") , _mixer_strip_visibility ("mixer-element-visibility")
{ {
@ -1831,6 +1832,7 @@ RCOptionEditor::RCOptionEditor ()
/* TRANSPORT */ /* TRANSPORT */
add_option (_("Transport"), new OptionEditorHeading (S_("Playhead Behaviour")));
add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options"))); add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options")));
BoolOption* tsf; BoolOption* tsf;

View file

@ -20,6 +20,8 @@
#ifndef __gtk_ardour_rc_option_editor_h__ #ifndef __gtk_ardour_rc_option_editor_h__
#define __gtk_ardour_rc_option_editor_h__ #define __gtk_ardour_rc_option_editor_h__
#include "gtkmm2ext/tabbable.h"
#include "option_editor.h" #include "option_editor.h"
#include "visibility_group.h" #include "visibility_group.h"
@ -32,7 +34,7 @@
*/ */
/** Editor for options which are obtained from and written back to one of the .rc files. */ /** Editor for options which are obtained from and written back to one of the .rc files. */
class RCOptionEditor : public OptionEditor class RCOptionEditor : public OptionEditor, public Gtkmm2ext::Tabbable
{ {
public: public:
RCOptionEditor (); RCOptionEditor ();

View file

@ -222,7 +222,7 @@ RegionLayeringOrderEditor::on_key_press_event (GdkEventKey* ev)
} }
if (!handled) { if (!handled) {
handled = key_press_focus_accelerator_handler (editor, ev); handled = relay_key_press (ev, 0);
} }
if (!handled) { if (!handled) {

View file

@ -504,7 +504,7 @@ StepEntry::on_key_press_event (GdkEventKey* ev)
} }
} }
return forward_key_press (ev); return relay_key_press (ev);
} }
bool bool

View file

@ -297,39 +297,28 @@ ARDOUR_UI_UTILS::gdk_color_to_rgba (Gdk::Color const& c)
bool bool
ARDOUR_UI_UTILS::relay_key_press (GdkEventKey* ev, Gtk::Window* win) ARDOUR_UI_UTILS::relay_key_press (GdkEventKey* ev, Gtk::Window* win)
{ {
switch (ev->type) {
if (!key_press_focus_accelerator_handler (*win, ev)) { case GDK_KEY_PRESS:
if (!PublicEditor::_instance) { return ARDOUR_UI::instance()->key_press_handler (ev, win);
/* early key press in pre-main-window-dialogs, no editor yet */ default:
return false; return ARDOUR_UI::instance()->key_release_handler (ev, win);
}
PublicEditor& ed (PublicEditor::instance());
return ed.on_key_press_event(ev);
} else {
return true;
} }
} }
bool bool
ARDOUR_UI_UTILS::forward_key_press (GdkEventKey* ev) ARDOUR_UI_UTILS::emulate_key_event (unsigned int keyval)
{ {
return PublicEditor::instance().on_key_press_event(ev); GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET(ARDOUR_UI::instance()->main_window().gobj()));
}
bool
ARDOUR_UI_UTILS::emulate_key_event (Gtk::Widget* w, unsigned int keyval)
{
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET(w->gobj()));
GdkKeymap *keymap = gdk_keymap_get_for_display (display); GdkKeymap *keymap = gdk_keymap_get_for_display (display);
GdkKeymapKey *keymapkey = NULL; GdkKeymapKey *keymapkey = NULL;
gint n_keys; gint n_keys;
if (!gdk_keymap_get_entries_for_keyval(keymap, keyval, &keymapkey, &n_keys)) return false; if (!gdk_keymap_get_entries_for_keyval(keymap, keyval, &keymapkey, &n_keys)) return false;
if (n_keys !=1) { g_free(keymapkey); return false;} if (n_keys !=1) { g_free(keymapkey); return false;}
GdkEventKey ev; GdkEventKey ev;
ev.type = GDK_KEY_PRESS; ev.type = GDK_KEY_PRESS;
ev.window = gtk_widget_get_window(GTK_WIDGET(w->gobj())); ev.window = ARDOUR_UI::instance()->main_window().get_window()->gobj();
ev.send_event = FALSE; ev.send_event = FALSE;
ev.time = 0; ev.time = 0;
ev.state = 0; ev.state = 0;
@ -340,9 +329,9 @@ ARDOUR_UI_UTILS::emulate_key_event (Gtk::Widget* w, unsigned int keyval)
ev.group = keymapkey[0].group; ev.group = keymapkey[0].group;
g_free(keymapkey); g_free(keymapkey);
forward_key_press(&ev); relay_key_press(&ev);
ev.type = GDK_KEY_RELEASE; ev.type = GDK_KEY_RELEASE;
return forward_key_press(&ev); return relay_key_press(&ev);
} }
static string static string

View file

@ -67,10 +67,9 @@ void set_color_from_rgba (Gdk::Color&, uint32_t);
uint32_t gdk_color_to_rgba (Gdk::Color const&); uint32_t gdk_color_to_rgba (Gdk::Color const&);
uint32_t contrasting_text_color (uint32_t c); uint32_t contrasting_text_color (uint32_t c);
bool relay_key_press (GdkEventKey* ev, Gtk::Window* win); bool relay_key_press (GdkEventKey* ev, Gtk::Window* win = 0);
bool forward_key_press (GdkEventKey* ev);
bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev); bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev);
bool emulate_key_event (Gtk::Widget*, unsigned int); bool emulate_key_event (unsigned int);
Glib::RefPtr<Gdk::Pixbuf> get_xpm (std::string); Glib::RefPtr<Gdk::Pixbuf> get_xpm (std::string);
std::vector<std::string> get_icon_sets (); std::vector<std::string> get_icon_sets ();

View file

@ -255,9 +255,7 @@ VideoMonitor::is_started ()
void void
VideoMonitor::forward_keyevent (unsigned int keyval) VideoMonitor::forward_keyevent (unsigned int keyval)
{ {
Editor* ed = dynamic_cast<Editor*>(&PublicEditor::instance()); emulate_key_event (keyval);
if (!ed) return;
emulate_key_event(ed, keyval);
} }
void void

View file

@ -170,269 +170,23 @@ Manager::set_transient_for (Gtk::Window* parent)
/*-------------------------*/ /*-------------------------*/
ProxyBase::ProxyBase (const string& name, const std::string& menu_name) ProxyBase::ProxyBase (const std::string& name, const std::string& menu_name)
: _name (name) : WindowProxy (name, menu_name)
, _menu_name (menu_name)
, _window (0)
, _visible (false)
, _x_off (-1)
, _y_off (-1)
, _width (-1)
, _height (-1)
, vistracker (0)
{ {
} }
ProxyBase::ProxyBase (const string& name, const std::string& menu_name, const XMLNode& node) ProxyBase::ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode& node)
: _name (name) : WindowProxy (name, menu_name, node)
, _menu_name (menu_name)
, _window (0)
, _visible (false)
, _x_off (-1)
, _y_off (-1)
, _width (-1)
, _height (-1)
, vistracker (0)
{ {
set_state (node);
}
ProxyBase::~ProxyBase ()
{
delete vistracker;
delete _window;
}
void
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());
}
if ((prop = (*i)->property (X_("y-off"))) != 0) {
_y_off = atoi (prop->value());
}
if ((prop = (*i)->property (X_("x-size"))) != 0) {
_width = atoi (prop->value());
}
if ((prop = (*i)->property (X_("y-size"))) != 0) {
_height = atoi (prop->value());
}
}
/* if we have a window already, reset its properties */
if (_window) {
setup ();
}
}
void
ProxyBase::set_action (Glib::RefPtr<Gtk::Action> act)
{
_action = act;
}
std::string
ProxyBase::action_name() const
{
return string_compose (X_("toggle-%1"), _name);
}
void
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 ();
if (_width != -1 && _height != -1) {
_window->set_default_size (_width, _height);
}
if (_x_off != -1 && _y_off != -1) {
_window->move (_x_off, _y_off);
}
} else {
if (_window->is_mapped()) {
save_pos_and_size();
}
vistracker->cycle_visibility ();
if (_window->is_mapped()) {
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&
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 ();
if (_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
ProxyBase::drop_window ()
{
if (_window) {
_window->hide ();
delete _window;
_window = 0;
delete vistracker;
vistracker = 0;
}
}
void
ProxyBase::use_window (Gtk::Window& win)
{
drop_window ();
_window = &win;
setup ();
} }
void void
ProxyBase::setup () ProxyBase::setup ()
{ {
assert (_window); WindowProxy::setup ();
vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
_window->signal_delete_event().connect (sigc::mem_fun (*this, &ProxyBase::delete_event_handler));
if (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1) {
/* cancel any mouse-based positioning */
_window->set_position (Gtk::WIN_POS_NONE);
}
if (_width != -1 && _height != -1) {
_window->set_default_size (_width, _height);
}
if (_x_off != -1 && _y_off != -1) {
_window->move (_x_off, _y_off);
}
set_session(_session); set_session(_session);
} }
void
ProxyBase::show ()
{
get (true);
assert (_window);
_window->show ();
}
void
ProxyBase::maybe_show ()
{
if (_visible) {
show ();
}
}
void
ProxyBase::show_all ()
{
get (true);
assert (_window);
_window->show_all ();
}
void
ProxyBase::present ()
{
get (true);
assert (_window);
_window->show_all ();
_window->present ();
/* turn off any mouse-based positioning */
_window->set_position (Gtk::WIN_POS_NONE);
}
void
ProxyBase::hide ()
{
if (_window) {
save_pos_and_size();
_window->hide ();
}
}
bool
ProxyBase::delete_event_handler (GdkEventAny* /*ev*/)
{
hide();
return true;
}
void
ProxyBase::save_pos_and_size ()
{
if (_window) {
_window->get_position (_x_off, _y_off);
_window->get_size (_width, _height);
}
}
/*-----------------------*/ /*-----------------------*/
ProxyTemporary::ProxyTemporary (const string& name, Gtk::Window* win) ProxyTemporary::ProxyTemporary (const string& name, Gtk::Window* win)

View file

@ -1,19 +1,19 @@
/* /*
Copyright (C) 2013 Paul Davis Copyright (C) 2013 Paul Davis
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
@ -27,20 +27,22 @@
#include <glibmm/refptr.h> #include <glibmm/refptr.h>
#include <sigc++/trackable.h> #include <sigc++/trackable.h>
#include "gtkmm2ext/window_proxy.h"
class XMLNode; class XMLNode;
namespace Gtk { namespace Gtk {
class Window; class Window;
class Action; class Action;
} }
namespace Gtkmm2ext { namespace Gtkmm2ext {
class VisibilityTracker; class VisibilityTracker;
} }
namespace ARDOUR { namespace ARDOUR {
class Session; class Session;
class SessionHandlePtr; class SessionHandlePtr;
} }
namespace WM { namespace WM {
@ -50,192 +52,156 @@ class ProxyBase;
class Manager : public ARDOUR::SessionHandlePtr class Manager : public ARDOUR::SessionHandlePtr
{ {
public: public:
static Manager& instance(); static Manager& instance();
void register_window (ProxyBase*); void register_window (ProxyBase*);
void remove (const ProxyBase*); void remove (const ProxyBase*);
void toggle_window (ProxyBase*); void toggle_window (ProxyBase*);
void show_visible () const; void show_visible () const;
void set_session (ARDOUR::Session*); void set_session (ARDOUR::Session*);
void add_state (XMLNode&) const; void add_state (XMLNode&) const;
/* HACK HACK HACK */ /* HACK HACK HACK */
void set_transient_for (Gtk::Window*); void set_transient_for (Gtk::Window*);
Gtk::Window* transient_parent() const { return current_transient_parent; } Gtk::Window* transient_parent() const { return current_transient_parent; }
private: private:
typedef std::list<ProxyBase*> Windows; typedef std::list<ProxyBase*> Windows;
Windows _windows; Windows _windows;
Glib::RefPtr<Gtk::ActionGroup> window_actions; Glib::RefPtr<Gtk::ActionGroup> window_actions;
Gtk::Window* current_transient_parent; Gtk::Window* current_transient_parent;
Manager(); Manager();
~Manager(); ~Manager();
static Manager* _instance; static Manager* _instance;
}; };
class ProxyBase : public ARDOUR::SessionHandlePtr, public sigc::trackable { class ProxyBase : public ARDOUR::SessionHandlePtr, public Gtkmm2ext::WindowProxy
{
public: public:
ProxyBase (const std::string& name, const std::string& menu_name); ProxyBase (const std::string& name, const std::string& menu_name);
ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode&); ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode&);
virtual ~ProxyBase();
virtual ARDOUR::SessionHandlePtr* session_handle () = 0;
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: protected:
std::string _name; void setup ();
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 save_pos_and_size ();
bool delete_event_handler (GdkEventAny *ev);
void setup ();
}; };
class ProxyTemporary: public ProxyBase { class ProxyTemporary: public ProxyBase
{
public: public:
ProxyTemporary (const std::string& name, Gtk::Window* win); ProxyTemporary (const std::string& name, Gtk::Window* win);
~ProxyTemporary(); ~ProxyTemporary();
Gtk::Window* get (bool create = false) {
(void) create;
return _window;
}
Gtk::Window* operator->() {
return _window;
}
Gtk::Window* get (bool create = false) { ARDOUR::SessionHandlePtr* session_handle ();
(void) create;
return _window;
}
Gtk::Window* operator->() {
return _window;
}
ARDOUR::SessionHandlePtr* session_handle ();
}; };
template<typename T> template<typename T>
class ProxyWithConstructor: public ProxyBase { class ProxyWithConstructor: public ProxyBase
{
public: public:
ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c) ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c)
: ProxyBase (name, menu_name) , creator (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) 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) {} : ProxyBase (name, menu_name, *node) , creator (c) {}
Gtk::Window* get (bool create = false) { Gtk::Window* get (bool create = false) {
if (!_window) { if (!_window) {
if (!create) { if (!create) {
return 0; return 0;
} }
_window = dynamic_cast<Gtk::Window*> (creator ()); _window = dynamic_cast<Gtk::Window*> (creator ());
if (_window) { if (_window) {
setup (); setup ();
} }
} }
return _window; return _window;
} }
T* operator->() { T* operator->() {
return dynamic_cast<T*> (get (true)); return dynamic_cast<T*> (get (true));
} }
ARDOUR::SessionHandlePtr* session_handle () { ARDOUR::SessionHandlePtr* session_handle () {
/* may return null */ /* may return null */
return dynamic_cast<T*> (_window); return dynamic_cast<T*> (_window);
} }
void set_session(ARDOUR::Session *s) { void set_session(ARDOUR::Session *s) {
SessionHandlePtr::set_session (s); SessionHandlePtr::set_session (s);
ARDOUR::SessionHandlePtr* sp = session_handle (); ARDOUR::SessionHandlePtr* sp = session_handle ();
if (sp) { if (sp) {
sp->set_session (s); sp->set_session (s);
dynamic_cast<T*>(_window)->set_session(s); dynamic_cast<T*>(_window)->set_session(s);
} }
} }
private: private:
boost::function<T*()> creator; boost::function<T*()> creator;
>>>>>>> first compilable version of tabbable design.
}; };
template<typename T> template<typename T>
class Proxy : public ProxyBase { class Proxy : public ProxyBase
{
public: public:
Proxy (const std::string& name, const std::string& menu_name) Proxy (const std::string& name, const std::string& menu_name)
: ProxyBase (name, menu_name) {} : ProxyBase (name, menu_name) {}
Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node) Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node)
: ProxyBase (name, menu_name, *node) {} : ProxyBase (name, menu_name, *node) {}
Gtk::Window* get (bool create = false) {
if (!_window) {
if (!create) {
return 0;
}
Gtk::Window* get (bool create = false) { _window = new T ();
if (!_window) {
if (!create) {
return 0;
}
_window = new T (); if (_window) {
setup ();
}
}
if (_window) { return _window;
setup (); }
}
}
return _window; T* operator->() {
} return dynamic_cast<T*> (get(true));
}
T* operator->() {
return dynamic_cast<T*> (get(true));
}
ARDOUR::SessionHandlePtr* session_handle () {
/* may return null */
return dynamic_cast<T*> (_window);
}
void set_session(ARDOUR::Session *s) {
SessionHandlePtr::set_session (s);
ARDOUR::SessionHandlePtr* sp = session_handle ();
if (sp) {
sp->set_session (s);
dynamic_cast<T*>(_window)->set_session(s);
}
}
ARDOUR::SessionHandlePtr* session_handle () {
/* may return null */
return dynamic_cast<T*> (_window);
}
void set_session(ARDOUR::Session *s) {
SessionHandlePtr::set_session (s);
ARDOUR::SessionHandlePtr* sp = session_handle ();
if (sp) {
sp->set_session (s);
dynamic_cast<T*>(_window)->set_session(s);
}
}
private: private:
boost::function<T*()> creator; boost::function<T*()> creator;
}; };
} /* namespace */ } /* namespace */

View file

@ -36,11 +36,14 @@ class VisibilityTracker;
class LIBGTKMM2EXT_API Tabbable : public WindowProxy { class LIBGTKMM2EXT_API Tabbable : public WindowProxy {
public: public:
Tabbable (Gtk::Widget&); Tabbable (Gtk::Widget&, const std::string&);
~Tabbable (); ~Tabbable ();
void add_to_notebook (Gtk::Notebook& notebook, const std::string& tab_title, int position); void add_to_notebook (Gtk::Notebook& notebook, const std::string& tab_title, int position);
void show_tab ();
Gtk::Widget& contents() const { return _contents; }
Gtk::Window* get (bool create = false); Gtk::Window* get (bool create = false);
Gtk::Window* own_window () { return get (false); } Gtk::Window* own_window () { return get (false); }
Gtk::Notebook* tabbed_parent (); Gtk::Notebook* tabbed_parent ();
@ -52,12 +55,17 @@ class LIBGTKMM2EXT_API Tabbable : public WindowProxy {
virtual void show_window (); virtual void show_window ();
bool window_visible (); bool window_visible ();
Gtk::Window* current_toplevel () const;
Gtk::Notebook* tab_root_drop ();
protected: protected:
bool delete_event_handler (GdkEventAny *ev); bool delete_event_handler (GdkEventAny *ev);
private: private:
Gtk::Widget& _contents; Gtk::Widget& _contents;
Gtk::Notebook _own_notebook;
Gtk::Notebook* _parent_notebook; Gtk::Notebook* _parent_notebook;
std::string _tab_title; std::string _tab_title;
int _notebook_position; int _notebook_position;

View file

@ -25,7 +25,7 @@
#include <glibmm/refptr.h> #include <glibmm/refptr.h>
#include <sigc++/trackable.h> #include <sigc++/trackable.h>
class XMLNode; #include "pbd/statefuldestructible.h"
#include "gtkmm2ext/visibility.h" #include "gtkmm2ext/visibility.h"
@ -38,10 +38,10 @@ namespace Gtkmm2ext {
class VisibilityTracker; class VisibilityTracker;
class LIBGTKMM2EXT_API WindowProxy : public virtual sigc::trackable class LIBGTKMM2EXT_API WindowProxy : public PBD::StatefulDestructible, public virtual sigc::trackable
{ {
public: public:
WindowProxy (); WindowProxy (const std::string& name);
WindowProxy (const std::string& name, const std::string& menu_name); WindowProxy (const std::string& name, const std::string& menu_name);
WindowProxy (const std::string& name, const std::string& menu_name, const XMLNode&); WindowProxy (const std::string& name, const std::string& menu_name, const XMLNode&);
virtual ~WindowProxy(); virtual ~WindowProxy();
@ -68,8 +68,8 @@ class LIBGTKMM2EXT_API WindowProxy : public virtual sigc::trackable
virtual void toggle (); virtual void toggle ();
virtual int set_state (const XMLNode&); virtual int set_state (const XMLNode&, int version);
virtual XMLNode& get_state () const; virtual XMLNode& get_state ();
operator bool() const { return _window != 0; } operator bool() const { return _window != 0; }

View file

@ -28,8 +28,9 @@ using namespace Gtkmm2ext;
using namespace Gtk; using namespace Gtk;
using std::string; using std::string;
Tabbable::Tabbable (Widget& w) Tabbable::Tabbable (Widget& w, const string& name)
: _contents (w) : WindowProxy (name)
, _contents (w)
{ {
} }
@ -78,17 +79,45 @@ Tabbable::get (bool create)
if (!create) { if (!create) {
return 0; return 0;
} }
/* From here on, we're creating the window
*/
if ((_window = new Window (WINDOW_TOPLEVEL)) == 0) { if ((_window = new Window (WINDOW_TOPLEVEL)) == 0) {
return 0; return 0;
} }
/* allow parent window to become the key focus window */ _window->add (_own_notebook);
_window->set_flags (CAN_FOCUS); _own_notebook.show ();
_own_notebook.set_show_tabs (false);
/* do other window-related setup */
setup ();
/* window should be ready for derived classes to do something with it */
return _window; return _window;
} }
Gtk::Notebook*
Tabbable::tab_root_drop ()
{
(void) use_own_window ();
/* This is called after a drop of a tab onto the root window. Its
* responsibility is to return the notebook that this Tabbable's
* contents should be packed into before the drop handling is
* completed. It is not responsible for actually taking care of this
* packing.
*/
_window->show_all ();
_window->present ();
return &_own_notebook;
}
void void
Tabbable::show_window () Tabbable::show_window ()
{ {
@ -119,6 +148,8 @@ Tabbable::delete_event_handler (GdkEventAny *ev)
if (_window == toplevel) { if (_window == toplevel) {
std::cerr << " delete event for own window\n";
/* unpack Tabbable from parent, put it back in the main tabbed /* unpack Tabbable from parent, put it back in the main tabbed
* notebook * notebook
*/ */
@ -132,13 +163,13 @@ Tabbable::delete_event_handler (GdkEventAny *ev)
_window->hide (); _window->hide ();
if (_parent_notebook) { if (_parent_notebook) {
std::cerr << "repack into parent notebook\n";
_parent_notebook->insert_page (_contents, _tab_title, _notebook_position); _parent_notebook->insert_page (_contents, _tab_title, _notebook_position);
_parent_notebook->set_tab_detachable (_contents); _parent_notebook->set_tab_detachable (_contents);
} }
show_all ();
/* don't let anything else handle this */ /* don't let anything else handle this */
return true; return true;
@ -163,3 +194,17 @@ Tabbable::is_tabbed () const
return false; return false;
} }
void
Tabbable::show_tab ()
{
if (!window_visible() && _parent_notebook) {
_parent_notebook->set_current_page (_parent_notebook->page_num (_contents));
}
}
Gtk::Window*
Tabbable::current_toplevel () const
{
return dynamic_cast<Gtk::Window*> (contents().get_toplevel());
}

View file

@ -32,8 +32,9 @@ using namespace Gtk;
using namespace Gtkmm2ext; using namespace Gtkmm2ext;
using namespace PBD; using namespace PBD;
WindowProxy::WindowProxy () WindowProxy::WindowProxy (const std::string& name)
: _window (0) : _name (name)
, _window (0)
, _visible (false) , _visible (false)
, _x_off (-1) , _x_off (-1)
, _y_off (-1) , _y_off (-1)
@ -67,7 +68,7 @@ WindowProxy::WindowProxy (const std::string& name, const std::string& menu_name,
, _height (-1) , _height (-1)
, vistracker (0) , vistracker (0)
{ {
set_state (node); set_state (node, 0);
} }
WindowProxy::~WindowProxy () WindowProxy::~WindowProxy ()
@ -77,7 +78,7 @@ WindowProxy::~WindowProxy ()
} }
int int
WindowProxy::set_state (const XMLNode& node) WindowProxy::set_state (const XMLNode& node, int /* version */)
{ {
XMLNodeList children = node.children (); XMLNodeList children = node.children ();
@ -171,7 +172,7 @@ WindowProxy::toggle()
} }
XMLNode& XMLNode&
WindowProxy::get_state () const WindowProxy::get_state ()
{ {
XMLNode* node = new XMLNode (X_("Window")); XMLNode* node = new XMLNode (X_("Window"));
char buf[32]; char buf[32];

View file

@ -57,11 +57,13 @@ gtkmm2ext_sources = [
'selector.cc', 'selector.cc',
'slider_controller.cc', 'slider_controller.cc',
'stateful_button.cc', 'stateful_button.cc',
'tabbable.cc',
'tearoff.cc', 'tearoff.cc',
'textviewer.cc', 'textviewer.cc',
'treeutils.cc', 'treeutils.cc',
'utils.cc', 'utils.cc',
'visibility_tracker.cc', 'visibility_tracker.cc',
'window_proxy.cc'
'window_title.cc' 'window_title.cc'
] ]