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 AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r,
53 boost::shared_ptr<Automatable> a, boost::shared_ptr<AutomationControl> c,
54 PublicEditor& e, TimeAxisView& parent, bool show_regions,
55 ArdourCanvas::Canvas& canvas, const string & nom, const string & nomparent)
58 TimeAxisView (s, e, &parent, canvas),
62 _controller(AutomationController::create(a, c->list(), c)),
64 _view (show_regions ? new AutomationStreamView(*this) : NULL),
66 height_button (_("h")),
67 clear_button (_("clear")),
68 auto_button (X_("")) /* force addition of a label */
70 if (!have_name_font) {
71 name_font = get_font_for_style (X_("AutomationTrackName"));
72 have_name_font = true;
80 mode_discrete_item = 0;
83 ignore_state_request = false;
84 first_call_to_set_height = true;
86 _base_rect = new SimpleRect(*canvas_display);
87 _base_rect->property_x1() = 0.0;
88 _base_rect->property_y1() = 0.0;
89 _base_rect->property_x2() = editor.frame_to_pixel (max_frames);
90 _base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackOutline.get();
92 /* outline ends and bottom */
93 _base_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);
94 _base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackFill.get();
96 _base_rect->set_data ("trackview", this);
98 _base_rect->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_automation_track_event),
101 _base_rect->lower_to_bottom();
103 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
105 height_button.set_name ("TrackSizeButton");
106 auto_button.set_name ("TrackVisualButton");
107 clear_button.set_name ("TrackVisualButton");
108 hide_button.set_name ("TrackRemoveButton");
110 controls_table.set_no_show_all();
112 ARDOUR_UI::instance()->tooltips().set_tip(height_button, _("track height"));
113 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
114 ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track"));
115 ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
117 /* rearrange the name display */
119 /* we never show these for automation tracks, so make
120 life easier and remove them.
125 /* move the name label over a bit */
127 string shortpname = _name;
128 bool shortened = false;
131 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
133 if (shortpname != _name ){
137 name_label.set_text (shortpname);
138 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
140 if (nomparent.length()) {
142 /* limit the plug name string */
144 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
145 if (pname != nomparent) {
149 plugname = new Label (pname);
150 plugname->set_name (X_("TrackPlugName"));
152 name_label.set_name (X_("TrackParameterName"));
153 controls_table.remove (name_hbox);
154 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
155 plugname_packed = true;
156 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
159 plugname_packed = false;
163 string tipname = nomparent;
164 if (!tipname.empty()) {
168 ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
171 /* add the buttons */
172 controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
173 controls_table.attach (height_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
175 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
176 controls_table.attach (clear_button, 5, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
178 /* add bar controller */
179 controls_table.attach (*_controller.get(), 0, 8, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
181 controls_table.show_all ();
183 height_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::height_clicked));
184 clear_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::clear_clicked));
185 hide_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
186 auto_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::auto_clicked));
188 controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
189 controls_base_unselected_name = X_("AutomationTrackControlsBase");
190 controls_ebox.set_name (controls_base_unselected_name);
192 controls_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
194 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
195 _control->parameter());
198 set_state (*xml_node);
201 /* ask for notifications of any new RegionViews */
207 /* no regions, just a single line for the entire track (e.g. bus gain) */
210 boost::shared_ptr<AutomationLine> line(new AutomationLine (
211 _control->parameter().to_string(),
216 line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
217 line->queue_reset ();
221 /* make sure labels etc. are correct */
223 automation_state_changed ();
224 ColorsChanged.connect (mem_fun (*this, &AutomationTimeAxisView::color_handler));
227 AutomationTimeAxisView::~AutomationTimeAxisView ()
232 AutomationTimeAxisView::auto_clicked ()
234 using namespace Menu_Helpers;
236 if (automation_menu == 0) {
237 automation_menu = manage (new Menu);
238 automation_menu->set_name ("ArdourContextMenu");
239 MenuList& items (automation_menu->items());
241 items.push_back (MenuElem (_("Manual"),
242 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
243 items.push_back (MenuElem (_("Play"),
244 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
245 items.push_back (MenuElem (_("Write"),
246 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
247 items.push_back (MenuElem (_("Touch"),
248 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
251 automation_menu->popup (1, gtk_get_current_event_time());
255 AutomationTimeAxisView::set_automation_state (AutoState state)
257 if (!ignore_state_request) {
258 if (_route == _automatable) { // FIXME: ew
259 _route->set_parameter_automation_state (
260 _control->parameter(),
264 _control->list()->set_automation_state(state);
270 AutomationTimeAxisView::automation_state_changed ()
274 /* update button label */
279 state = _control->list()->automation_state ();
282 switch (state & (Off|Play|Touch|Write)) {
284 auto_button.set_label (_("Manual"));
286 ignore_state_request = true;
287 auto_off_item->set_active (true);
288 auto_play_item->set_active (false);
289 auto_touch_item->set_active (false);
290 auto_write_item->set_active (false);
291 ignore_state_request = false;
295 auto_button.set_label (_("Play"));
296 if (auto_play_item) {
297 ignore_state_request = true;
298 auto_play_item->set_active (true);
299 auto_off_item->set_active (false);
300 auto_touch_item->set_active (false);
301 auto_write_item->set_active (false);
302 ignore_state_request = false;
306 auto_button.set_label (_("Write"));
307 if (auto_write_item) {
308 ignore_state_request = true;
309 auto_write_item->set_active (true);
310 auto_off_item->set_active (false);
311 auto_play_item->set_active (false);
312 auto_touch_item->set_active (false);
313 ignore_state_request = false;
317 auto_button.set_label (_("Touch"));
318 if (auto_touch_item) {
319 ignore_state_request = true;
320 auto_touch_item->set_active (true);
321 auto_off_item->set_active (false);
322 auto_play_item->set_active (false);
323 auto_write_item->set_active (false);
324 ignore_state_request = false;
328 auto_button.set_label (_("???"));
334 AutomationTimeAxisView::interpolation_changed ()
336 AutomationList::InterpolationStyle style = _control->list()->interpolation();
338 if (mode_line_item && mode_discrete_item) {
339 if (style == AutomationList::Discrete) {
340 mode_discrete_item->set_active(true);
341 mode_line_item->set_active(false);
343 mode_line_item->set_active(true);
344 mode_discrete_item->set_active(false);
349 _line->set_interpolation(style);
353 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
355 _control->list()->set_interpolation(style);
357 _line->set_interpolation(style);
361 AutomationTimeAxisView::height_clicked ()
367 AutomationTimeAxisView::clear_clicked ()
369 _session.begin_reversible_command (_("clear automation"));
372 _session.commit_reversible_command ();
376 AutomationTimeAxisView::set_height (TrackHeight ht)
378 uint32_t h = height_to_pixels (ht);
379 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
381 if (first_call_to_set_height)
382 first_call_to_set_height = false;
384 TimeAxisView::set_height (ht);
385 _base_rect->property_y2() = h;
388 _line->set_y_position_and_height (0, h);
391 _view->set_height(h);
392 _view->update_contents_y_position_and_height();
395 TimeAxisView* state_parent = get_parent_with_state ();
396 assert(state_parent);
398 XMLNode* xml_node = state_parent->get_automation_child_xml_node(_control->parameter());
403 xml_node->add_property ("track_height", "largest");
407 xml_node->add_property ("track_height", "large");
411 xml_node->add_property ("track_height", "larger");
415 xml_node->add_property ("track_height", "normal");
419 xml_node->add_property ("track_height", "smaller");
423 xml_node->add_property ("track_height", "small");
431 _controller->show ();
437 controls_table.remove (name_hbox);
440 if (plugname_packed) {
441 controls_table.remove (*plugname);
442 plugname_packed = false;
444 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
445 plugname_packed = true;
446 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
448 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
452 name_hbox.show_all ();
455 height_button.show();
457 hide_button.show_all();
465 controls_table.remove (name_hbox);
467 if (plugname_packed) {
468 controls_table.remove (*plugname);
469 plugname_packed = false;
472 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
473 controls_table.hide_all ();
476 name_hbox.show_all ();
479 height_button.hide();
486 /* only emit the signal if the height really changed */
487 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
492 AutomationTimeAxisView::set_samples_per_unit (double spu)
494 TimeAxisView::set_samples_per_unit (spu);
500 _view->set_samples_per_unit (spu);
504 AutomationTimeAxisView::hide_clicked ()
506 // LAME fix for refreshing the hide button
507 hide_button.set_sensitive(false);
509 set_marked_for_display (false);
512 hide_button.set_sensitive(true);
516 AutomationTimeAxisView::build_display_menu ()
518 using namespace Menu_Helpers;
520 /* get the size menu ready */
526 TimeAxisView::build_display_menu ();
528 /* now fill it with our stuff */
530 MenuList& items = display_menu->items();
532 items.push_back (MenuElem (_("Height"), *size_menu));
533 items.push_back (SeparatorElem());
534 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
535 items.push_back (SeparatorElem());
536 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
537 items.push_back (SeparatorElem());
541 Menu* auto_state_menu = manage (new Menu);
542 auto_state_menu->set_name ("ArdourContextMenu");
543 MenuList& as_items = auto_state_menu->items();
545 as_items.push_back (CheckMenuElem (_("Manual"),
546 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
547 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
549 as_items.push_back (CheckMenuElem (_("Play"),
550 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
551 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
553 as_items.push_back (CheckMenuElem (_("Write"),
554 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
555 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
557 as_items.push_back (CheckMenuElem (_("Touch"),
558 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
559 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
561 items.push_back (MenuElem (_("State"), *auto_state_menu));
565 if (_control->parameter().type() == MidiCCAutomation) {
566 Menu* auto_mode_menu = manage (new Menu);
567 auto_mode_menu->set_name ("ArdourContextMenu");
568 MenuList& am_items = auto_mode_menu->items();
570 RadioMenuItem::Group group;
572 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
573 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
574 AutomationList::Discrete)));
575 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
576 //mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
578 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
579 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
580 AutomationList::Linear)));
581 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
582 //mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
584 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
587 /* make sure the automation menu state is correct */
589 automation_state_changed ();
590 interpolation_changed ();
594 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent* event, nframes_t when, double y)
601 canvas_display->w2i (x, y);
603 /* compute vertical fractional position */
605 y = 1.0 - (y / height);
609 _line->view_to_model_y (y);
611 _session.begin_reversible_command (_("add automation event"));
612 XMLNode& before = _control->list()->get_state();
614 _control->list()->add (when, y);
616 XMLNode& after = _control->list()->get_state();
617 _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->list().get(), &before, &after));
619 _session.set_dirty ();
624 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
626 return (_line ? cut_copy_clear_one (*_line, selection, op) : false);
630 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
632 AutomationList* what_we_got = 0;
633 boost::shared_ptr<AutomationList> alist (line.the_list());
636 XMLNode &before = alist->get_state();
640 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
641 editor.get_cut_buffer().add (what_we_got);
642 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
647 if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) {
648 editor.get_cut_buffer().add (what_we_got);
653 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
654 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
663 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
664 double foo = (*x)->value;
665 line.model_to_view_y (foo);
674 AutomationTimeAxisView::reset_objects (PointSelection& selection)
676 reset_objects_one (*_line, selection);
680 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
682 boost::shared_ptr<AutomationList> alist(line.the_list());
684 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
686 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
688 if (&(*i).track != this) {
692 alist->reset_range ((*i).start, (*i).end);
697 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
699 return cut_copy_clear_objects_one (*_line, selection, op);
703 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
705 AutomationList* what_we_got = 0;
706 boost::shared_ptr<AutomationList> alist(line.the_list());
709 XMLNode &before = alist->get_state();
711 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
713 if (&(*i).track != this) {
719 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
720 editor.get_cut_buffer().add (what_we_got);
721 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
726 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
727 editor.get_cut_buffer().add (what_we_got);
732 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
733 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
745 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
746 double foo = (*x)->value;
747 line.model_to_view_y (foo);
756 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
758 return paste_one (*_line, pos, times, selection, nth);
762 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
764 AutomationSelection::iterator p;
765 boost::shared_ptr<AutomationList> alist(line.the_list());
767 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth);
769 if (p == selection.lines.end()) {
773 /* Make a copy of the list because we have to scale the
774 values from view coordinates to model coordinates, and we're
775 not supposed to modify the points in the selection.
778 AutomationList copy (**p);
780 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
781 double foo = (*x)->value;
782 line.view_to_model_y (foo);
786 XMLNode &before = alist->get_state();
787 alist->paste (copy, pos, times);
788 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
794 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
796 if (_line && touched (top, bot)) {
800 /* remember: this is X Window - coordinate space starts in upper left and moves down.
801 y_position is the "origin" or "top" of the track.
804 double mybot = y_position + height;
806 if (y_position >= top && mybot <= bot) {
808 /* y_position is below top, mybot is above bot, so we're fully
817 /* top and bot are within y_position .. mybot */
819 topfrac = 1.0 - ((top - y_position) / height);
820 botfrac = 1.0 - ((bot - y_position) / height);
824 _line->get_selectables (start, end, botfrac, topfrac, results);
829 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
832 _line->get_inverted_selectables (sel, result);
836 AutomationTimeAxisView::set_selected_points (PointSelection& points)
839 _line->set_selected_points (points);
843 AutomationTimeAxisView::clear_lines ()
846 automation_connection.disconnect ();
850 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
854 assert(line->the_list() == _control->list());
856 automation_connection = _control->list()->automation_state_changed.connect
857 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
860 //_controller = AutomationController::create(_session, line->the_list(), _control);
862 line->set_y_position_and_height (0, height);
864 /* pick up the current state */
865 automation_state_changed ();
871 AutomationTimeAxisView::entered()
874 _line->track_entered();
878 AutomationTimeAxisView::exited ()
881 _line->track_exited();
885 AutomationTimeAxisView::set_colors ()
887 for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
896 AutomationTimeAxisView::color_handler ()
904 AutomationTimeAxisView::set_state (const XMLNode& node)
906 TimeAxisView::set_state (node);
909 XMLNodeConstIterator iter;
911 kids = node.children ();
913 for (iter = kids.begin(); iter != kids.end(); ++iter) {
915 if ((*iter)->name() == state_node_name) {
916 XMLProperty* type = (*iter)->property("automation-id");
918 if (type && type->value() == _control->parameter().to_string()) {
919 XMLProperty *shown = (*iter)->property("shown_editor");
921 if (shown && shown->value() == "yes") {
922 set_marked_for_display(true);
923 canvas_display->show(); /* FIXME: necessary? show_at? */
930 if (!_marked_for_display)
935 AutomationTimeAxisView::get_state_node ()
937 TimeAxisView* state_parent = get_parent_with_state ();
940 return state_parent->get_automation_child_xml_node (_control->parameter());
947 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
949 XMLNode* xml_node = get_state_node();
950 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
954 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
956 update_extra_xml_shown (true);
958 return TimeAxisView::show_at (y, nth, parent);
962 AutomationTimeAxisView::hide ()
964 update_extra_xml_shown (false);
966 TimeAxisView::hide ();