2 Copyright (C) 2000-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <ardour/route.h>
22 #include <ardour/automation_control.h>
23 #include <pbd/memento_command.h>
24 #include <gtkmm2ext/barcontroller.h>
26 #include "ardour_ui.h"
27 #include "automation_time_axis.h"
28 #include "automation_streamview.h"
29 #include "route_time_axis.h"
30 #include "automation_line.h"
31 #include "public_editor.h"
32 #include "simplerect.h"
33 #include "selection.h"
34 #include "rgb_macros.h"
35 #include "automation_selectable.h"
36 #include "point_selection.h"
37 #include "canvas_impl.h"
42 using namespace ARDOUR;
45 using namespace Gtkmm2ext;
46 using namespace Editing;
48 Pango::FontDescription* AutomationTimeAxisView::name_font = 0;
49 bool AutomationTimeAxisView::have_name_font = false;
50 const string AutomationTimeAxisView::state_node_name = "AutomationChild";
52 /** \a a the automatable object this time axis is to display data for.
53 * For route/track automation (e.g. gain) pass the route for both \r and \a.
54 * For route child (e.g. plugin) automation, pass the child for \a.
55 * For region automation (e.g. MIDI CC), pass null for \a.
57 AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r,
58 boost::shared_ptr<Automatable> a, boost::shared_ptr<AutomationControl> c,
59 PublicEditor& e, TimeAxisView& parent, bool show_regions,
60 ArdourCanvas::Canvas& canvas, const string & nom, const string & nomparent)
62 TimeAxisView (s, e, &parent, canvas),
66 _controller(AutomationController::create(a, c->parameter(), c)),
68 _view (show_regions ? new AutomationStreamView(*this) : NULL),
70 height_button (_("h")),
71 clear_button (_("clear")),
72 auto_button (X_("")) /* force addition of a label */
74 if (!have_name_font) {
75 name_font = get_font_for_style (X_("AutomationTrackName"));
76 have_name_font = true;
84 mode_discrete_item = 0;
87 ignore_state_request = false;
88 first_call_to_set_height = true;
90 _base_rect = new SimpleRect(*canvas_display);
91 _base_rect->property_x1() = 0.0;
92 _base_rect->property_y1() = 0.0;
93 _base_rect->property_x2() = editor.frame_to_pixel (max_frames);
94 _base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackOutline.get();
96 /* outline ends and bottom */
97 _base_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);
98 _base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackFill.get();
100 _base_rect->set_data ("trackview", this);
102 _base_rect->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_automation_track_event),
105 _base_rect->lower_to_bottom();
107 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
109 height_button.set_name ("TrackSizeButton");
110 auto_button.set_name ("TrackVisualButton");
111 clear_button.set_name ("TrackVisualButton");
112 hide_button.set_name ("TrackRemoveButton");
114 controls_table.set_no_show_all();
116 ARDOUR_UI::instance()->tooltips().set_tip(height_button, _("track height"));
117 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
118 ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track"));
119 ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
121 /* rearrange the name display */
123 /* we never show these for automation tracks, so make
124 life easier and remove them.
129 /* move the name label over a bit */
131 string shortpname = _name;
132 bool shortened = false;
135 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
137 if (shortpname != _name ){
141 name_label.set_text (shortpname);
142 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
144 if (nomparent.length()) {
146 /* limit the plug name string */
148 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
149 if (pname != nomparent) {
153 plugname = new Label (pname);
154 plugname->set_name (X_("TrackPlugName"));
156 name_label.set_name (X_("TrackParameterName"));
157 controls_table.remove (name_hbox);
158 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
159 plugname_packed = true;
160 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
163 plugname_packed = false;
167 string tipname = nomparent;
168 if (!tipname.empty()) {
172 ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
175 /* add the buttons */
176 controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
177 controls_table.attach (height_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
179 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
180 controls_table.attach (clear_button, 5, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
182 /* add bar controller */
183 controls_table.attach (*_controller.get(), 0, 8, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
185 controls_table.show_all ();
187 height_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::height_clicked));
188 clear_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::clear_clicked));
189 hide_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
190 auto_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::auto_clicked));
192 controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
193 controls_base_unselected_name = X_("AutomationTrackControlsBase");
194 controls_ebox.set_name (controls_base_unselected_name);
196 controls_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
198 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
199 _control->parameter());
202 set_state (*xml_node);
205 /* ask for notifications of any new RegionViews */
211 /* no regions, just a single line for the entire track (e.g. bus gain) */
214 boost::shared_ptr<AutomationLine> line(new AutomationLine (
215 ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter()),
220 line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
221 line->queue_reset ();
225 /* make sure labels etc. are correct */
227 automation_state_changed ();
228 ColorsChanged.connect (mem_fun (*this, &AutomationTimeAxisView::color_handler));
231 AutomationTimeAxisView::~AutomationTimeAxisView ()
236 AutomationTimeAxisView::auto_clicked ()
238 using namespace Menu_Helpers;
240 if (automation_menu == 0) {
241 automation_menu = manage (new Menu);
242 automation_menu->set_name ("ArdourContextMenu");
243 MenuList& items (automation_menu->items());
245 items.push_back (MenuElem (_("Manual"), bind (mem_fun(*this,
246 &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
247 items.push_back (MenuElem (_("Play"), bind (mem_fun(*this,
248 &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
249 items.push_back (MenuElem (_("Write"), bind (mem_fun(*this,
250 &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
251 items.push_back (MenuElem (_("Touch"), bind (mem_fun(*this,
252 &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
255 automation_menu->popup (1, gtk_get_current_event_time());
259 AutomationTimeAxisView::set_automation_state (AutoState state)
261 if (!ignore_state_request) {
262 if (_route == _automatable) { // This is a time axis for route (not region) automation
263 _route->set_parameter_automation_state (_control->parameter(), state);
266 if (_control->list())
267 _control->alist()->set_automation_state(state);
270 _view->set_automation_state (state);
274 AutomationTimeAxisView::automation_state_changed ()
278 /* update button label */
283 state = _control->alist()->automation_state ();
286 switch (state & (Off|Play|Touch|Write)) {
288 auto_button.set_label (_("Manual"));
290 ignore_state_request = true;
291 auto_off_item->set_active (true);
292 auto_play_item->set_active (false);
293 auto_touch_item->set_active (false);
294 auto_write_item->set_active (false);
295 ignore_state_request = false;
299 auto_button.set_label (_("Play"));
300 if (auto_play_item) {
301 ignore_state_request = true;
302 auto_play_item->set_active (true);
303 auto_off_item->set_active (false);
304 auto_touch_item->set_active (false);
305 auto_write_item->set_active (false);
306 ignore_state_request = false;
310 auto_button.set_label (_("Write"));
311 if (auto_write_item) {
312 ignore_state_request = true;
313 auto_write_item->set_active (true);
314 auto_off_item->set_active (false);
315 auto_play_item->set_active (false);
316 auto_touch_item->set_active (false);
317 ignore_state_request = false;
321 auto_button.set_label (_("Touch"));
322 if (auto_touch_item) {
323 ignore_state_request = true;
324 auto_touch_item->set_active (true);
325 auto_off_item->set_active (false);
326 auto_play_item->set_active (false);
327 auto_write_item->set_active (false);
328 ignore_state_request = false;
332 auto_button.set_label (_("???"));
338 AutomationTimeAxisView::interpolation_changed ()
340 AutomationList::InterpolationStyle style = _control->list()->interpolation();
342 if (mode_line_item && mode_discrete_item) {
343 if (style == AutomationList::Discrete) {
344 mode_discrete_item->set_active(true);
345 mode_line_item->set_active(false);
347 mode_line_item->set_active(true);
348 mode_discrete_item->set_active(false);
353 _line->set_interpolation(style);
357 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
359 _control->list()->set_interpolation(style);
361 _line->set_interpolation(style);
365 AutomationTimeAxisView::height_clicked ()
371 AutomationTimeAxisView::clear_clicked ()
373 _session.begin_reversible_command (_("clear automation"));
376 _session.commit_reversible_command ();
380 AutomationTimeAxisView::set_height (uint32_t h)
382 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
383 bool changed_between_small_and_normal = ( (h == hSmall || h == hSmaller) ^ (height == hSmall || height == hSmaller) );
385 TimeAxisView* state_parent = get_parent_with_state ();
387 assert(state_parent);
388 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
390 TimeAxisView::set_height (h);
391 _base_rect->property_y2() = h;
394 _line->set_height(h);
397 _view->set_height(h);
398 _view->update_contents_height();
402 snprintf (buf, sizeof (buf), "%u", height);
403 xml_node->add_property ("height", buf);
405 if (changed_between_small_and_normal || first_call_to_set_height) {
407 first_call_to_set_height = false;
410 controls_table.remove (name_hbox);
413 if (plugname_packed) {
414 controls_table.remove (*plugname);
415 plugname_packed = false;
417 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
418 plugname_packed = true;
419 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
421 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
425 name_hbox.show_all ();
428 height_button.show();
430 hide_button.show_all();
432 } else if (h >= hSmall) {
433 controls_table.remove (name_hbox);
435 if (plugname_packed) {
436 controls_table.remove (*plugname);
437 plugname_packed = false;
440 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
441 controls_table.hide_all ();
444 name_hbox.show_all ();
447 height_button.hide();
451 } else if (h >= hNormal){
453 height_button.show();
455 hide_button.show_all();
459 /* only emit the signal if the height really changed */
460 _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
465 AutomationTimeAxisView::set_samples_per_unit (double spu)
467 TimeAxisView::set_samples_per_unit (spu);
473 _view->set_samples_per_unit (spu);
477 AutomationTimeAxisView::hide_clicked ()
479 // LAME fix for refreshing the hide button
480 hide_button.set_sensitive(false);
482 set_marked_for_display (false);
485 hide_button.set_sensitive(true);
489 AutomationTimeAxisView::build_display_menu ()
491 using namespace Menu_Helpers;
493 /* get the size menu ready */
499 TimeAxisView::build_display_menu ();
501 /* now fill it with our stuff */
503 MenuList& items = display_menu->items();
505 items.push_back (MenuElem (_("Height"), *size_menu));
506 items.push_back (SeparatorElem());
507 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
508 items.push_back (SeparatorElem());
509 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
510 items.push_back (SeparatorElem());
514 Menu* auto_state_menu = manage (new Menu);
515 auto_state_menu->set_name ("ArdourContextMenu");
516 MenuList& as_items = auto_state_menu->items();
518 as_items.push_back (CheckMenuElem (_("Manual"),
519 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
520 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
522 as_items.push_back (CheckMenuElem (_("Play"),
523 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
524 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
526 as_items.push_back (CheckMenuElem (_("Write"),
527 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
528 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
530 as_items.push_back (CheckMenuElem (_("Touch"),
531 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
532 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
534 items.push_back (MenuElem (_("State"), *auto_state_menu));
538 if (_control->parameter().type() == MidiCCAutomation) {
539 Menu* auto_mode_menu = manage (new Menu);
540 auto_mode_menu->set_name ("ArdourContextMenu");
541 MenuList& am_items = auto_mode_menu->items();
543 RadioMenuItem::Group group;
545 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
546 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
547 AutomationList::Discrete)));
548 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
549 //mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
551 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
552 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
553 AutomationList::Linear)));
554 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
555 //mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
557 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
560 /* make sure the automation menu state is correct */
562 automation_state_changed ();
563 interpolation_changed ();
567 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent* event, nframes_t when, double y)
574 canvas_display->w2i (x, y);
576 /* compute vertical fractional position */
578 y = 1.0 - (y / height);
582 _line->view_to_model_y (y);
584 _session.begin_reversible_command (_("add automation event"));
585 XMLNode& before = _control->alist()->get_state();
587 _control->alist()->add (when, y);
589 XMLNode& after = _control->alist()->get_state();
590 _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->alist(), &before, &after));
592 _session.set_dirty ();
597 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
599 return (_line ? cut_copy_clear_one (*_line, selection, op) : false);
603 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
605 boost::shared_ptr<Evoral::ControlList> what_we_got;
606 boost::shared_ptr<AutomationList> alist (line.the_list());
609 XMLNode &before = alist->get_state();
613 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
614 editor.get_cut_buffer().add (what_we_got);
615 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
620 if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) {
621 editor.get_cut_buffer().add (what_we_got);
626 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
627 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
634 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
635 double foo = (*x)->value;
636 line.model_to_view_y (foo);
645 AutomationTimeAxisView::reset_objects (PointSelection& selection)
647 reset_objects_one (*_line, selection);
651 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
653 boost::shared_ptr<AutomationList> alist(line.the_list());
655 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
657 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
659 if (&(*i).track != this) {
663 alist->reset_range ((*i).start, (*i).end);
668 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
670 return cut_copy_clear_objects_one (*_line, selection, op);
674 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
676 boost::shared_ptr<Evoral::ControlList> what_we_got;
677 boost::shared_ptr<AutomationList> alist(line.the_list());
680 XMLNode &before = alist->get_state();
682 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
684 if (&(*i).track != this) {
690 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
691 editor.get_cut_buffer().add (what_we_got);
692 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
697 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
698 editor.get_cut_buffer().add (what_we_got);
703 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
704 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
714 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
715 double foo = (*x)->value;
716 line.model_to_view_y (foo);
725 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
727 return paste_one (*_line, pos, times, selection, nth);
731 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
733 AutomationSelection::iterator p;
734 boost::shared_ptr<AutomationList> alist(line.the_list());
736 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth);
738 if (p == selection.lines.end()) {
742 /* Make a copy of the list because we have to scale the
743 values from view coordinates to model coordinates, and we're
744 not supposed to modify the points in the selection.
747 AutomationList copy (**p);
749 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
750 double foo = (*x)->value;
751 line.view_to_model_y (foo);
755 XMLNode &before = alist->get_state();
756 alist->paste (copy, pos, times);
757 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
763 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
765 if (_line && touched (top, bot)) {
769 /* remember: this is X Window - coordinate space starts in upper left and moves down.
770 y_position is the "origin" or "top" of the track.
773 double mybot = y_position + height;
775 if (y_position >= top && mybot <= bot) {
777 /* y_position is below top, mybot is above bot, so we're fully
786 /* top and bot are within y_position .. mybot */
788 topfrac = 1.0 - ((top - y_position) / height);
789 botfrac = 1.0 - ((bot - y_position) / height);
793 _line->get_selectables (start, end, botfrac, topfrac, results);
798 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
801 _line->get_inverted_selectables (sel, result);
805 AutomationTimeAxisView::set_selected_points (PointSelection& points)
808 _line->set_selected_points (points);
812 AutomationTimeAxisView::clear_lines ()
815 automation_connection.disconnect ();
819 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
823 assert(line->the_list() == _control->list());
825 automation_connection = _control->alist()->automation_state_changed.connect
826 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
829 //_controller = AutomationController::create(_session, line->the_list(), _control);
831 line->set_height (height);
833 /* pick up the current state */
834 automation_state_changed ();
840 AutomationTimeAxisView::entered()
843 _line->track_entered();
847 AutomationTimeAxisView::exited ()
850 _line->track_exited();
854 AutomationTimeAxisView::set_colors ()
856 for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
865 AutomationTimeAxisView::color_handler ()
873 AutomationTimeAxisView::set_state (const XMLNode& node)
875 TimeAxisView::set_state (node);
878 XMLNodeConstIterator iter;
880 kids = node.children ();
882 for (iter = kids.begin(); iter != kids.end(); ++iter) {
884 if ((*iter)->name() == state_node_name) {
885 XMLProperty* type = (*iter)->property("automation-id");
887 if (type && type->value() == ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter())) {
888 XMLProperty *shown = (*iter)->property("shown-editor");
890 if (shown && shown->value() == "yes") {
891 set_marked_for_display(true);
892 canvas_display->show(); /* FIXME: necessary? show_at? */
899 if (!_marked_for_display)
906 AutomationTimeAxisView::get_state_node ()
908 TimeAxisView* state_parent = get_parent_with_state ();
911 return state_parent->get_automation_child_xml_node (_control->parameter());
918 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
920 XMLNode* xml_node = get_state_node();
922 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
927 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
929 update_extra_xml_shown (true);
931 return TimeAxisView::show_at (y, nth, parent);
935 AutomationTimeAxisView::hide ()
937 update_extra_xml_shown (false);
939 TimeAxisView::hide ();