From 3be16e8afbd891c0bfe7227158384ed0d127597f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 8 Dec 2008 16:07:28 +0000 Subject: [PATCH] partial patch/partial by-hand merge of 2.X commits 3169&3170 to 3.X codebase git-svn-id: svn://localhost/ardour2/branches/3.0@4300 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/SConscript | 1 + gtk2_ardour/ardour_ui.cc | 4 +- gtk2_ardour/audio_region_view.cc | 10 +- gtk2_ardour/editor.h | 1 + gtk2_ardour/editor_mixer.cc | 175 +++++--- gtk2_ardour/gain_meter.cc | 120 ++--- gtk2_ardour/gain_meter.h | 9 +- gtk2_ardour/level_meter.cc | 15 +- gtk2_ardour/level_meter.h | 4 +- gtk2_ardour/main.cc | 21 +- gtk2_ardour/matrix.cc | 427 ++++++++++++++++++ gtk2_ardour/matrix.h | 106 +++++ gtk2_ardour/mixer_strip.cc | 339 +++++++++------ gtk2_ardour/mixer_strip.h | 4 + gtk2_ardour/option_editor.cc | 6 +- gtk2_ardour/panner_ui.cc | 115 +++-- gtk2_ardour/panner_ui.h | 11 +- gtk2_ardour/port_group.h | 90 ++++ gtk2_ardour/port_matrix.cc | 433 +------------------ gtk2_ardour/port_matrix.h | 116 +---- gtk2_ardour/processor_box.cc | 31 +- gtk2_ardour/processor_box.h | 8 +- gtk2_ardour/route_params_ui.cc | 7 +- gtk2_ardour/route_time_axis.cc | 4 +- gtk2_ardour/route_ui.cc | 146 +++++-- gtk2_ardour/route_ui.h | 14 + gtk2_ardour/send_ui.cc | 11 +- gtk2_ardour/sfdb_ui.cc | 3 +- libs/ardour/plugin_manager.cc | 45 +- libs/gtkmm2ext/binding_proxy.cc | 21 +- libs/gtkmm2ext/gtkmm2ext/barcontroller.h | 2 + libs/gtkmm2ext/gtkmm2ext/bindable_button.h | 14 +- libs/gtkmm2ext/gtkmm2ext/binding_proxy.h | 2 + libs/gtkmm2ext/gtkmm2ext/slider_controller.h | 7 +- libs/gtkmm2ext/slider_controller.cc | 9 +- 35 files changed, 1399 insertions(+), 932 deletions(-) create mode 100644 gtk2_ardour/matrix.cc create mode 100644 gtk2_ardour/matrix.h create mode 100644 gtk2_ardour/port_group.h diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index fef196e5ba..8bfccae2b4 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -194,6 +194,7 @@ lineset.cc location_ui.cc main.cc marker.cc +matrix.cc midi_channel_selector.cc midi_port_dialog.cc midi_region_view.cc diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index b3ac2e3db8..44280a3109 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -1736,8 +1736,8 @@ ARDOUR_UI::engine_halted () _("\ JACK has either been shutdown or it\n\ disconnected Ardour because Ardour\n\ -was not fast enough. You can save the\n\ -session and/or try to reconnect to JACK .")); +was not fast enough. Try to restart\n\ +JACK, reconnect and save the session.")); pop_back_splash (); msg.run (); } diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 40046cd9a1..e3dd980eee 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -196,6 +196,10 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd) setup_fade_handle_positions (); + if (!Config->get_show_region_fades()) { + set_fade_visibility (false); + } + string line_name = _region->name(); line_name += ':'; line_name += "gain"; @@ -410,8 +414,10 @@ AudioRegionView::reset_width_dependent_items (double pixel_width) fade_in_handle->hide(); fade_out_handle->hide(); } else { - fade_in_handle->show(); - fade_out_handle->show(); + if (Config->get_show_region_fades()) { + fade_in_handle->show(); + fade_out_handle->show(); + } } } } diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 279de99298..394c1ad121 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -294,6 +294,7 @@ class Editor : public PublicEditor Width editor_mixer_strip_width; void maybe_add_mixer_strip_width (XMLNode&); void show_editor_mixer (bool yn); + void create_editor_mixer (); void show_editor_list (bool yn); void set_selected_mixer_strip (TimeAxisView&); void hide_track_in_display (TimeAxisView& tv, bool temporary = false); diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index 6bfc325f6d..cb10b2f551 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -57,13 +57,6 @@ Editor::editor_list_button_toggled () } } -void -Editor::cms_new (boost::shared_ptr r) -{ - current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(), *session, r); - current_mixer_strip->GoingAway.connect (mem_fun (*this, &Editor::cms_deleted)); -} - void Editor::cms_deleted () { @@ -73,77 +66,109 @@ Editor::cms_deleted () void Editor::show_editor_mixer (bool yn) { + boost::shared_ptr r; + show_editor_mixer_when_tracks_arrive = false; + if (!session) { + show_editor_mixer_when_tracks_arrive = yn; + return; + } + if (yn) { - if (current_mixer_strip == 0) { + if (selection->tracks.empty()) { + + if (track_views.empty()) { + show_editor_mixer_when_tracks_arrive = true; + return; + } - if (selection->tracks.empty()) { + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + AudioTimeAxisView* atv; - if (track_views.empty()) { - show_editor_mixer_when_tracks_arrive = true; - return; - } - - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - AudioTimeAxisView* atv; - - if ((atv = dynamic_cast (*i)) != 0) { - cms_new (atv->route ()); - break; - } + if ((atv = dynamic_cast (*i)) != 0) { + r = atv->route(); + break; } - - } else { - - sort_track_selection (); - - for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { - AudioTimeAxisView* atv; - - if ((atv = dynamic_cast (*i)) != 0) { - cms_new (atv->route ()); - break; - } - } - } + } else { + + sort_track_selection (); + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast (*i)) != 0) { + r = atv->route(); + break; + } + } + } + + if (r) { + bool created; + if (current_mixer_strip == 0) { - return; - } + create_editor_mixer (); + created = true; + } else { + created = false; + } + + current_mixer_strip->set_route (r); + + if (created) { + current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this); + } } if (current_mixer_strip->get_parent() == 0) { - current_mixer_strip->set_embedded (true); - current_mixer_strip->Hiding.connect (mem_fun(*this, &Editor::current_mixer_strip_hidden)); - current_mixer_strip->GoingAway.connect (mem_fun(*this, &Editor::current_mixer_strip_removed)); - current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this); - global_hpacker.pack_start (*current_mixer_strip, Gtk::PACK_SHRINK ); global_hpacker.reorder_child (*current_mixer_strip, 0); - current_mixer_strip->show_all (); } } else { if (current_mixer_strip) { - editor_mixer_strip_width = current_mixer_strip->get_width (); if (current_mixer_strip->get_parent() != 0) { global_hpacker.remove (*current_mixer_strip); } } } + #ifdef GTKOSX /* XXX gtk problem here */ - ruler_label_event_box.queue_draw (); - time_button_event_box.queue_draw (); - controls_layout.queue_draw (); + ensure_all_elements_drawn(); #endif } +#ifdef GTKOSX +void +Editor::ensure_all_elements_drawn () +{ + controls_layout.queue_draw (); + ruler_label_event_box.queue_draw (); + time_button_event_box.queue_draw (); +} +#endif + +void +Editor::create_editor_mixer () +{ + current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(), + *session, + false); + current_mixer_strip->Hiding.connect (mem_fun(*this, &Editor::current_mixer_strip_hidden)); + current_mixer_strip->GoingAway.connect (mem_fun(*this, &Editor::current_mixer_strip_removed)); +#ifdef GTKOSX + current_mixer_strip->WidthChanged.connect (mem_fun(*this, &Editor::ensure_all_elements_drawn)); +#endif + current_mixer_strip->set_embedded (true); +} + void Editor::show_editor_list (bool yn) { @@ -157,38 +182,52 @@ Editor::show_editor_list (bool yn) void Editor::set_selected_mixer_strip (TimeAxisView& view) { - RouteTimeAxisView* rt; + AudioTimeAxisView* at; bool show = false; + bool created; - if (!session || (rt = dynamic_cast(&view)) == 0) { + if (!session || (at = dynamic_cast(&view)) == 0) { + return; + } + + Glib::RefPtr act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer")); + if (act) { + Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); + if (!tact || !tact->get_active()) { + /* not showing mixer strip presently */ + return; + } + } + + if (current_mixer_strip == 0) { + create_editor_mixer (); + created = true; + } else { + created = false; + } + + /* might be nothing to do */ + + if (current_mixer_strip->route() == at->route()) { return; } - if (current_mixer_strip) { - - /* might be nothing to do */ - - if (current_mixer_strip->route() == rt->route()) { - return; - } - - if (current_mixer_strip->get_parent()) { - show = true; - } - delete current_mixer_strip; - current_mixer_strip = 0; + if (current_mixer_strip->get_parent()) { + show = true; + } + + current_mixer_strip->set_route (at->route()); + + if (created) { + current_mixer_strip->set_width (editor_mixer_strip_width, (void*) this); } - current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(), - *session, - rt->route(), false); - current_mixer_strip->GoingAway.connect (mem_fun(*this, &Editor::cms_deleted)); - if (show) { show_editor_mixer (true); } } + double current = 0.0; bool currentInitialized = 0; @@ -276,7 +315,7 @@ void Editor::current_mixer_strip_removed () { if (current_mixer_strip) { - /* it is being deleted */ + /* it is being deleted elsewhere */ current_mixer_strip = 0; } } diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index a580ec6b38..b34c0b8d28 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -72,17 +72,18 @@ GainMeter::setup_slider_pix () } } -GainMeterBase::GainMeterBase (boost::shared_ptr io, Session& s, +GainMeterBase::GainMeterBase (Session& s, const Glib::RefPtr& pix, bool horizontal) - : _io (io), - _session (s), + : _session (s), // 0.781787 is the value needed for gain to be set to 0. gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1), gain_automation_style_button (""), gain_automation_state_button ("") { + using namespace Menu_Helpers; + ignore_toggle = false; meter_menu = 0; next_release_selects = false; @@ -92,16 +93,14 @@ GainMeterBase::GainMeterBase (boost::shared_ptr io, Session& s, if (horizontal) { gain_slider = manage (new HSliderController (pix, &gain_adjustment, - _io->gain_control(), false)); } else { gain_slider = manage (new VSliderController (pix, &gain_adjustment, - _io->gain_control(), false)); } - level_meter = new LevelMeter(_io, _session); + level_meter = new LevelMeter(_session); gain_slider->signal_button_press_event().connect (mem_fun(*this, &GainMeter::start_gain_touch)); gain_slider->signal_button_release_event().connect (mem_fun(*this, &GainMeter::end_gain_touch)); @@ -133,10 +132,40 @@ GainMeterBase::GainMeterBase (boost::shared_ptr io, Session& s, gain_automation_state_button.set_size_request(15, 15); gain_automation_style_button.set_size_request(15, 15); + + gain_astyle_menu.items().push_back (MenuElem (_("Trim"))); + gain_astyle_menu.items().push_back (MenuElem (_("Abs"))); + + gain_astate_menu.set_name ("ArdourContextMenu"); + gain_astyle_menu.set_name ("ArdourContextMenu"); + gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeterBase::gain_adjusted)); + peak_display.signal_button_release_event().connect (mem_fun(*this, &GainMeterBase::peak_button_release), false); + gain_display.signal_key_press_event().connect (mem_fun(*this, &GainMeterBase::gain_key_press), false); + ResetAllPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_peak_display)); + ResetGroupPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_group_peak_display)); + UI::instance()->theme_changed.connect (mem_fun(*this, &GainMeterBase::on_theme_changed)); + ColorsChanged.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), false)); + DPIReset.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), true)); +} +GainMeterBase::~GainMeterBase () +{ + delete meter_menu; + delete level_meter; +} + +void +GainMeterBase::set_io (boost::shared_ptr io) +{ + connections.clear (); + + _io = io; + + level_meter->set_io (_io); + gain_slider->set_controllable (_io->gain_control()); boost::shared_ptr r; @@ -146,6 +175,8 @@ GainMeterBase::GainMeterBase (boost::shared_ptr io, Session& s, using namespace Menu_Helpers; + gain_astate_menu.items().clear (); + gain_astate_menu.items().push_back (MenuElem (_("Manual"), bind (mem_fun (*_io, &IO::set_parameter_automation_state), Evoral::Parameter(GainAutomation), (AutoState) Off))); @@ -159,50 +190,21 @@ GainMeterBase::GainMeterBase (boost::shared_ptr io, Session& s, bind (mem_fun (*_io, &IO::set_parameter_automation_state), Evoral::Parameter(GainAutomation), (AutoState) Touch))); - gain_astyle_menu.items().push_back (MenuElem (_("Trim"))); - gain_astyle_menu.items().push_back (MenuElem (_("Abs"))); + connections.push_back (gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false)); + connections.push_back (gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false)); - gain_astate_menu.set_name ("ArdourContextMenu"); - gain_astyle_menu.set_name ("ArdourContextMenu"); - - gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false); - gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false); - - r->gain_control()->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)); - r->gain_control()->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)); + connections.push_back (r->gain_control()->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed))); + connections.push_back (r->gain_control()->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed))); gain_automation_state_changed (); } } - _io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed)); - - gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeterBase::gain_adjusted)); - peak_display.signal_button_release_event().connect (mem_fun(*this, &GainMeterBase::peak_button_release), false); - gain_display.signal_key_press_event().connect (mem_fun(*this, &GainMeterBase::gain_key_press), false); + connections.push_back (_io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed))); gain_changed (); show_gain (); - update_gain_sensitive (); - - ResetAllPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_peak_display)); - ResetGroupPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_group_peak_display)); - - UI::instance()->theme_changed.connect (mem_fun(*this, &GainMeterBase::on_theme_changed)); - ColorsChanged.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), false)); - DPIReset.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), true)); -} - -GainMeterBase::~GainMeterBase () -{ - if (meter_menu) { - delete meter_menu; - } - - if (level_meter) { - delete level_meter; - } } void @@ -752,10 +754,9 @@ GainMeterBase::on_theme_changed() style_changed = true; } -GainMeter::GainMeter (boost::shared_ptr io, Session& s) - : GainMeterBase (io, s, slider, false) +GainMeter::GainMeter (Session& s) + : GainMeterBase (s, slider, false) { - gain_display_box.set_homogeneous (true); gain_display_box.set_spacing (2); gain_display_box.pack_start (gain_display, true, true); @@ -785,6 +786,31 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) hbox.set_spacing (2); hbox.pack_start (*fader_vbox, true, true); + set_spacing (2); + + pack_start (gain_display_box, Gtk::PACK_SHRINK); + pack_start (hbox, Gtk::PACK_SHRINK); + + meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose)); +} + +void +GainMeter::set_io (boost::shared_ptr io) +{ + if (level_meter->get_parent()) { + hbox.remove (*level_meter); + } + + if (peak_display.get_parent()) { + gain_display_box.remove (peak_display); + } + + if (gain_automation_state_button.get_parent()) { + fader_vbox->remove (gain_automation_state_button); + } + + GainMeterBase::set_io (io); + boost::shared_ptr r; if ((r = boost::dynamic_pointer_cast (_io)) != 0) { @@ -801,16 +827,8 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) fader_vbox->pack_start (gain_automation_state_button, false, false, 0); } } - - set_spacing (2); - - pack_start (gain_display_box, Gtk::PACK_SHRINK); - pack_start (hbox, Gtk::PACK_SHRINK); - - meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose)); } - int GainMeter::get_gm_width () { diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h index d493edf0fb..820e9ef0e7 100644 --- a/gtk2_ardour/gain_meter.h +++ b/gtk2_ardour/gain_meter.h @@ -58,10 +58,12 @@ namespace Gtk { class GainMeterBase : virtual public sigc::trackable { public: - GainMeterBase (boost::shared_ptr, ARDOUR::Session&, const Glib::RefPtr& pix, + GainMeterBase ( ARDOUR::Session&, const Glib::RefPtr& pix, bool horizontal); virtual ~GainMeterBase (); + virtual void set_io (boost::shared_ptr); + void update_gain_sensitive (); void update_meters (); @@ -82,6 +84,7 @@ class GainMeterBase : virtual public sigc::trackable friend class MixerStrip; boost::shared_ptr _io; ARDOUR::Session& _session; + std::vector connections; bool ignore_toggle; bool next_release_selects; @@ -169,9 +172,11 @@ class GainMeterBase : virtual public sigc::trackable class GainMeter : public GainMeterBase, public Gtk::VBox { public: - GainMeter (boost::shared_ptr, ARDOUR::Session&); + GainMeter (ARDOUR::Session&); ~GainMeter () {} + void set_io (boost::shared_ptr); + int get_gm_width (); void setup_meters (int len=0); diff --git a/gtk2_ardour/level_meter.cc b/gtk2_ardour/level_meter.cc index f6e3731aac..cd7308cfa2 100644 --- a/gtk2_ardour/level_meter.cc +++ b/gtk2_ardour/level_meter.cc @@ -58,9 +58,8 @@ using namespace std; //sigc::signal LevelMeter::ResetGroupPeakDisplays; -LevelMeter::LevelMeter (boost::shared_ptr io, Session& s) - : _io (io), - _session (s) +LevelMeter::LevelMeter (Session& s) + : _session (s) { set_spacing (1); @@ -85,6 +84,12 @@ LevelMeter::~LevelMeter () } } +void +LevelMeter::set_io (boost::shared_ptr io) +{ + _io = io; +} + float LevelMeter::update_meters () { @@ -144,6 +149,10 @@ LevelMeter::hide_all_meters () void LevelMeter::setup_meters (int len, int initial_width) { + if (!_io) { + return; /* do it later */ + } + uint32_t nmeters = _io->n_outputs().n_total(); regular_meter_width = initial_width; diff --git a/gtk2_ardour/level_meter.h b/gtk2_ardour/level_meter.h index ce0aa125cb..521b9d1d8f 100644 --- a/gtk2_ardour/level_meter.h +++ b/gtk2_ardour/level_meter.h @@ -56,9 +56,11 @@ namespace Gtk { class LevelMeter : public Gtk::HBox { public: - LevelMeter (boost::shared_ptr, ARDOUR::Session&); + LevelMeter (ARDOUR::Session&); ~LevelMeter (); + virtual void set_io (boost::shared_ptr io); + void update_gain_sensitive (); float update_meters (); diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index edbdcd58cb..aecbc1f634 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -117,7 +117,10 @@ fixup_bundle_environment () Glib::ustring path; const char *cstr = getenv ("PATH"); - /* ensure that we find any bundled executables (e.g. JACK) */ + /* ensure that we find any bundled executables (e.g. JACK), + and find them before any instances of the same name + elsewhere in PATH + */ path = dir_path; if (cstr) { @@ -152,8 +155,10 @@ fixup_bundle_environment () if (cstr) { path = cstr; path += ':'; + } else { + path = ""; } - path = dir_path; + path += dir_path; path += "/../Plugins"; setenv ("LADSPA_PATH", path.c_str(), 1); @@ -162,8 +167,10 @@ fixup_bundle_environment () if (cstr) { path = cstr; path += ':'; + } else { + path = ""; } - path = dir_path; + path += dir_path; path += "/../Frameworks"; setenv ("VAMP_PATH", path.c_str(), 1); @@ -172,8 +179,10 @@ fixup_bundle_environment () if (cstr) { path = cstr; path += ':'; + } else { + path = ""; } - path = dir_path; + path += dir_path; path += "/../Surfaces"; setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1); @@ -182,8 +191,10 @@ fixup_bundle_environment () if (cstr) { path = cstr; path += ':'; + } else { + path = ""; } - path = dir_path; + path += dir_path; path += "/../Plugins"; setenv ("LV2_PATH", path.c_str(), 1); diff --git a/gtk2_ardour/matrix.cc b/gtk2_ardour/matrix.cc new file mode 100644 index 0000000000..db16362ca0 --- /dev/null +++ b/gtk2_ardour/matrix.cc @@ -0,0 +1,427 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "matrix.h" + +using namespace std; +using namespace Gtk; +using namespace ARDOUR; + +Matrix::Matrix () +{ + alloc_width = 0; + alloc_height = 0; + line_width = 0; + line_height = 0; + labels_y_shift = 0; + labels_x_shift = 0; + arc_radius = 0; + xstep = 0; + ystep = 0; + pixmap = 0; + drawn = false; + angle_radians = M_PI/4.0; + motion_x = -1; + motion_y = -1; + + add_events (Gdk::POINTER_MOTION_MASK|Gdk::LEAVE_NOTIFY_MASK); +} + +void +Matrix::set_ports (const list& ports) +{ + ours = ports; + reset_size (); +} + +void +Matrix::add_group (PortGroup& pg) +{ + for (vector::const_iterator s = pg.ports.begin(); s != pg.ports.end(); ++s) { + others.push_back (OtherPort (*s, pg)); + } + reset_size (); +} + +void +Matrix::remove_group (PortGroup& pg) +{ + for (list::iterator o = others.begin(); o != others.end(); ) { + if (&(*o).group() == &pg) { + o = others.erase (o); + } else { + ++o; + } + } + reset_size (); +} + +void +Matrix::hide_group (PortGroup& pg) +{ + reset_size(); +} + +void +Matrix::show_group (PortGroup& pg) +{ + reset_size (); +} + +void +Matrix::setup_nodes () +{ + int n, x, y; + list::iterator m; + list::iterator s; + + for (vector::iterator p = nodes.begin(); p != nodes.end(); ++p) { + delete *p; + } + nodes.clear (); + + list::size_type visible_others = 0; + + for (list::iterator s = others.begin(); s != others.end(); ++s) { + if ((*s).visible()) { + ++visible_others; + } + } + + nodes.assign (ours.size() * visible_others, 0); + + for (n = 0, y = 0, m = ours.begin(); m != ours.end(); ++m, ++y) { + for (x = 0, s = others.begin(); s != others.end(); ++s) { + if ((*s).visible()) { + nodes[n] = new MatrixNode (*m, *s, x, y); + n++; + x++; + } + } + } +} + +void +Matrix::reset_size () +{ + list::size_type visible_others = 0; + + for (list::iterator s = others.begin(); s != others.end(); ++s) { + if ((*s).visible()) { + ++visible_others; + } + } + + border = 10; + + if (alloc_width > line_width) { + + xstep = (alloc_width - labels_x_shift - (2 * border) - (2 * arc_radius)) / visible_others; + line_width = xstep * (others.size() - 1); + + ystep = (alloc_height - labels_y_shift - (2 * border) - (2 * arc_radius)) / (ours.size() - 1); + line_height = ystep * (ours.size() - 1); + + } else { + + xstep = 20; + ystep = 20; + + line_height = (ours.size() - 1) * ystep; + line_width = visible_others * xstep; + } + + int half_step = min (ystep/2,xstep/2); + if (half_step > 3) { + arc_radius = half_step - 5; + } else { + arc_radius = 3; + } + + arc_radius = min (arc_radius, 10); + + /* scan all the port names that will be rotated, and compute + how much space we need for them + */ + + float w = 0; + float w1; + float h = 0; + cairo_text_extents_t extents; + cairo_t* cr; + GdkPixmap* pm; + + pm = gdk_pixmap_new (NULL, 1, 1, 24); + gdk_drawable_set_colormap (pm, gdk_colormap_get_system()); + + cr = gdk_cairo_create (pm); + + for (list::iterator s = others.begin(); s != others.end(); ++s) { + if ((*s).visible()) { + cairo_text_extents (cr, (*s).name().c_str(), &extents); + w = max ((float) extents.width, w); + h = max ((float) extents.height, h); + } + } + + cairo_destroy (cr); + gdk_pixmap_unref (pm); + + /* transform */ + + w = fabs (w * cos (angle_radians) + h * sin (angle_radians)); + h = fabs (w * sin (angle_radians) + h * cos (angle_radians)); + + labels_y_shift = (int) ceil (h) + 10; + labels_x_shift = (int) ceil (w); + + setup_nodes (); +} + +bool +Matrix::on_motion_notify_event (GdkEventMotion* ev) +{ + motion_x = ev->x; + motion_y = ev->y; + queue_draw (); + return false; +} + +bool +Matrix::on_leave_notify_event (GdkEventCrossing *ev) +{ + motion_x = -1; + motion_y = -1; + queue_draw (); + return false; +} + +void +Matrix::on_size_request (Requisition* req) +{ + req->width = labels_x_shift + line_width + (2*border) + (2*arc_radius); + req->height = labels_y_shift + line_height + (2*border) + (2*arc_radius); +} + +MatrixNode* +Matrix::get_node (int32_t x, int32_t y) +{ + int half_xstep = xstep / 2; + int half_ystep = ystep / 2; + + x -= labels_x_shift - border; + if (x < half_xstep) { + return 0; + } + + y -= labels_y_shift - border; + if (y < half_ystep) { + return 0; + } + + x = (x - half_xstep) / xstep; + y = (y - half_ystep) / ystep; + + x = y*ours.size() + x; + + if (x >= nodes.size()) { + return 0; + } + + return nodes[x]; +} + +bool +Matrix::on_button_press_event (GdkEventButton* ev) +{ + MatrixNode* node; + + if ((node = get_node (ev->x, ev->y)) != 0) { + cerr << "Event in node " << node->our_name() << " x " << node->their_name () << endl; + node->set_connected (!node->connected()); + drawn = false; + queue_draw(); + } +} + +void +Matrix::alloc_pixmap () +{ + if (pixmap) { + gdk_pixmap_unref (pixmap); + } + + pixmap = gdk_pixmap_new (get_window()->gobj(), + alloc_width, + alloc_height, + -1); + + drawn = false; +} + +void +Matrix::on_size_allocate (Allocation& alloc) +{ + EventBox::on_size_allocate (alloc); + + alloc_width = alloc.get_width(); + alloc_height = alloc.get_height(); + + if (is_realized()) { + alloc_pixmap (); + reset_size (); +#ifdef MATRIX_USE_BACKING_PIXMAP + redraw (pixmap, 0, 0, alloc_width, alloc_height); +#endif + } +} + +void +Matrix::on_realize () +{ + EventBox::on_realize (); + alloc_pixmap (); +} + +void +Matrix::redraw (GdkDrawable* drawable, GdkRectangle* rect) +{ + list::iterator o; + list::iterator t; + int x, y; + uint32_t top_shift, bottom_shift, left_shift, right_shift; + cairo_t* cr; + + cr = gdk_cairo_create (drawable); + + cairo_set_source_rgb (cr, 0.83, 0.83, 0.83); + cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height); + cairo_fill (cr); + + cairo_set_line_width (cr, 0.5); + + top_shift = labels_y_shift + border; + left_shift = labels_x_shift + border; + bottom_shift = 0; + right_shift = 0; + + /* horizontal grid lines and side labels */ + + for (y = top_shift, o = ours.begin(); o != ours.end(); ++o, y += ystep) { + + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + cairo_move_to (cr, left_shift, y); + cairo_line_to (cr, left_shift+line_width, y); + cairo_stroke (cr); +#if 0 + + cairo_text_extents_t extents; + cairo_text_extents (cr, (*o).c_str(),&extents); + cairo_move_to (cr, border, y+extents.height/2); + cairo_show_text (cr, (*o).c_str()); +#endif + + } + + /* vertical grid lines and rotated labels*/ + + for (x = left_shift, t = others.begin(); t != others.end(); ++t, x += xstep) { + + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + cairo_move_to (cr, x, top_shift); + cairo_line_to (cr, x, top_shift+line_height); + cairo_stroke (cr); + + cairo_move_to (cr, x-left_shift+12, border); + cairo_set_source_rgb (cr, 0, 0, 1.0); + + cairo_save (cr); + cairo_rotate (cr, angle_radians); + cairo_show_text (cr, (*t).name().c_str()); + cairo_restore (cr); + + } + + /* nodes */ + + for (vector::iterator n = nodes.begin(); n != nodes.end(); ++n) { + + x = (*n)->x() * xstep; + y = (*n)->y() * ystep; + + cairo_new_path (cr); + + if (arc_radius) { + cairo_arc (cr, left_shift+x, top_shift+y, arc_radius, 0, 2.0 * M_PI); + if ((*n)->connected()) { + cairo_set_source_rgba (cr, 1.0, 0, 0, 1.0); + cairo_stroke (cr); + } else { + cairo_set_source_rgba (cr, 1.0, 0, 0, 0.7); + cairo_fill (cr); + } + } + } + + /* motion indicators */ + + if (motion_x >= left_shift && motion_y >= top_shift) { + + int col_left = left_shift + ((motion_x - left_shift) / xstep) * xstep; + int row_top = top_shift + ((motion_y - top_shift) / ystep) * ystep; + + cairo_set_line_width (cr, 5); + cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.3); + + /* horizontal (row) */ + + cairo_line_to (cr, left_shift, row_top); + cairo_line_to (cr, left_shift + line_width, row_top); + cairo_stroke (cr); + + /* vertical (col) */ + + cairo_move_to (cr, col_left, top_shift); + cairo_line_to (cr, col_left, top_shift + line_height); + cairo_stroke (cr); + } + + cairo_destroy (cr); + +#ifdef MATRIX_USE_BACKING_PIXMAP + drawn = true; +#endif +} + +bool +Matrix::on_expose_event (GdkEventExpose* event) +{ +#ifdef MATRIX_USE_BACKING_PIXMAP + if (!drawn) { + redraw (pixmap, 0, 0, alloc_width, alloc_height); + } + + gdk_draw_drawable (get_window()->gobj(), + get_style()->get_fg_gc (STATE_NORMAL)->gobj(), + pixmap, + event->area.x, + event->area.y, + event->area.x, + event->area.y, + event->area.width, + event->area.height); +#else + redraw (get_window()->gobj(), &event->area); +#endif + + + + return true; +} diff --git a/gtk2_ardour/matrix.h b/gtk2_ardour/matrix.h new file mode 100644 index 0000000000..f859a881c7 --- /dev/null +++ b/gtk2_ardour/matrix.h @@ -0,0 +1,106 @@ +#ifndef __gtk_ardour_matrix_h__ +#define __gtk_ardour_matrix_h__ + +#include +#include +#include +#include + +#include +#include + +#include "port_group.h" + +class OtherPort { +public: + OtherPort (const std::string& n, PortGroup& g) + : _name (n), _group (g) {} + + std::string name() const { return _name; } + PortGroup& group() const { return _group; } + bool visible() const { return _group.visible; } + +public: + std::string _name; + PortGroup& _group; +}; + +class MatrixNode { + public: + MatrixNode (std::string a, OtherPort o, int32_t x, int32_t y) + : _name (a), them (o), _connected (random()%3), _x(x), _y(y) {} + ~MatrixNode() {} + + PortGroup& get_group() const { return them.group(); } + + std::string our_name() const { return _name; } + std::string their_name() const { return them.name(); } + + bool connected() const { return _connected; } + void set_connected (bool yn) { _connected = yn; } + int32_t x() const { return _x; } + int32_t y() const { return _y; } + + private: + std::string _name; + OtherPort them; + bool _connected; + int32_t _x; + int32_t _y; +}; + +class Matrix : public Gtk::EventBox +{ + public: + Matrix(); + + void set_ports (const std::list&); + void add_group (PortGroup&); + void remove_group (PortGroup&); + void hide_group (PortGroup&); + void show_group (PortGroup&); + + int row_spacing () const { return xstep; } + + protected: + bool on_button_press_event (GdkEventButton* ev); + bool on_expose_event (GdkEventExpose* ev); + void on_size_allocate (Gtk::Allocation&); + void on_size_request (Gtk::Requisition*); + void on_realize (); + bool on_motion_notify_event (GdkEventMotion*); + bool on_leave_notify_event (GdkEventCrossing*); + + MatrixNode* get_node (int32_t x, int32_t y); + +private: + int height; + int width; + int alloc_width; + int alloc_height; + bool drawn; + int labels_y_shift; + int labels_x_shift; + float angle_radians; + int border; + int ystep; + int xstep; + uint32_t line_height; + uint32_t line_width; + int arc_radius; + int32_t motion_x; + int32_t motion_y; + + std::list ours; + std::list others; + std::vector nodes; + + void reset_size (); + void redraw (GdkDrawable*, GdkRectangle*); + void alloc_pixmap (); + void setup_nodes (); + + GdkPixmap* pixmap; +}; + +#endif /* __gtk_ardour_matrix_h__ */ diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 373babf417..1a357dc002 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -82,34 +82,56 @@ speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg) } #endif -MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt, bool in_mixer) - : AxisView(sess), - RouteUI (rt, sess, _("Mute"), _("Solo"), _("Record")), - _mixer(mx), - _mixer_owned (in_mixer), - pre_processor_box (PreFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer), - post_processor_box (PostFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer), - gpm (_route, sess), - panners (_route, sess), - button_table (3, 2), - middle_button_table (1, 2), - bottom_button_table (1, 2), - meter_point_label (_("pre")), - comment_button (_("Comments")), - speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1), - speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true) - +MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer) + : AxisView(sess) + , RouteUI (sess, _("Mute"), _("Solo"), _("Record")) + ,_mixer(mx) + , _mixer_owned (in_mixer) + , pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer) + , post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer) + , gpm (sess) + , panners (sess) + , button_table (3, 2) + , middle_button_table (1, 2) + , bottom_button_table (1, 2) + , meter_point_label (_("pre")) + , comment_button (_("Comments")) + , speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1) + , speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true) + { - if (set_color_from_route()) { - set_color (unique_random_color()); - } + init (); +} +MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt, bool in_mixer) + : AxisView(sess) + , RouteUI (sess, _("Mute"), _("Solo"), _("Record")) + ,_mixer(mx) + , _mixer_owned (in_mixer) + , pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer) + , post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer) + , gpm (sess) + , panners (sess) + , button_table (3, 2) + , middle_button_table (1, 2) + , bottom_button_table (1, 2) + , meter_point_label (_("pre")) + , comment_button (_("Comments")) + , speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1) + , speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true) + +{ + init (); + set_route (rt); +} + +void +MixerStrip::init () +{ input_selector = 0; output_selector = 0; group_menu = 0; - if (!_route->is_hidden()) { - _marked_for_display = true; - } + _marked_for_display = false; route_ops_menu = 0; ignore_comment_edit = false; ignore_toggle = false; @@ -118,40 +140,26 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt comment_area = 0; _width_owner = 0; - Gtk::Image *width_icon = manage (new Gtk::Image (::get_icon("strip_width"))); - Gtk::Image *hide_icon = manage (new Gtk::Image (::get_icon("hide"))); - width_button.add (*width_icon); - hide_button.add (*hide_icon); + width_button.add (*(manage (new Gtk::Image (::get_icon("strip_width"))))); + hide_button.add (*(manage (new Gtk::Image (::get_icon("hide"))))); input_label.set_text (_("Input")); + ARDOUR_UI::instance()->set_tip (&input_button, _("Click to choose inputs"), ""); input_button.add (input_label); input_button.set_name ("MixerIOButton"); input_label.set_name ("MixerIOButtonLabel"); output_label.set_text (_("Output")); + ARDOUR_UI::instance()->set_tip (&output_button, _("Click to choose outputs"), ""); output_button.add (output_label); output_button.set_name ("MixerIOButton"); output_label.set_name ("MixerIOButtonLabel"); - _route->meter_change.connect (mem_fun(*this, &MixerStrip::meter_changed)); + ARDOUR_UI::instance()->set_tip (&meter_point_button, _("Select metering point"), ""); meter_point_button.add (meter_point_label); meter_point_button.set_name ("MixerStripMeterPreButton"); meter_point_label.set_name ("MixerStripMeterPreButton"); - switch (_route->meter_point()) { - case MeterInput: - meter_point_label.set_text (_("input")); - break; - - case MeterPreFader: - meter_point_label.set_text (_("pre")); - break; - - case MeterPostFader: - meter_point_label.set_text (_("post")); - break; - } - /* TRANSLATORS: this string should be longest of the strings used to describe meter points. In english, it's "input". */ @@ -183,56 +191,18 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt bottom_button_table.set_homogeneous (true); bottom_button_table.attach (group_button, 0, 1, 0, 1); - if (is_audio_track()) { - boost::shared_ptr at = audio_track(); - - at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen)); - -#ifdef VARISPEED_IN_MIXER_STRIP - speed_adjustment.signal_value_changed().connect (mem_fun(*this, &MixerStrip::speed_adjustment_changed)); - - speed_frame.set_name ("BaseFrame"); - speed_frame.set_shadow_type (Gtk::SHADOW_IN); - speed_frame.add (speed_spinner); - - speed_spinner.set_print_func (speed_printer, 0); - - ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("Varispeed")); - - button_table.attach (speed_frame, 0, 2, 5, 6); -#endif /* VARISPEED_IN_MIXER_STRIP */ - - } - - if(rec_enable_button) { - rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false); - rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release)); - - rec_enable_button->set_name ("MixerRecordEnableButton"); - button_table.attach (*rec_enable_button, 0, 2, 2, 3); - } - name_button.add (name_label); name_button.set_name ("MixerNameButton"); Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2); name_label.set_name ("MixerNameButtonLabel"); - if (_route->phase_invert()) { - name_label.set_text (X_("Ø ") + name_label.get_text()); - } else { - name_label.set_text (_route->name()); - } - + ARDOUR_UI::instance()->set_tip (&group_button, _("Mix group"), ""); group_button.add (group_label); group_button.set_name ("MixerGroupButton"); group_label.set_name ("MixerGroupButtonLabel"); comment_button.set_name ("MixerCommentButton"); - ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route->comment()=="" ? - _("Click to Add/Edit Comments"): - _route->comment()); - comment_button.signal_clicked().connect (mem_fun(*this, &MixerStrip::comment_button_clicked)); global_vpacker.set_border_width (0); @@ -269,19 +239,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK); global_vpacker.pack_start (comment_button, Gtk::PACK_SHRINK); - if (route()->is_master() || route()->is_control()) { - - if (scrollbar_height == 0) { - HScrollbar scrollbar; - Gtk::Requisition requisition(scrollbar.size_request ()); - scrollbar_height = requisition.height; - } - - EventBox* spacer = manage (new EventBox); - spacer->set_size_request (-1, scrollbar_height); - global_vpacker.pack_start (*spacer, false, false); - } - global_frame.add (global_vpacker); global_frame.set_shadow_type (Gtk::SHADOW_IN); global_frame.set_name ("BaseFrame"); @@ -298,22 +255,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt _session.engine().Stopped.connect (mem_fun(*this, &MixerStrip::engine_stopped)); _session.engine().Running.connect (mem_fun(*this, &MixerStrip::engine_running)); - _route->input_changed.connect (mem_fun(*this, &MixerStrip::input_changed)); - _route->output_changed.connect (mem_fun(*this, &MixerStrip::output_changed)); - _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)); - _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)); - _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)); - _route->mix_group_changed.connect (mem_fun(*this, &MixerStrip::mix_group_changed)); - _route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan)); - - if (is_audio_track()) { - audio_track()->DiskstreamChanged.connect (mem_fun(*this, &MixerStrip::diskstream_changed)); - get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed)); - } - - _route->NameChanged.connect (mem_fun(*this, &RouteUI::name_changed)); - _route->comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed)); - _route->gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed)); input_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::input_press), false); output_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::output_press), false); @@ -323,11 +264,22 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false); mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false); + /* we don't need this if its not an audio track, but we don't know that yet and it doesn't + hurt (much). + */ + + rec_enable_button->set_name ("MixerRecordEnableButton"); + rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false); + rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release)); + name_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::name_button_button_press), false); group_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::select_mix_group), false); _width = (Width) -1; - set_stuff_from_route (); + + /* start off as a passthru strip. we'll correct this, if necessary, + in update_diskstream_display(). + */ /* start off as a passthru strip. we'll correct this, if necessary, in update_diskstream_display(). @@ -338,6 +290,126 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt else set_name ("AudioTrackStripBase"); + add_events (Gdk::BUTTON_RELEASE_MASK); +} + +MixerStrip::~MixerStrip () +{ + GoingAway(); /* EMIT_SIGNAL */ + + if (input_selector) { + delete input_selector; + } + + if (output_selector) { + delete output_selector; + } +} + +void +MixerStrip::set_route (boost::shared_ptr rt) +{ + if (rec_enable_button->get_parent()) { + button_table.remove (*rec_enable_button); + } + +#ifdef VARISPEED_IN_MIXER_STRIP + if (speed_frame->get_parent()) { + button_table.remove (*speed_frame); + } +#endif + + RouteUI::set_route (rt); + + panners.set_io (rt); + gpm.set_io (rt); + pre_processor_box.set_route (rt); + post_processor_box.set_route (rt); + + if (set_color_from_route()) { + set_color (unique_random_color()); + } + + if (_mixer_owned && (route()->is_master() || route()->is_control())) { + + if (scrollbar_height == 0) { + HScrollbar scrollbar; + Gtk::Requisition requisition(scrollbar.size_request ()); + scrollbar_height = requisition.height; + } + + EventBox* spacer = manage (new EventBox); + spacer->set_size_request (-1, scrollbar_height); + global_vpacker.pack_start (*spacer, false, false); + } + + if (is_audio_track()) { + + boost::shared_ptr at = audio_track(); + + connections.push_back (at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen))); + +#ifdef VARISPEED_IN_MIXER_STRIP + speed_adjustment.signal_value_changed().connect (mem_fun(*this, &MixerStrip::speed_adjustment_changed)); + + speed_frame.set_name ("BaseFrame"); + speed_frame.set_shadow_type (Gtk::SHADOW_IN); + speed_frame.add (speed_spinner); + + speed_spinner.set_print_func (speed_printer, 0); + + ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("Varispeed")); + + button_table.attach (speed_frame, 0, 2, 5, 6); +#endif /* VARISPEED_IN_MIXER_STRIP */ + + button_table.attach (*rec_enable_button, 0, 2, 2, 3); + } + + if (_route->phase_invert()) { + name_label.set_text (X_("Ø ") + name_label.get_text()); + } else { + name_label.set_text (_route->name()); + } + + switch (_route->meter_point()) { + case MeterInput: + meter_point_label.set_text (_("input")); + break; + + case MeterPreFader: + meter_point_label.set_text (_("pre")); + break; + + case MeterPostFader: + meter_point_label.set_text (_("post")); + break; + } + + ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route->comment().empty() ? + _("Click to Add/Edit Comments"): + _route->comment()); + + connections.push_back (_route->meter_change.connect (mem_fun(*this, &MixerStrip::meter_changed))); + connections.push_back (_route->input_changed.connect (mem_fun(*this, &MixerStrip::input_changed))); + connections.push_back (_route->output_changed.connect (mem_fun(*this, &MixerStrip::output_changed))); + connections.push_back (_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed))); + connections.push_back (_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed))); + connections.push_back (_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed))); + connections.push_back (_route->mix_group_changed.connect (mem_fun(*this, &MixerStrip::mix_group_changed))); + connections.push_back (_route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan))); + + if (is_audio_track()) { + connections.push_back (audio_track()->DiskstreamChanged.connect (mem_fun(*this, &MixerStrip::diskstream_changed))); + connections.push_back (get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed))); + } + + connections.push_back (_route->NameChanged.connect (mem_fun(*this, &RouteUI::name_changed))); + connections.push_back (_route->comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed))); + connections.push_back (_route->gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed))); + + set_stuff_from_route (); + /* now force an update of all the various elements */ pre_processor_box.update(); @@ -362,11 +434,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt add_events (Gdk::BUTTON_RELEASE_MASK); - whvbox->show(); - hide_icon->show(); - width_icon->show(); - gain_meter_alignment->show_all(); - pre_processor_box.show(); if (!route()->is_master() && !route()->is_control()) { @@ -402,19 +469,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt show(); } -MixerStrip::~MixerStrip () -{ - GoingAway(); /* EMIT_SIGNAL */ - - if (input_selector) { - delete input_selector; - } - - if (output_selector) { - delete output_selector; - } -} - void MixerStrip::set_stuff_from_route () { @@ -796,6 +850,7 @@ MixerStrip::update_output_display () break; } } + gpm.setup_meters (); panners.setup_pan (); } @@ -1292,22 +1347,22 @@ MixerStrip::meter_changed (void *src) ENSURE_GUI_THREAD (bind (mem_fun(*this, &MixerStrip::meter_changed), src)); switch (_route->meter_point()) { - case MeterInput: - meter_point_label.set_text (_("input")); - break; + case MeterInput: + meter_point_label.set_text (_("input")); + break; - case MeterPreFader: - meter_point_label.set_text (_("pre")); - break; - - case MeterPostFader: - meter_point_label.set_text (_("post")); - break; + case MeterPreFader: + meter_point_label.set_text (_("pre")); + break; + + case MeterPostFader: + meter_point_label.set_text (_("post")); + break; } gpm.setup_meters (); - // reset peak when meter point changes - gpm.reset_peak_display(); - set_width(_width, this); + // reset peak when meter point changes + gpm.reset_peak_display(); + set_width(_width, this); } diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h index 63a47974cc..c4c28a06e9 100644 --- a/gtk2_ardour/mixer_strip.h +++ b/gtk2_ardour/mixer_strip.h @@ -83,6 +83,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox { public: MixerStrip (Mixer_UI&, ARDOUR::Session&, boost::shared_ptr, bool in_mixer = true); + MixerStrip (Mixer_UI&, ARDOUR::Session&, bool in_mixer = true); ~MixerStrip (); void set_width (Width, void* owner); @@ -93,6 +94,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox void set_embedded (bool); ARDOUR::RouteGroup* mix_group() const; + void set_route (boost::shared_ptr); protected: friend class Mixer_UI; @@ -105,6 +107,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox private: Mixer_UI& _mixer; + void init (); + bool _embedded; bool _packed; bool _mixer_owned; diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc index ca598a363f..c261aba649 100644 --- a/gtk2_ardour/option_editor.cc +++ b/gtk2_ardour/option_editor.cc @@ -1117,7 +1117,8 @@ OptionEditor::setup_click_editor () click_emphasis_path_entry.set_sensitive (true); click_io_selector = new IOSelector (*session, session->click_io(), false); - click_gpm = new GainMeter (session->click_io(), *session); + click_gpm = new GainMeter (*session); + click_gpm->set_io (session->click_io()); click_hpacker.pack_start (*click_io_selector, false, false); click_hpacker.pack_start (*click_gpm, false, false); @@ -1173,7 +1174,8 @@ void OptionEditor::connect_audition_editor () { auditioner_io_selector = new IOSelector (*session, session->the_auditioner(), false); - auditioner_gpm = new GainMeter (session->the_auditioner(), *session); + auditioner_gpm = new GainMeter (*session); + auditioner_gpm->set_io (session->the_auditioner()); audition_hpacker.pack_start (*auditioner_io_selector, false, false); audition_hpacker.pack_start (*auditioner_gpm, false, false); diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index 2be7be73ed..b1273aa460 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -47,9 +47,8 @@ using namespace sigc; const int PannerUI::pan_bar_height = 30; -PannerUI::PannerUI (boost::shared_ptr io, Session& s) - : _io (io), - _session (s), +PannerUI::PannerUI (Session& s) + : _session (s), hAdjustment(0.0, 0.0, 0.0), vAdjustment(0.0, 0.0, 0.0), panning_viewport(hAdjustment, vAdjustment), @@ -61,6 +60,8 @@ PannerUI::PannerUI (boost::shared_ptr io, Session& s) { ignore_toggle = false; pan_menu = 0; + pan_astate_menu = 0; + pan_astyle_menu = 0; in_pan_update = false; pan_automation_style_button.set_name ("MixerAutomationModeButton"); @@ -84,22 +85,6 @@ PannerUI::PannerUI (boost::shared_ptr io, Session& s) pan_automation_style_button.unset_flags (Gtk::CAN_FOCUS); pan_automation_state_button.unset_flags (Gtk::CAN_FOCUS); - using namespace Menu_Helpers; - pan_astate_menu.items().push_back (MenuElem (_("Manual"), - bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off))); - pan_astate_menu.items().push_back (MenuElem (_("Play"), - bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play))); - pan_astate_menu.items().push_back (MenuElem (_("Write"), - bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Write))); - pan_astate_menu.items().push_back (MenuElem (_("Touch"), - bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Touch))); - - pan_astyle_menu.items().push_back (MenuElem (_("Trim"))); - pan_astyle_menu.items().push_back (MenuElem (_("Abs"))); - - pan_astate_menu.set_name ("ArdourContextMenu"); - pan_astyle_menu.set_name ("ArdourContextMenu"); - pan_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_style_button_event), false); pan_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &PannerUI::pan_automation_state_button_event), false); @@ -141,16 +126,41 @@ PannerUI::PannerUI (boost::shared_ptr io, Session& s) panner = 0; set_width(Narrow); - - _io->panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed)); - _io->panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)); - _io->panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)); +} + +void +PannerUI::set_io (boost::shared_ptr io) +{ + connections.clear (); + + if (pan_astyle_menu) { + delete pan_astyle_menu; + pan_astyle_menu = 0; + } + + if (pan_astate_menu) { + delete pan_astate_menu; + pan_astate_menu = 0; + } + + _io = io; + + connections.push_back (_io->panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed))); + connections.push_back (_io->panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage))); + connections.push_back (_io->panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state))); + + if (panner) { + delete panner; + panner = 0; + } + pan_changed (0); update_pan_sensitive (); update_pan_linkage (); pan_automation_state_changed (); +#if WHERE_DOES_THIS_LIVE pan_bar_packer.show(); panning_viewport.show(); panning_up.show(); @@ -164,6 +174,46 @@ PannerUI::PannerUI (boost::shared_ptr io, Session& s) pan_automation_style_button.show(); pan_automation_state_button.show(); show(); +#endif +} + +void +PannerUI::build_astate_menu () +{ + using namespace Menu_Helpers; + + if (pan_astate_menu == 0) { + pan_astate_menu = new Menu; + pan_astate_menu->set_name ("ArdourContextMenu"); + } else { + pan_astate_menu->items().clear (); + } + + pan_astate_menu->items().push_back (MenuElem (_("Manual"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off))); + pan_astate_menu->items().push_back (MenuElem (_("Play"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play))); + pan_astate_menu->items().push_back (MenuElem (_("Write"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Write))); + pan_astate_menu->items().push_back (MenuElem (_("Touch"), + bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Touch))); + +} + +void +PannerUI::build_astyle_menu () +{ + using namespace Menu_Helpers; + + if (pan_astyle_menu == 0) { + pan_astyle_menu = new Menu; + pan_astyle_menu->set_name ("ArdourContextMenu"); + } else { + pan_astyle_menu->items().clear(); + } + + pan_astyle_menu->items().push_back (MenuElem (_("Trim"))); + pan_astyle_menu->items().push_back (MenuElem (_("Abs"))); } boost::shared_ptr @@ -262,7 +312,14 @@ PannerUI::~PannerUI () if (pan_menu) { delete pan_menu; } - + + if (pan_astyle_menu) { + delete pan_astyle_menu; + } + + if (pan_astate_menu) { + delete pan_astate_menu; + } } @@ -662,7 +719,10 @@ PannerUI::pan_automation_state_button_event (GdkEventButton *ev) switch (ev->button) { case 1: - pan_astate_menu.popup (1, ev->time); + if (pan_astate_menu == 0) { + build_astate_menu (); + } + pan_astate_menu->popup (1, ev->time); break; default: break; @@ -680,7 +740,10 @@ PannerUI::pan_automation_style_button_event (GdkEventButton *ev) switch (ev->button) { case 1: - pan_astyle_menu.popup (1, ev->time); + if (pan_astyle_menu == 0) { + build_astyle_menu (); + } + pan_astyle_menu->popup (1, ev->time); break; default: break; diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h index e10080a317..4501659750 100644 --- a/gtk2_ardour/panner_ui.h +++ b/gtk2_ardour/panner_ui.h @@ -54,9 +54,11 @@ namespace Gtk { class PannerUI : public Gtk::HBox { public: - PannerUI (boost::shared_ptr, ARDOUR::Session&); + PannerUI (ARDOUR::Session&); ~PannerUI (); + virtual void set_io (boost::shared_ptr); + void pan_changed (void *); void update_pan_sensitive (); @@ -75,6 +77,7 @@ class PannerUI : public Gtk::HBox boost::shared_ptr _io; ARDOUR::Session& _session; + std::vector connections; bool ignore_toggle; bool in_pan_update; @@ -101,8 +104,8 @@ class PannerUI : public Gtk::HBox bool panning_link_button_press (GdkEventButton*); bool panning_link_button_release (GdkEventButton*); - Gtk::Menu pan_astate_menu; - Gtk::Menu pan_astyle_menu; + Gtk::Menu* pan_astate_menu; + Gtk::Menu* pan_astyle_menu; Gtk::Button pan_automation_style_button; Gtk::ToggleButton pan_automation_state_button; @@ -118,6 +121,8 @@ class PannerUI : public Gtk::HBox void update_pan_bars (bool only_if_aplay); void update_pan_linkage (); void update_pan_state (); + void build_astate_menu (); + void build_astyle_menu (); void panner_changed (); diff --git a/gtk2_ardour/port_group.h b/gtk2_ardour/port_group.h new file mode 100644 index 0000000000..d5334640b1 --- /dev/null +++ b/gtk2_ardour/port_group.h @@ -0,0 +1,90 @@ +#ifndef __gtk_ardour_port_group_h__ +#define __gtk_ardour_port_group_h__ + +#include +#include + +#include +#include + +#include + +namespace ARDOUR { + class Session; + class IO; + class PortInsert; +} + +class PortMatrix; + +/// A list of port names, grouped by some aspect of their type e.g. busses, tracks, system +class PortGroup +{ + public: + /** PortGroup constructor. + * @param n Name. + * @param p Port name prefix. + * @param v true if group should be visible in the UI, otherwise false. + */ + PortGroup (std::string const & n, std::string const & p, bool v) : name (n), prefix (p), visible (v) {} + + void add (std::string const & p); + + std::string name; ///< name for the group + std::string prefix; ///< prefix (before colon) e.g. "ardour:" + std::vector ports; ///< port names + bool visible; ///< true if the group is visible in the UI +}; + +/// The UI for a PortGroup +class PortGroupUI +{ + public: + PortGroupUI (PortMatrix&, PortGroup&); + + Gtk::Widget& get_visibility_checkbutton (); + PortGroup& port_group () { return _port_group; } + void setup_visibility (); + + private: + void port_checkbutton_toggled (Gtk::CheckButton*, int, int); + bool port_checkbutton_release (GdkEventButton* ev, Gtk::CheckButton* b, int r, int c); + void visibility_checkbutton_toggled (); + + PortMatrix& _port_matrix; ///< the PortMatrix that we are working for + PortGroup& _port_group; ///< the PortGroup that we are representing + bool _ignore_check_button_toggle; + Gtk::CheckButton _visibility_checkbutton; +}; + +/// A list of PortGroups +class PortGroupList : public std::list +{ + public: + enum Mask { + BUSS = 0x1, + TRACK = 0x2, + SYSTEM = 0x4, + OTHER = 0x8 + }; + + PortGroupList (ARDOUR::Session &, ARDOUR::DataType, bool, Mask); + + void refresh (); + int n_visible_ports () const; + std::string get_port_by_index (int, bool with_prefix = true) const; + void set_type (ARDOUR::DataType); + void set_offer_inputs (bool); + + private: + ARDOUR::Session& _session; + ARDOUR::DataType _type; + bool _offer_inputs; + + PortGroup buss; + PortGroup track; + PortGroup system; + PortGroup other; +}; + +#endif /* __gtk_ardour_port_group_h__ */ diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc index cff4a3328e..b1dd2a17ac 100644 --- a/gtk2_ardour/port_matrix.cc +++ b/gtk2_ardour/port_matrix.cc @@ -69,59 +69,8 @@ PortGroupUI::PortGroupUI (PortMatrix& m, PortGroup& g) , _ignore_check_button_toggle (false) , _visibility_checkbutton (g.name) { - int const ports = _port_group.ports.size(); - int const rows = _port_matrix.n_rows (); - - if (rows == 0 || ports == 0) { - return; - } - - /* Sort out the table and the checkbuttons inside it */ - - _table.resize (rows, ports); - _port_checkbuttons.resize (rows); - for (int i = 0; i < rows; ++i) { - _port_checkbuttons[i].resize (ports); - } - - - for (int i = 0; i < rows; ++i) { - for (uint32_t j = 0; j < _port_group.ports.size(); ++j) { - CheckButton* b = new CheckButton; - - b->signal_toggled().connect ( - sigc::bind (sigc::mem_fun (*this, &PortGroupUI::port_checkbutton_toggled), b, i, j)); - - b->signal_button_release_event().connect ( - sigc::bind (sigc::mem_fun (*this, &PortGroupUI::port_checkbutton_release), b, i, j), false); - - _port_checkbuttons[i][j] = b; - - cerr << this << " bind to " << &_port_checkbuttons << " via " << b - << endl; - - _table.attach (*b, j, j + 1, i, i + 1); - } - } - - _table_box.add (_table); - - _ignore_check_button_toggle = true; - - /* Set the state of the check boxes according to current connections */ - for (int i = 0; i < rows; ++i) { - for (uint32_t j = 0; j < _port_group.ports.size(); ++j) { - std::string const t = _port_group.prefix + _port_group.ports[j]; - bool const s = _port_matrix.get_state (i, t); - _port_checkbuttons[i][j]->set_active (s); - if (s) { - _port_group.visible = true; - } - } - } - + _port_group.visible = true; _ignore_check_button_toggle = false; - _visibility_checkbutton.signal_toggled().connect (sigc::mem_fun (*this, &PortGroupUI::visibility_checkbutton_toggled)); } @@ -132,34 +81,6 @@ PortGroupUI::visibility_checkbutton_toggled () _port_group.visible = _visibility_checkbutton.get_active (); } -/** @return Width and height of a single checkbutton in a port group table */ -std::pair -PortGroupUI::unit_size () const -{ - if (_port_checkbuttons.empty() || _port_checkbuttons[0].empty()) - { - return std::pair (0, 0); - } - - int r = 0; - /* We can't ask for row spacing unless there >1 rows, otherwise we get a warning */ - if (_table.property_n_rows() > 1) { - r = _table.get_row_spacing (0); - } - - return std::make_pair ( - _port_checkbuttons[0][0]->get_width() + _table.get_col_spacing (0), - _port_checkbuttons[0][0]->get_height() + r - ); -} - -/** @return Table widget containing the port checkbuttons */ -Widget& -PortGroupUI::get_table () -{ - return _table_box; -} - /** @return Checkbutton used to toggle visibility */ Widget& PortGroupUI::get_visibility_checkbutton () @@ -173,324 +94,37 @@ void PortGroupUI::port_checkbutton_toggled (CheckButton* b, int r, int c) { if (_ignore_check_button_toggle == false) { - _port_matrix.set_state (r, _port_group.prefix + _port_group.ports[c], b->get_active(), 0); + // _port_matrix.hide_group (_port_group); } } -bool -PortGroupUI::port_checkbutton_release (GdkEventButton* ev, CheckButton* b, int r, int c) -{ - cerr << this << " RELEASE on " << b << " state = " << ev->state << endl; - - if (ev->state == 0) { - /* let usual toggle handler take care of it */ - return false; - } - - /* The fun starts here - */ - - const size_t ports = _port_group.ports.size(); - const size_t rows = _port_matrix.n_rows (); - - if (rows == 0 || ports == 0) { - return true; - } - - /* For each port in the group, change the state of - the connection for the corresponding "connector" port. - */ - - for (size_t j = c; j < ports; ++j) { - - /* we've got a port to connect, now lets find the thing to - connect it too ... (search "down" the rows) - */ - - cerr << "we're going to connect port " << j << " of " << ports << endl; - - for (size_t i = r; i < rows; ++i) { - - cerr << this << " going to connect to row " << i << " of " << rows << endl; - cerr << "access [" << i << "][" << j << "]\n"; - cerr << " @ " << &_port_checkbuttons << endl; - - _port_checkbuttons[i][j]->set_active (!_port_checkbuttons[i][j]->get_active()); - - /* next time, get at least as far as this port before looking - for more. - */ - - r = i + 1; - - /* changed connection state, stop looking for more */ - - break; - } - } - - return true; -} - /** Set up visibility of the port group according to PortGroup::visible */ void PortGroupUI::setup_visibility () { - if (!_port_group.ports.empty() && _port_group.visible) { - _table_box.show (); - } else { - _table_box.hide (); - } - if (_visibility_checkbutton.get_active () != _port_group.visible) { - _visibility_checkbutton.set_active (_port_group.visible); } } -RotatedLabelSet::RotatedLabelSet (PortGroupList& g) - : Glib::ObjectBase ("RotatedLabelSet"), Widget (), _port_group_list (g), _base_width (128) -{ - set_flags (NO_WINDOW); - if (getenv ("AD_ANGLE") != 0) { - set_angle (atoi (getenv ("AD_ANGLE"))); - } else { - set_angle (45); - } -} - -RotatedLabelSet::~RotatedLabelSet () -{ - -} - - -/** Set the angle that the labels are drawn at. - * @param degrees New angle in degrees. - */ - -void -RotatedLabelSet::set_angle (int degrees) -{ - _angle_degrees = degrees; - _angle_radians = M_PI * _angle_degrees / 180; - - queue_resize (); -} - -void -RotatedLabelSet::on_size_request (Requisition* requisition) -{ - *requisition = Requisition (); - - if (_pango_layout == 0) { - return; - } - - /* Our height is the highest label */ - requisition->height = 0; - for (PortGroupList::const_iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) { - for (std::vector::const_iterator j = (*i)->ports.begin(); j != (*i)->ports.end(); ++j) { - std::pair const d = setup_layout (*j); - if (d.second > requisition->height) { - requisition->height = d.second; - } - } - } - - /* And our width is the base plus the width of the last label */ - requisition->width = _base_width; - int const n = _port_group_list.n_visible_ports (); - if (n > 0) { - std::pair const d = setup_layout (_port_group_list.get_port_by_index (n - 1, false)); - requisition->width += d.first; - } - - cerr << "Labels will be " << requisition->width << " x " << requisition->height << endl; -} - -void -RotatedLabelSet::on_size_allocate (Allocation& allocation) -{ - set_allocation (allocation); - - if (_gdk_window) { - _gdk_window->move_resize (allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height()); - } -} - -void -RotatedLabelSet::on_realize () -{ - Widget::on_realize (); - - Glib::RefPtr