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 <gtkmm2ext/barcontroller.h>
22 #include "pbd/memento_command.h"
23 #include "ardour/automation_control.h"
24 #include "ardour/event_type_map.h"
25 #include "ardour/route.h"
27 #include "ardour_ui.h"
28 #include "automation_time_axis.h"
29 #include "automation_streamview.h"
30 #include "route_time_axis.h"
31 #include "automation_line.h"
32 #include "public_editor.h"
33 #include "simplerect.h"
34 #include "selection.h"
35 #include "rgb_macros.h"
36 #include "automation_selectable.h"
37 #include "point_selection.h"
38 #include "canvas_impl.h"
43 using namespace ARDOUR;
46 using namespace Gtkmm2ext;
47 using namespace Editing;
49 Pango::FontDescription* AutomationTimeAxisView::name_font = 0;
50 bool AutomationTimeAxisView::have_name_font = false;
51 const string AutomationTimeAxisView::state_node_name = "AutomationChild";
54 /** \a a the automatable object this time axis is to display data for.
55 * For route/track automation (e.g. gain) pass the route for both \r and \a.
56 * For route child (e.g. plugin) automation, pass the child for \a.
57 * For region automation (e.g. MIDI CC), pass null for \a.
59 AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r,
60 boost::shared_ptr<Automatable> a, boost::shared_ptr<AutomationControl> c,
61 PublicEditor& e, TimeAxisView& parent, bool show_regions,
62 ArdourCanvas::Canvas& canvas, const string & nom, const string & nomparent)
64 TimeAxisView (s, e, &parent, canvas),
68 _controller(AutomationController::create(a, c->parameter(), c)),
70 _view (show_regions ? new AutomationStreamView(*this) : NULL),
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() = LONG_MAX - 2;
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 (
103 mem_fun (_editor, &PublicEditor::canvas_automation_track_event),
106 _base_rect->lower_to_bottom();
108 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
110 auto_button.set_name ("TrackVisualButton");
111 hide_button.set_name ("TrackRemoveButton");
113 auto_button.unset_flags (Gtk::CAN_FOCUS);
114 hide_button.unset_flags (Gtk::CAN_FOCUS);
116 controls_table.set_no_show_all();
118 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
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);
178 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
180 /* add bar controller */
181 controls_table.attach (*_controller.get(), 0, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
183 controls_table.show_all ();
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) */
209 boost::shared_ptr<AutomationLine> line(new AutomationLine (
210 ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter()),
215 line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
216 line->queue_reset ();
220 /* make sure labels etc. are correct */
222 automation_state_changed ();
223 ColorsChanged.connect (mem_fun (*this, &AutomationTimeAxisView::color_handler));
226 AutomationTimeAxisView::~AutomationTimeAxisView ()
231 AutomationTimeAxisView::auto_clicked ()
233 using namespace Menu_Helpers;
235 if (automation_menu == 0) {
236 automation_menu = manage (new Menu);
237 automation_menu->set_name ("ArdourContextMenu");
238 MenuList& items (automation_menu->items());
240 items.push_back (MenuElem (_("Manual"), bind (mem_fun(*this,
241 &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
242 items.push_back (MenuElem (_("Play"), bind (mem_fun(*this,
243 &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
244 items.push_back (MenuElem (_("Write"), bind (mem_fun(*this,
245 &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
246 items.push_back (MenuElem (_("Touch"), bind (mem_fun(*this,
247 &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
250 automation_menu->popup (1, gtk_get_current_event_time());
254 AutomationTimeAxisView::set_automation_state (AutoState state)
256 if (!ignore_state_request) {
257 if (_route == _automatable) { // This is a time axis for route (not region) automation
258 _route->set_parameter_automation_state (_control->parameter(), state);
261 if (_control->list())
262 _control->alist()->set_automation_state(state);
265 _view->set_automation_state (state);
269 AutomationTimeAxisView::automation_state_changed ()
273 /* update button label */
278 state = _control->alist()->automation_state ();
281 switch (state & (Off|Play|Touch|Write)) {
283 auto_button.set_label (_("Manual"));
285 ignore_state_request = true;
286 auto_off_item->set_active (true);
287 auto_play_item->set_active (false);
288 auto_touch_item->set_active (false);
289 auto_write_item->set_active (false);
290 ignore_state_request = false;
294 auto_button.set_label (_("Play"));
295 if (auto_play_item) {
296 ignore_state_request = true;
297 auto_play_item->set_active (true);
298 auto_off_item->set_active (false);
299 auto_touch_item->set_active (false);
300 auto_write_item->set_active (false);
301 ignore_state_request = false;
305 auto_button.set_label (_("Write"));
306 if (auto_write_item) {
307 ignore_state_request = true;
308 auto_write_item->set_active (true);
309 auto_off_item->set_active (false);
310 auto_play_item->set_active (false);
311 auto_touch_item->set_active (false);
312 ignore_state_request = false;
316 auto_button.set_label (_("Touch"));
317 if (auto_touch_item) {
318 ignore_state_request = true;
319 auto_touch_item->set_active (true);
320 auto_off_item->set_active (false);
321 auto_play_item->set_active (false);
322 auto_write_item->set_active (false);
323 ignore_state_request = false;
327 auto_button.set_label (_("???"));
333 AutomationTimeAxisView::interpolation_changed ()
335 AutomationList::InterpolationStyle style = _control->list()->interpolation();
337 if (mode_line_item && mode_discrete_item) {
338 if (style == AutomationList::Discrete) {
339 mode_discrete_item->set_active(true);
340 mode_line_item->set_active(false);
342 mode_line_item->set_active(true);
343 mode_discrete_item->set_active(false);
348 _line->set_interpolation(style);
353 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
355 _control->list()->set_interpolation(style);
357 _line->set_interpolation(style);
362 AutomationTimeAxisView::clear_clicked ()
364 _session.begin_reversible_command (_("clear automation"));
368 _session.commit_reversible_command ();
372 AutomationTimeAxisView::set_height (uint32_t h)
374 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
375 bool changed_between_small_and_normal = (
376 (height < hNormal && h >= hNormal)
377 || (height >= hNormal || h < hNormal) );
379 TimeAxisView* state_parent = get_parent_with_state ();
380 assert(state_parent);
381 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
383 TimeAxisView::set_height (h);
384 _base_rect->property_y2() = h;
387 _line->set_height(h);
390 _view->set_height(h);
391 _view->update_contents_height();
395 snprintf (buf, sizeof (buf), "%u", height);
397 xml_node->add_property ("height", buf);
400 if (changed_between_small_and_normal || first_call_to_set_height) {
402 first_call_to_set_height = false;
405 controls_table.remove (name_hbox);
408 if (plugname_packed) {
409 controls_table.remove (*plugname);
410 plugname_packed = false;
412 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
413 plugname_packed = true;
414 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
416 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
420 name_hbox.show_all ();
423 hide_button.show_all();
425 } else if (h >= hSmall) {
426 controls_table.remove (name_hbox);
428 if (plugname_packed) {
429 controls_table.remove (*plugname);
430 plugname_packed = false;
433 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
434 controls_table.hide_all ();
437 name_hbox.show_all ();
442 } else if (h >= hNormal){
443 cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
447 /* only emit the signal if the height really changed */
448 _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
453 AutomationTimeAxisView::set_samples_per_unit (double spu)
455 TimeAxisView::set_samples_per_unit (spu);
461 _view->set_samples_per_unit (spu);
465 AutomationTimeAxisView::hide_clicked ()
467 // LAME fix for refreshing the hide button
468 hide_button.set_sensitive(false);
470 set_marked_for_display (false);
473 hide_button.set_sensitive(true);
477 AutomationTimeAxisView::build_display_menu ()
479 using namespace Menu_Helpers;
481 /* get the size menu ready */
487 TimeAxisView::build_display_menu ();
489 /* now fill it with our stuff */
491 MenuList& items = display_menu->items();
493 items.push_back (MenuElem (_("Height"), *size_menu));
494 items.push_back (SeparatorElem());
495 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
496 items.push_back (SeparatorElem());
497 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
498 items.push_back (SeparatorElem());
502 Menu* auto_state_menu = manage (new Menu);
503 auto_state_menu->set_name ("ArdourContextMenu");
504 MenuList& as_items = auto_state_menu->items();
506 as_items.push_back (CheckMenuElem (_("Manual"), bind (
507 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
509 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
511 as_items.push_back (CheckMenuElem (_("Play"), bind (
512 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
514 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
516 as_items.push_back (CheckMenuElem (_("Write"), bind (
517 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
518 (AutoState) Write)));
519 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
521 as_items.push_back (CheckMenuElem (_("Touch"), bind (
522 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
523 (AutoState) Touch)));
524 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
526 items.push_back (MenuElem (_("State"), *auto_state_menu));
530 if ( EventTypeMap::instance().is_midi_parameter(_control->parameter()) ) {
532 Menu* auto_mode_menu = manage (new Menu);
533 auto_mode_menu->set_name ("ArdourContextMenu");
534 MenuList& am_items = auto_mode_menu->items();
536 RadioMenuItem::Group group;
538 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
539 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
540 AutomationList::Discrete)));
541 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
542 mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
544 // For discrete types we dont allow the linear option since it makes no sense for those Controls
545 if (EventTypeMap::instance().interpolation_of(_control->parameter()) == Evoral::ControlList::Linear) {
546 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
547 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
548 AutomationList::Linear)));
549 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
550 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_coord (x, 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 when = (*x)->when;
632 double val = (*x)->value;
633 line.model_to_view_coord (when, val);
643 AutomationTimeAxisView::reset_objects (PointSelection& selection)
645 reset_objects_one (*_line, selection);
649 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
651 boost::shared_ptr<AutomationList> alist(line.the_list());
653 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
655 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
657 if (&(*i).track != this) {
661 alist->reset_range ((*i).start, (*i).end);
666 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
668 return cut_copy_clear_objects_one (*_line, selection, op);
672 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
674 boost::shared_ptr<Evoral::ControlList> what_we_got;
675 boost::shared_ptr<AutomationList> alist(line.the_list());
678 XMLNode &before = alist->get_state();
680 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
682 if (&(*i).track != this) {
688 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
689 _editor.get_cut_buffer().add (what_we_got);
690 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
695 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
696 _editor.get_cut_buffer().add (what_we_got);
701 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
702 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
712 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
713 double when = (*x)->when;
714 double val = (*x)->value;
715 line.model_to_view_coord (when, val);
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 when = (*x)->when;
751 double val = (*x)->value;
752 line.view_to_model_coord (when, val);
757 XMLNode &before = alist->get_state();
758 alist->paste (copy, pos, times);
759 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
765 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
767 if (_line && touched (top, bot)) {
771 /* remember: this is X Window - coordinate space starts in upper left and moves down.
772 _y_position is the "origin" or "top" of the track.
775 double mybot = _y_position + height;
777 if (_y_position >= top && mybot <= bot) {
779 /* _y_position is below top, mybot is above bot, so we're fully
788 /* top and bot are within _y_position .. mybot */
790 topfrac = 1.0 - ((top - _y_position) / height);
791 botfrac = 1.0 - ((bot - _y_position) / height);
795 _line->get_selectables (start, end, botfrac, topfrac, results);
800 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
803 _line->get_inverted_selectables (sel, result);
807 AutomationTimeAxisView::set_selected_points (PointSelection& points)
810 _line->set_selected_points (points);
814 AutomationTimeAxisView::clear_lines ()
817 automation_connection.disconnect ();
821 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
825 assert(line->the_list() == _control->list());
827 automation_connection = _control->alist()->automation_state_changed.connect
828 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
831 //_controller = AutomationController::create(_session, line->the_list(), _control);
833 line->set_height (height);
835 /* pick up the current state */
836 automation_state_changed ();
842 AutomationTimeAxisView::entered()
845 _line->track_entered();
849 AutomationTimeAxisView::exited ()
852 _line->track_exited();
856 AutomationTimeAxisView::color_handler ()
864 AutomationTimeAxisView::set_state (const XMLNode& node)
866 TimeAxisView::set_state (node);
868 XMLProperty const * type = node.property ("automation-id");
869 if (type && type->value () == ARDOUR::EventTypeMap::instance().to_symbol (_control->parameter())) {
870 XMLProperty const * shown = node.property ("shown");
871 if (shown && shown->value () == "yes") {
872 set_marked_for_display (true);
873 _canvas_display->show (); /* FIXME: necessary? show_at? */
877 if (!_marked_for_display) {
885 AutomationTimeAxisView::get_state_node ()
887 TimeAxisView* state_parent = get_parent_with_state ();
890 return state_parent->get_automation_child_xml_node (_control->parameter());
897 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
899 XMLNode* xml_node = get_state_node();
901 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
906 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
908 update_extra_xml_shown (true);
910 return TimeAxisView::show_at (y, nth, parent);
914 AutomationTimeAxisView::hide ()
916 update_extra_xml_shown (false);
918 TimeAxisView::hide ();