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().symbol(),
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->alist()->set_automation_state(state);
270 AutomationTimeAxisView::automation_state_changed ()
274 /* update button label */
279 state = _control->alist()->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 (uint32_t h)
378 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
379 bool changed_between_small_and_normal = ( (h == hSmall || h == hSmaller) ^ (height == hSmall || height == hSmaller) );
381 TimeAxisView* state_parent = get_parent_with_state ();
383 assert(state_parent);
384 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
386 TimeAxisView::set_height (h);
387 _base_rect->property_y2() = h;
390 _line->set_y_position_and_height (0, h);
393 _view->set_height(h);
394 _view->update_contents_y_position_and_height();
398 snprintf (buf, sizeof (buf), "%u", height);
399 xml_node->add_property ("height", buf);
401 if (changed_between_small_and_normal || first_call_to_set_height) {
403 first_call_to_set_height = false;
406 controls_table.remove (name_hbox);
409 if (plugname_packed) {
410 controls_table.remove (*plugname);
411 plugname_packed = false;
413 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
414 plugname_packed = true;
415 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
417 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
421 name_hbox.show_all ();
424 height_button.show();
426 hide_button.show_all();
428 } else if (h >= hSmall) {
429 controls_table.remove (name_hbox);
431 if (plugname_packed) {
432 controls_table.remove (*plugname);
433 plugname_packed = false;
436 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
437 controls_table.hide_all ();
440 name_hbox.show_all ();
443 height_button.hide();
447 } else if (h >= hNormal){
449 height_button.show();
451 hide_button.show_all();
455 /* only emit the signal if the height really changed */
456 _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
461 AutomationTimeAxisView::set_samples_per_unit (double spu)
463 TimeAxisView::set_samples_per_unit (spu);
469 _view->set_samples_per_unit (spu);
473 AutomationTimeAxisView::hide_clicked ()
475 // LAME fix for refreshing the hide button
476 hide_button.set_sensitive(false);
478 set_marked_for_display (false);
481 hide_button.set_sensitive(true);
485 AutomationTimeAxisView::build_display_menu ()
487 using namespace Menu_Helpers;
489 /* get the size menu ready */
495 TimeAxisView::build_display_menu ();
497 /* now fill it with our stuff */
499 MenuList& items = display_menu->items();
501 items.push_back (MenuElem (_("Height"), *size_menu));
502 items.push_back (SeparatorElem());
503 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
504 items.push_back (SeparatorElem());
505 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
506 items.push_back (SeparatorElem());
510 Menu* auto_state_menu = manage (new Menu);
511 auto_state_menu->set_name ("ArdourContextMenu");
512 MenuList& as_items = auto_state_menu->items();
514 as_items.push_back (CheckMenuElem (_("Manual"),
515 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
516 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
518 as_items.push_back (CheckMenuElem (_("Play"),
519 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
520 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
522 as_items.push_back (CheckMenuElem (_("Write"),
523 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
524 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
526 as_items.push_back (CheckMenuElem (_("Touch"),
527 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
528 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
530 items.push_back (MenuElem (_("State"), *auto_state_menu));
534 if (_control->parameter().type() == MidiCCAutomation) {
535 Menu* auto_mode_menu = manage (new Menu);
536 auto_mode_menu->set_name ("ArdourContextMenu");
537 MenuList& am_items = auto_mode_menu->items();
539 RadioMenuItem::Group group;
541 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
542 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
543 AutomationList::Discrete)));
544 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
545 //mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
547 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
548 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
549 AutomationList::Linear)));
550 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
551 //mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
553 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
556 /* make sure the automation menu state is correct */
558 automation_state_changed ();
559 interpolation_changed ();
563 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent* event, nframes_t when, double y)
570 canvas_display->w2i (x, y);
572 /* compute vertical fractional position */
574 y = 1.0 - (y / height);
578 _line->view_to_model_y (y);
580 _session.begin_reversible_command (_("add automation event"));
581 XMLNode& before = _control->alist()->get_state();
583 _control->alist()->add (when, y);
585 XMLNode& after = _control->alist()->get_state();
586 _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->alist(), &before, &after));
588 _session.set_dirty ();
593 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
595 return (_line ? cut_copy_clear_one (*_line, selection, op) : false);
599 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
601 boost::shared_ptr<Evoral::ControlList> what_we_got;
602 boost::shared_ptr<AutomationList> alist (line.the_list());
605 XMLNode &before = alist->get_state();
609 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
610 editor.get_cut_buffer().add (what_we_got);
611 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
616 if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) {
617 editor.get_cut_buffer().add (what_we_got);
622 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
623 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
630 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
631 double foo = (*x)->value;
632 line.model_to_view_y (foo);
641 AutomationTimeAxisView::reset_objects (PointSelection& selection)
643 reset_objects_one (*_line, selection);
647 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
649 boost::shared_ptr<AutomationList> alist(line.the_list());
651 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
653 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
655 if (&(*i).track != this) {
659 alist->reset_range ((*i).start, (*i).end);
664 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
666 return cut_copy_clear_objects_one (*_line, selection, op);
670 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
672 boost::shared_ptr<Evoral::ControlList> what_we_got;
673 boost::shared_ptr<AutomationList> alist(line.the_list());
676 XMLNode &before = alist->get_state();
678 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
680 if (&(*i).track != this) {
686 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
687 editor.get_cut_buffer().add (what_we_got);
688 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
693 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
694 editor.get_cut_buffer().add (what_we_got);
699 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
700 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
710 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
711 double foo = (*x)->value;
712 line.model_to_view_y (foo);
721 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
723 return paste_one (*_line, pos, times, selection, nth);
727 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
729 AutomationSelection::iterator p;
730 boost::shared_ptr<AutomationList> alist(line.the_list());
732 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth);
734 if (p == selection.lines.end()) {
738 /* Make a copy of the list because we have to scale the
739 values from view coordinates to model coordinates, and we're
740 not supposed to modify the points in the selection.
743 AutomationList copy (**p);
745 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
746 double foo = (*x)->value;
747 line.view_to_model_y (foo);
751 XMLNode &before = alist->get_state();
752 alist->paste (copy, pos, times);
753 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
759 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
761 if (_line && touched (top, bot)) {
765 /* remember: this is X Window - coordinate space starts in upper left and moves down.
766 y_position is the "origin" or "top" of the track.
769 double mybot = y_position + height;
771 if (y_position >= top && mybot <= bot) {
773 /* y_position is below top, mybot is above bot, so we're fully
782 /* top and bot are within y_position .. mybot */
784 topfrac = 1.0 - ((top - y_position) / height);
785 botfrac = 1.0 - ((bot - y_position) / height);
789 _line->get_selectables (start, end, botfrac, topfrac, results);
794 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
797 _line->get_inverted_selectables (sel, result);
801 AutomationTimeAxisView::set_selected_points (PointSelection& points)
804 _line->set_selected_points (points);
808 AutomationTimeAxisView::clear_lines ()
811 automation_connection.disconnect ();
815 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
819 assert(line->the_list() == _control->list());
821 automation_connection = _control->alist()->automation_state_changed.connect
822 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
825 //_controller = AutomationController::create(_session, line->the_list(), _control);
827 line->set_y_position_and_height (0, height);
829 /* pick up the current state */
830 automation_state_changed ();
836 AutomationTimeAxisView::entered()
839 _line->track_entered();
843 AutomationTimeAxisView::exited ()
846 _line->track_exited();
850 AutomationTimeAxisView::set_colors ()
852 for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
861 AutomationTimeAxisView::color_handler ()
869 AutomationTimeAxisView::set_state (const XMLNode& node)
871 return TimeAxisView::set_state (node);
874 XMLNodeConstIterator iter;
876 kids = node.children ();
878 for (iter = kids.begin(); iter != kids.end(); ++iter) {
880 if ((*iter)->name() == state_node_name) {
881 XMLProperty* type = (*iter)->property("automation-id");
883 if (type && type->value() == _control->parameter().symbol()) {
884 XMLProperty *shown = (*iter)->property("shown_editor");
886 if (shown && shown->value() == "yes") {
887 set_marked_for_display(true);
888 canvas_display->show(); /* FIXME: necessary? show_at? */
895 if (!_marked_for_display)
900 AutomationTimeAxisView::get_state_node ()
902 TimeAxisView* state_parent = get_parent_with_state ();
905 return state_parent->get_automation_child_xml_node (_control->parameter());
912 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
914 XMLNode* xml_node = get_state_node();
916 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
921 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
923 update_extra_xml_shown (true);
925 return TimeAxisView::show_at (y, nth, parent);
929 AutomationTimeAxisView::hide ()
931 update_extra_xml_shown (false);
933 TimeAxisView::hide ();