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 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
194 _control->parameter());
197 set_state (*xml_node);
200 /* ask for notifications of any new RegionViews */
206 /* no regions, just a single line for the entire track (e.g. bus gain) */
208 boost::shared_ptr<AutomationLine> line(new AutomationLine (
209 ARDOUR::EventTypeMap::instance().to_symbol(_control->parameter()),
214 line->set_line_color (ARDOUR_UI::config()->canvasvar_ProcessorAutomationLine.get());
215 line->queue_reset ();
219 /* make sure labels etc. are correct */
221 automation_state_changed ();
222 ColorsChanged.connect (mem_fun (*this, &AutomationTimeAxisView::color_handler));
225 AutomationTimeAxisView::~AutomationTimeAxisView ()
230 AutomationTimeAxisView::auto_clicked ()
232 using namespace Menu_Helpers;
234 if (automation_menu == 0) {
235 automation_menu = manage (new Menu);
236 automation_menu->set_name ("ArdourContextMenu");
237 MenuList& items (automation_menu->items());
239 items.push_back (MenuElem (_("Manual"), bind (mem_fun(*this,
240 &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
241 items.push_back (MenuElem (_("Play"), bind (mem_fun(*this,
242 &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
243 items.push_back (MenuElem (_("Write"), bind (mem_fun(*this,
244 &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
245 items.push_back (MenuElem (_("Touch"), bind (mem_fun(*this,
246 &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
249 automation_menu->popup (1, gtk_get_current_event_time());
253 AutomationTimeAxisView::set_automation_state (AutoState state)
255 if (!ignore_state_request) {
256 _automatable->set_parameter_automation_state (_control->parameter(), state);
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);
268 _view->set_automation_state (state);
273 AutomationTimeAxisView::automation_state_changed ()
277 /* update button label */
282 state = _control->alist()->automation_state ();
285 switch (state & (Off|Play|Touch|Write)) {
287 auto_button.set_label (_("Manual"));
289 ignore_state_request = true;
290 auto_off_item->set_active (true);
291 auto_play_item->set_active (false);
292 auto_touch_item->set_active (false);
293 auto_write_item->set_active (false);
294 ignore_state_request = false;
298 auto_button.set_label (_("Play"));
299 if (auto_play_item) {
300 ignore_state_request = true;
301 auto_play_item->set_active (true);
302 auto_off_item->set_active (false);
303 auto_touch_item->set_active (false);
304 auto_write_item->set_active (false);
305 ignore_state_request = false;
309 auto_button.set_label (_("Write"));
310 if (auto_write_item) {
311 ignore_state_request = true;
312 auto_write_item->set_active (true);
313 auto_off_item->set_active (false);
314 auto_play_item->set_active (false);
315 auto_touch_item->set_active (false);
316 ignore_state_request = false;
320 auto_button.set_label (_("Touch"));
321 if (auto_touch_item) {
322 ignore_state_request = true;
323 auto_touch_item->set_active (true);
324 auto_off_item->set_active (false);
325 auto_play_item->set_active (false);
326 auto_write_item->set_active (false);
327 ignore_state_request = false;
331 auto_button.set_label (_("???"));
337 AutomationTimeAxisView::interpolation_changed ()
339 AutomationList::InterpolationStyle style = _control->list()->interpolation();
341 if (mode_line_item && mode_discrete_item) {
342 if (style == AutomationList::Discrete) {
343 mode_discrete_item->set_active(true);
344 mode_line_item->set_active(false);
346 mode_line_item->set_active(true);
347 mode_discrete_item->set_active(false);
352 _line->set_interpolation(style);
357 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
359 _control->list()->set_interpolation(style);
361 _line->set_interpolation(style);
366 AutomationTimeAxisView::clear_clicked ()
368 _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 = (
380 (height < hNormal && h >= hNormal)
381 || (height >= hNormal || h < hNormal) );
383 TimeAxisView* state_parent = get_parent_with_state ();
384 assert(state_parent);
385 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
387 TimeAxisView::set_height (h);
388 _base_rect->property_y2() = h;
391 _line->set_height(h);
394 _view->set_height(h);
395 _view->update_contents_height();
399 snprintf (buf, sizeof (buf), "%u", height);
401 xml_node->add_property ("height", buf);
404 if (changed_between_small_and_normal || first_call_to_set_height) {
406 first_call_to_set_height = false;
409 controls_table.remove (name_hbox);
412 if (plugname_packed) {
413 controls_table.remove (*plugname);
414 plugname_packed = false;
416 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
417 plugname_packed = true;
418 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
420 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
424 name_hbox.show_all ();
427 hide_button.show_all();
429 } else if (h >= hSmall) {
430 controls_table.remove (name_hbox);
432 if (plugname_packed) {
433 controls_table.remove (*plugname);
434 plugname_packed = false;
437 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
438 controls_table.hide_all ();
441 name_hbox.show_all ();
446 } else if (h >= hNormal){
447 cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
451 /* only emit the signal if the height really changed */
452 _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
457 AutomationTimeAxisView::set_samples_per_unit (double spu)
459 TimeAxisView::set_samples_per_unit (spu);
465 _view->set_samples_per_unit (spu);
469 AutomationTimeAxisView::hide_clicked ()
471 // LAME fix for refreshing the hide button
472 hide_button.set_sensitive(false);
474 set_marked_for_display (false);
477 hide_button.set_sensitive(true);
481 AutomationTimeAxisView::build_display_menu ()
483 using namespace Menu_Helpers;
485 /* get the size menu ready */
491 TimeAxisView::build_display_menu ();
493 /* now fill it with our stuff */
495 MenuList& items = display_menu->items();
497 items.push_back (MenuElem (_("Height"), *size_menu));
498 items.push_back (SeparatorElem());
499 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
500 items.push_back (SeparatorElem());
501 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
502 items.push_back (SeparatorElem());
506 Menu* auto_state_menu = manage (new Menu);
507 auto_state_menu->set_name ("ArdourContextMenu");
508 MenuList& as_items = auto_state_menu->items();
510 as_items.push_back (CheckMenuElem (_("Manual"), bind (
511 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
513 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
515 as_items.push_back (CheckMenuElem (_("Play"), bind (
516 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
518 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
520 as_items.push_back (CheckMenuElem (_("Write"), bind (
521 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
522 (AutoState) Write)));
523 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
525 as_items.push_back (CheckMenuElem (_("Touch"), bind (
526 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
527 (AutoState) Touch)));
528 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
530 items.push_back (MenuElem (_("State"), *auto_state_menu));
534 if ( EventTypeMap::instance().is_midi_parameter(_control->parameter()) ) {
536 Menu* auto_mode_menu = manage (new Menu);
537 auto_mode_menu->set_name ("ArdourContextMenu");
538 MenuList& am_items = auto_mode_menu->items();
540 RadioMenuItem::Group group;
542 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
543 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
544 AutomationList::Discrete)));
545 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
546 mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
548 // For discrete types we dont allow the linear option since it makes no sense for those Controls
549 if (EventTypeMap::instance().interpolation_of(_control->parameter()) == Evoral::ControlList::Linear) {
550 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
551 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
552 AutomationList::Linear)));
553 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
554 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_coord (x, 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 when = (*x)->when;
636 double val = (*x)->value;
637 line.model_to_view_coord (when, val);
647 AutomationTimeAxisView::reset_objects (PointSelection& selection)
649 reset_objects_one (*_line, selection);
653 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
655 boost::shared_ptr<AutomationList> alist(line.the_list());
657 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
659 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
661 if (&(*i).track != this) {
665 alist->reset_range ((*i).start, (*i).end);
670 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
672 return cut_copy_clear_objects_one (*_line, selection, op);
676 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
678 boost::shared_ptr<Evoral::ControlList> what_we_got;
679 boost::shared_ptr<AutomationList> alist(line.the_list());
682 XMLNode &before = alist->get_state();
684 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
686 if (&(*i).track != this) {
692 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
693 _editor.get_cut_buffer().add (what_we_got);
694 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
699 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
700 _editor.get_cut_buffer().add (what_we_got);
705 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
706 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
716 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
717 double when = (*x)->when;
718 double val = (*x)->value;
719 line.model_to_view_coord (when, val);
729 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
731 return paste_one (*_line, pos, times, selection, nth);
735 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
737 AutomationSelection::iterator p;
738 boost::shared_ptr<AutomationList> alist(line.the_list());
740 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth) {}
742 if (p == selection.lines.end()) {
746 /* Make a copy of the list because we have to scale the
747 values from view coordinates to model coordinates, and we're
748 not supposed to modify the points in the selection.
751 AutomationList copy (**p);
753 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
754 double when = (*x)->when;
755 double val = (*x)->value;
756 line.view_to_model_coord (when, val);
761 XMLNode &before = alist->get_state();
762 alist->paste (copy, pos, times);
763 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
769 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
771 if (_line && touched (top, bot)) {
775 /* remember: this is X Window - coordinate space starts in upper left and moves down.
776 _y_position is the "origin" or "top" of the track.
779 double mybot = _y_position + height;
781 if (_y_position >= top && mybot <= bot) {
783 /* _y_position is below top, mybot is above bot, so we're fully
792 /* top and bot are within _y_position .. mybot */
794 topfrac = 1.0 - ((top - _y_position) / height);
795 botfrac = 1.0 - ((bot - _y_position) / height);
799 _line->get_selectables (start, end, botfrac, topfrac, results);
804 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
807 _line->get_inverted_selectables (sel, result);
811 AutomationTimeAxisView::set_selected_points (PointSelection& points)
814 _line->set_selected_points (points);
818 AutomationTimeAxisView::clear_lines ()
821 automation_connection.disconnect ();
825 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
829 assert(line->the_list() == _control->list());
831 automation_connection = _control->alist()->automation_state_changed.connect
832 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
835 //_controller = AutomationController::create(_session, line->the_list(), _control);
837 line->set_height (height);
839 /* pick up the current state */
840 automation_state_changed ();
846 AutomationTimeAxisView::entered()
849 _line->track_entered();
853 AutomationTimeAxisView::exited ()
856 _line->track_exited();
860 AutomationTimeAxisView::color_handler ()
868 AutomationTimeAxisView::set_state (const XMLNode& node)
870 TimeAxisView::set_state (node);
872 XMLProperty const * type = node.property ("automation-id");
873 if (type && type->value () == ARDOUR::EventTypeMap::instance().to_symbol (_control->parameter())) {
874 XMLProperty const * shown = node.property ("shown");
875 if (shown && shown->value () == "yes") {
876 set_marked_for_display (true);
877 _canvas_display->show (); /* FIXME: necessary? show_at? */
881 if (!_marked_for_display) {
889 AutomationTimeAxisView::get_state_node ()
891 TimeAxisView* state_parent = get_parent_with_state ();
894 return state_parent->get_automation_child_xml_node (_control->parameter());
901 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
903 XMLNode* xml_node = get_state_node();
905 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
910 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
912 update_extra_xml_shown (true);
914 return TimeAxisView::show_at (y, nth, parent);
918 AutomationTimeAxisView::hide ()
920 update_extra_xml_shown (false);
922 TimeAxisView::hide ();