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"
44 using namespace ARDOUR;
47 using namespace Gtkmm2ext;
48 using namespace Editing;
50 Pango::FontDescription* AutomationTimeAxisView::name_font = 0;
51 bool AutomationTimeAxisView::have_name_font = false;
52 const string AutomationTimeAxisView::state_node_name = "AutomationChild";
55 /** \a a the automatable object this time axis is to display data for.
56 * For route/track automation (e.g. gain) pass the route for both \r and \a.
57 * For route child (e.g. plugin) automation, pass the child for \a.
58 * For region automation (e.g. MIDI CC), pass null for \a.
60 AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r,
61 boost::shared_ptr<Automatable> a, boost::shared_ptr<AutomationControl> c,
62 PublicEditor& e, TimeAxisView& parent, bool show_regions,
63 ArdourCanvas::Canvas& canvas, const string & nom, const string & nomparent)
65 TimeAxisView (s, e, &parent, canvas),
69 _controller(AutomationController::create(a, c->parameter(), c)),
71 _view (show_regions ? new AutomationStreamView(*this) : NULL),
73 auto_button (X_("")) /* force addition of a label */
75 if (!have_name_font) {
76 name_font = get_font_for_style (X_("AutomationTrackName"));
77 have_name_font = true;
85 mode_discrete_item = 0;
88 ignore_state_request = false;
89 first_call_to_set_height = true;
91 _base_rect = new SimpleRect(*_canvas_display);
92 _base_rect->property_x1() = 0.0;
93 _base_rect->property_y1() = 0.0;
94 _base_rect->property_x2() = LONG_MAX - 2;
95 _base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackOutline.get();
97 /* outline ends and bottom */
98 _base_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);
99 _base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackFill.get();
101 _base_rect->set_data ("trackview", this);
103 _base_rect->signal_event().connect (bind (
104 mem_fun (_editor, &PublicEditor::canvas_automation_track_event),
107 _base_rect->lower_to_bottom();
109 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
111 auto_button.set_name ("TrackVisualButton");
112 hide_button.set_name ("TrackRemoveButton");
114 auto_button.unset_flags (Gtk::CAN_FOCUS);
115 hide_button.unset_flags (Gtk::CAN_FOCUS);
117 controls_table.set_no_show_all();
119 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
120 ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
122 /* rearrange the name display */
124 /* we never show these for automation tracks, so make
125 life easier and remove them.
130 /* move the name label over a bit */
132 string shortpname = _name;
133 bool shortened = false;
136 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
138 if (shortpname != _name ){
142 name_label.set_text (shortpname);
143 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
145 if (nomparent.length()) {
147 /* limit the plug name string */
149 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
150 if (pname != nomparent) {
154 plugname = new Label (pname);
155 plugname->set_name (X_("TrackPlugName"));
157 name_label.set_name (X_("TrackParameterName"));
158 controls_table.remove (name_hbox);
159 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
160 plugname_packed = true;
161 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
164 plugname_packed = false;
168 string tipname = nomparent;
169 if (!tipname.empty()) {
173 ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
176 /* add the buttons */
177 controls_table.attach (hide_button, 0, 1, 0, 1, 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);
181 /* add bar controller */
182 controls_table.attach (*_controller.get(), 0, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
184 controls_table.show_all ();
186 hide_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
187 auto_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::auto_clicked));
189 controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
190 controls_base_unselected_name = X_("AutomationTrackControlsBase");
191 controls_ebox.set_name (controls_base_unselected_name);
193 controls_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
195 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
196 _control->parameter());
199 set_state (*xml_node);
202 /* ask for notifications of any new RegionViews */
208 /* no regions, just a single line for the entire track (e.g. bus gain) */
210 boost::shared_ptr<AutomationLine> line(new AutomationLine (
211 ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter()),
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"), bind (mem_fun(*this,
242 &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
243 items.push_back (MenuElem (_("Play"), bind (mem_fun(*this,
244 &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
245 items.push_back (MenuElem (_("Write"), bind (mem_fun(*this,
246 &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
247 items.push_back (MenuElem (_("Touch"), bind (mem_fun(*this,
248 &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) { // This is a time axis for route (not region) automation
259 _route->set_parameter_automation_state (_control->parameter(), state);
262 if (_control->list())
263 _control->alist()->set_automation_state(state);
266 _view->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);
354 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
356 _control->list()->set_interpolation(style);
358 _line->set_interpolation(style);
363 AutomationTimeAxisView::clear_clicked ()
365 _session.begin_reversible_command (_("clear automation"));
369 _session.commit_reversible_command ();
373 AutomationTimeAxisView::set_height (uint32_t h)
375 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
376 bool changed_between_small_and_normal = (
377 (height < hNormal && h >= hNormal)
378 || (height >= hNormal || h < hNormal) );
380 TimeAxisView* state_parent = get_parent_with_state ();
381 assert(state_parent);
382 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
384 TimeAxisView::set_height (h);
385 _base_rect->property_y2() = h;
388 _line->set_height(h);
391 _view->set_height(h);
392 _view->update_contents_height();
396 snprintf (buf, sizeof (buf), "%u", height);
398 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 hide_button.show_all();
426 } else if (h >= hSmall) {
427 controls_table.remove (name_hbox);
429 if (plugname_packed) {
430 controls_table.remove (*plugname);
431 plugname_packed = false;
434 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
435 controls_table.hide_all ();
438 name_hbox.show_all ();
443 } else if (h >= hNormal){
444 cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
448 /* only emit the signal if the height really changed */
449 _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
454 AutomationTimeAxisView::set_samples_per_unit (double spu)
456 TimeAxisView::set_samples_per_unit (spu);
462 _view->set_samples_per_unit (spu);
466 AutomationTimeAxisView::hide_clicked ()
468 // LAME fix for refreshing the hide button
469 hide_button.set_sensitive(false);
471 set_marked_for_display (false);
474 hide_button.set_sensitive(true);
478 AutomationTimeAxisView::build_display_menu ()
480 using namespace Menu_Helpers;
482 /* get the size menu ready */
488 TimeAxisView::build_display_menu ();
490 /* now fill it with our stuff */
492 MenuList& items = display_menu->items();
494 items.push_back (MenuElem (_("Height"), *size_menu));
495 items.push_back (SeparatorElem());
496 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
497 items.push_back (SeparatorElem());
498 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
499 items.push_back (SeparatorElem());
503 Menu* auto_state_menu = manage (new Menu);
504 auto_state_menu->set_name ("ArdourContextMenu");
505 MenuList& as_items = auto_state_menu->items();
507 as_items.push_back (CheckMenuElem (_("Manual"), bind (
508 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
510 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
512 as_items.push_back (CheckMenuElem (_("Play"), bind (
513 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
515 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
517 as_items.push_back (CheckMenuElem (_("Write"), bind (
518 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
519 (AutoState) Write)));
520 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
522 as_items.push_back (CheckMenuElem (_("Touch"), bind (
523 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
524 (AutoState) Touch)));
525 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
527 items.push_back (MenuElem (_("State"), *auto_state_menu));
531 if ( EventTypeMap::instance().is_midi_parameter(_control->parameter()) ) {
533 Menu* auto_mode_menu = manage (new Menu);
534 auto_mode_menu->set_name ("ArdourContextMenu");
535 MenuList& am_items = auto_mode_menu->items();
537 RadioMenuItem::Group group;
539 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
540 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
541 AutomationList::Discrete)));
542 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
543 mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
545 // For discrete types we dont allow the linear option since it makes no sense for those Controls
546 if (EventTypeMap::instance().interpolation_of(_control->parameter()) == Evoral::ControlList::Linear) {
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);
554 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
557 /* make sure the automation menu state is correct */
559 automation_state_changed ();
560 interpolation_changed ();
564 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent* event, nframes_t when, double y)
571 _canvas_display->w2i (x, y);
573 /* compute vertical fractional position */
575 y = 1.0 - (y / height);
579 _line->view_to_model_coord (x, y);
581 _session.begin_reversible_command (_("add automation event"));
582 XMLNode& before = _control->alist()->get_state();
584 _control->alist()->add (when, y);
586 XMLNode& after = _control->alist()->get_state();
587 _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->alist(), &before, &after));
589 _session.set_dirty ();
594 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
596 return (_line ? cut_copy_clear_one (*_line, selection, op) : false);
600 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
602 boost::shared_ptr<Evoral::ControlList> what_we_got;
603 boost::shared_ptr<AutomationList> alist (line.the_list());
606 XMLNode &before = alist->get_state();
610 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
611 _editor.get_cut_buffer().add (what_we_got);
612 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
617 if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) {
618 _editor.get_cut_buffer().add (what_we_got);
623 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
624 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
631 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
632 double when = (*x)->when;
633 double val = (*x)->value;
634 line.model_to_view_coord (when, val);
644 AutomationTimeAxisView::reset_objects (PointSelection& selection)
646 reset_objects_one (*_line, selection);
650 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
652 boost::shared_ptr<AutomationList> alist(line.the_list());
654 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
656 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
658 if (&(*i).track != this) {
662 alist->reset_range ((*i).start, (*i).end);
667 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
669 return cut_copy_clear_objects_one (*_line, selection, op);
673 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
675 boost::shared_ptr<Evoral::ControlList> what_we_got;
676 boost::shared_ptr<AutomationList> alist(line.the_list());
679 XMLNode &before = alist->get_state();
681 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
683 if (&(*i).track != this) {
689 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
690 _editor.get_cut_buffer().add (what_we_got);
691 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
696 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
697 _editor.get_cut_buffer().add (what_we_got);
702 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
703 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
713 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
714 double when = (*x)->when;
715 double val = (*x)->value;
716 line.model_to_view_coord (when, val);
726 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
728 return paste_one (*_line, pos, times, selection, nth);
732 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
734 AutomationSelection::iterator p;
735 boost::shared_ptr<AutomationList> alist(line.the_list());
737 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth) {}
739 if (p == selection.lines.end()) {
743 /* Make a copy of the list because we have to scale the
744 values from view coordinates to model coordinates, and we're
745 not supposed to modify the points in the selection.
748 AutomationList copy (**p);
750 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
751 double when = (*x)->when;
752 double val = (*x)->value;
753 line.view_to_model_coord (when, val);
758 XMLNode &before = alist->get_state();
759 alist->paste (copy, pos, times);
760 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
766 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
768 if (_line && touched (top, bot)) {
772 /* remember: this is X Window - coordinate space starts in upper left and moves down.
773 _y_position is the "origin" or "top" of the track.
776 double mybot = _y_position + height;
778 if (_y_position >= top && mybot <= bot) {
780 /* _y_position is below top, mybot is above bot, so we're fully
789 /* top and bot are within _y_position .. mybot */
791 topfrac = 1.0 - ((top - _y_position) / height);
792 botfrac = 1.0 - ((bot - _y_position) / height);
796 _line->get_selectables (start, end, botfrac, topfrac, results);
801 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
804 _line->get_inverted_selectables (sel, result);
808 AutomationTimeAxisView::set_selected_points (PointSelection& points)
811 _line->set_selected_points (points);
815 AutomationTimeAxisView::clear_lines ()
818 automation_connection.disconnect ();
822 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
826 assert(line->the_list() == _control->list());
828 automation_connection = _control->alist()->automation_state_changed.connect
829 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
832 //_controller = AutomationController::create(_session, line->the_list(), _control);
834 line->set_height (height);
836 /* pick up the current state */
837 automation_state_changed ();
843 AutomationTimeAxisView::entered()
846 _line->track_entered();
850 AutomationTimeAxisView::exited ()
853 _line->track_exited();
857 AutomationTimeAxisView::color_handler ()
865 AutomationTimeAxisView::set_state (const XMLNode& node)
867 TimeAxisView::set_state (node);
869 XMLProperty const * type = node.property ("automation-id");
870 if (type && type->value () == ARDOUR::EventTypeMap::instance().to_symbol (_control->parameter())) {
871 XMLProperty const * shown = node.property ("shown");
872 if (shown && shown->value () == "yes") {
873 set_marked_for_display (true);
874 _canvas_display->show (); /* FIXME: necessary? show_at? */
878 if (!_marked_for_display) {
886 AutomationTimeAxisView::get_state_node ()
888 TimeAxisView* state_parent = get_parent_with_state ();
891 return state_parent->get_automation_child_xml_node (_control->parameter());
898 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
900 XMLNode* xml_node = get_state_node();
902 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
907 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
909 update_extra_xml_shown (true);
911 return TimeAxisView::show_at (y, nth, parent);
915 AutomationTimeAxisView::hide ()
917 update_extra_xml_shown (false);
919 TimeAxisView::hide ();