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),
108 _base_rect->lower_to_bottom();
111 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
113 auto_button.set_name ("TrackVisualButton");
114 hide_button.set_name ("TrackRemoveButton");
116 auto_button.unset_flags (Gtk::CAN_FOCUS);
117 hide_button.unset_flags (Gtk::CAN_FOCUS);
119 controls_table.set_no_show_all();
121 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
122 ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
124 /* rearrange the name display */
126 /* we never show these for automation tracks, so make
127 life easier and remove them.
132 /* move the name label over a bit */
134 string shortpname = _name;
135 bool shortened = false;
138 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
140 if (shortpname != _name ){
144 name_label.set_text (shortpname);
145 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
147 if (nomparent.length()) {
149 /* limit the plug name string */
151 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
152 if (pname != nomparent) {
156 plugname = new Label (pname);
157 plugname->set_name (X_("TrackPlugName"));
159 name_label.set_name (X_("TrackParameterName"));
160 controls_table.remove (name_hbox);
161 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
162 plugname_packed = true;
163 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
166 plugname_packed = false;
170 string tipname = nomparent;
171 if (!tipname.empty()) {
175 ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
178 /* add the buttons */
179 controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
181 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
183 /* add bar controller */
184 controls_table.attach (*_controller.get(), 0, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
186 controls_table.show_all ();
188 hide_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
189 auto_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::auto_clicked));
191 controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
192 controls_base_unselected_name = X_("AutomationTrackControlsBase");
193 controls_ebox.set_name (controls_base_unselected_name);
195 XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (
196 _control->parameter());
199 set_state (*xml_node, Stateful::loading_state_version);
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) {
259 _automatable->set_parameter_automation_state (_control->parameter(), state);
262 if (_route == _automatable) { // This is a time axis for route (not region) automation
263 _route->set_parameter_automation_state (_control->parameter(), state);
266 if (_control->list())
267 _control->alist()->set_automation_state(state);
272 _view->set_automation_state (state);
277 AutomationTimeAxisView::automation_state_changed ()
281 /* update button label */
286 state = _control->alist()->automation_state ();
289 switch (state & (Off|Play|Touch|Write)) {
291 auto_button.set_label (_("Manual"));
293 ignore_state_request = true;
294 auto_off_item->set_active (true);
295 auto_play_item->set_active (false);
296 auto_touch_item->set_active (false);
297 auto_write_item->set_active (false);
298 ignore_state_request = false;
302 auto_button.set_label (_("Play"));
303 if (auto_play_item) {
304 ignore_state_request = true;
305 auto_play_item->set_active (true);
306 auto_off_item->set_active (false);
307 auto_touch_item->set_active (false);
308 auto_write_item->set_active (false);
309 ignore_state_request = false;
313 auto_button.set_label (_("Write"));
314 if (auto_write_item) {
315 ignore_state_request = true;
316 auto_write_item->set_active (true);
317 auto_off_item->set_active (false);
318 auto_play_item->set_active (false);
319 auto_touch_item->set_active (false);
320 ignore_state_request = false;
324 auto_button.set_label (_("Touch"));
325 if (auto_touch_item) {
326 ignore_state_request = true;
327 auto_touch_item->set_active (true);
328 auto_off_item->set_active (false);
329 auto_play_item->set_active (false);
330 auto_write_item->set_active (false);
331 ignore_state_request = false;
335 auto_button.set_label (_("???"));
341 AutomationTimeAxisView::interpolation_changed ()
343 AutomationList::InterpolationStyle style = _control->list()->interpolation();
345 if (mode_line_item && mode_discrete_item) {
346 if (style == AutomationList::Discrete) {
347 mode_discrete_item->set_active(true);
348 mode_line_item->set_active(false);
350 mode_line_item->set_active(true);
351 mode_discrete_item->set_active(false);
356 _line->set_interpolation(style);
361 AutomationTimeAxisView::set_interpolation (AutomationList::InterpolationStyle style)
363 _control->list()->set_interpolation(style);
365 _line->set_interpolation(style);
370 AutomationTimeAxisView::clear_clicked ()
372 _session.begin_reversible_command (_("clear automation"));
376 _session.commit_reversible_command ();
380 AutomationTimeAxisView::set_height (uint32_t h)
382 bool changed = (height != (uint32_t) h) || first_call_to_set_height;
383 bool changed_between_small_and_normal = (
384 (height < hNormal && h >= hNormal)
385 || (height >= hNormal || h < hNormal) );
387 TimeAxisView* state_parent = get_parent_with_state ();
388 assert(state_parent);
389 XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter());
391 TimeAxisView::set_height (h);
392 _base_rect->property_y2() = h;
395 _line->set_height(h);
398 _view->set_height(h);
399 _view->update_contents_height();
403 snprintf (buf, sizeof (buf), "%u", height);
405 xml_node->add_property ("height", buf);
408 if (changed_between_small_and_normal || first_call_to_set_height) {
410 first_call_to_set_height = false;
413 controls_table.remove (name_hbox);
416 if (plugname_packed) {
417 controls_table.remove (*plugname);
418 plugname_packed = false;
420 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
421 plugname_packed = true;
422 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
424 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
428 name_hbox.show_all ();
431 hide_button.show_all();
433 } else if (h >= hSmall) {
434 controls_table.remove (name_hbox);
436 if (plugname_packed) {
437 controls_table.remove (*plugname);
438 plugname_packed = false;
441 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
442 controls_table.hide_all ();
445 name_hbox.show_all ();
450 } else if (h >= hNormal){
451 cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
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"), bind (
515 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
517 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
519 as_items.push_back (CheckMenuElem (_("Play"), bind (
520 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
522 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
524 as_items.push_back (CheckMenuElem (_("Write"), bind (
525 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
526 (AutoState) Write)));
527 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
529 as_items.push_back (CheckMenuElem (_("Touch"), bind (
530 mem_fun(*this, &AutomationTimeAxisView::set_automation_state),
531 (AutoState) Touch)));
532 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
534 items.push_back (MenuElem (_("State"), *auto_state_menu));
538 if ( EventTypeMap::instance().is_midi_parameter(_control->parameter()) ) {
540 Menu* auto_mode_menu = manage (new Menu);
541 auto_mode_menu->set_name ("ArdourContextMenu");
542 MenuList& am_items = auto_mode_menu->items();
544 RadioMenuItem::Group group;
546 am_items.push_back (RadioMenuElem (group, _("Discrete"), bind (
547 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
548 AutomationList::Discrete)));
549 mode_discrete_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
550 mode_discrete_item->set_active(_control->list()->interpolation() == AutomationList::Discrete);
552 // For discrete types we dont allow the linear option since it makes no sense for those Controls
553 if (EventTypeMap::instance().interpolation_of(_control->parameter()) == Evoral::ControlList::Linear) {
554 am_items.push_back (RadioMenuElem (group, _("Line"), bind (
555 mem_fun(*this, &AutomationTimeAxisView::set_interpolation),
556 AutomationList::Linear)));
557 mode_line_item = dynamic_cast<CheckMenuItem*>(&am_items.back());
558 mode_line_item->set_active(_control->list()->interpolation() == AutomationList::Linear);
561 items.push_back (MenuElem (_("Mode"), *auto_mode_menu));
564 /* make sure the automation menu state is correct */
566 automation_state_changed ();
567 interpolation_changed ();
571 AutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* /*item*/, GdkEvent* /*event*/, nframes_t when, double y)
578 _canvas_display->w2i (x, y);
580 /* compute vertical fractional position */
582 y = 1.0 - (y / height);
586 _line->view_to_model_coord (x, y);
588 _session.begin_reversible_command (_("add automation event"));
589 XMLNode& before = _control->alist()->get_state();
591 _control->alist()->add (when, y);
593 XMLNode& after = _control->alist()->get_state();
594 _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(*_control->alist(), &before, &after));
596 _session.set_dirty ();
600 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
602 return (_line ? cut_copy_clear_one (*_line, selection, op) : false);
606 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
608 boost::shared_ptr<Evoral::ControlList> what_we_got;
609 boost::shared_ptr<AutomationList> alist (line.the_list());
612 XMLNode &before = alist->get_state();
616 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
617 _editor.get_cut_buffer().add (what_we_got);
618 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
623 if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) {
624 _editor.get_cut_buffer().add (what_we_got);
629 if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) {
630 _session.add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
637 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
638 double when = (*x)->when;
639 double val = (*x)->value;
640 line.model_to_view_coord (when, val);
650 AutomationTimeAxisView::reset_objects (PointSelection& selection)
652 reset_objects_one (*_line, selection);
656 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
658 boost::shared_ptr<AutomationList> alist(line.the_list());
660 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &alist->get_state(), 0));
662 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
664 if (&(*i).track != this) {
668 alist->reset_range ((*i).start, (*i).end);
673 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
675 return cut_copy_clear_objects_one (*_line, selection, op);
679 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
681 boost::shared_ptr<Evoral::ControlList> what_we_got;
682 boost::shared_ptr<AutomationList> alist(line.the_list());
685 XMLNode &before = alist->get_state();
687 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
689 if (&(*i).track != this) {
695 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
696 _editor.get_cut_buffer().add (what_we_got);
697 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
702 if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) {
703 _editor.get_cut_buffer().add (what_we_got);
708 if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) {
709 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), new XMLNode (before), &alist->get_state()));
719 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
720 double when = (*x)->when;
721 double val = (*x)->value;
722 line.model_to_view_coord (when, val);
732 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
734 return paste_one (*_line, pos, times, selection, nth);
738 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
740 AutomationSelection::iterator p;
741 boost::shared_ptr<AutomationList> alist(line.the_list());
743 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth) {}
745 if (p == selection.lines.end()) {
749 /* Make a copy of the list because we have to scale the
750 values from view coordinates to model coordinates, and we're
751 not supposed to modify the points in the selection.
754 AutomationList copy (**p);
756 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
757 double when = (*x)->when;
758 double val = (*x)->value;
759 line.view_to_model_coord (when, val);
764 XMLNode &before = alist->get_state();
765 alist->paste (copy, pos, times);
766 _session.add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
772 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
774 if (_line && touched (top, bot)) {
778 /* remember: this is X Window - coordinate space starts in upper left and moves down.
779 _y_position is the "origin" or "top" of the track.
782 double mybot = _y_position + height;
784 if (_y_position >= top && mybot <= bot) {
786 /* _y_position is below top, mybot is above bot, so we're fully
795 /* top and bot are within _y_position .. mybot */
797 topfrac = 1.0 - ((top - _y_position) / height);
798 botfrac = 1.0 - ((bot - _y_position) / height);
802 _line->get_selectables (start, end, botfrac, topfrac, results);
807 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
810 _line->get_inverted_selectables (sel, result);
814 AutomationTimeAxisView::set_selected_points (PointSelection& points)
817 _line->set_selected_points (points);
821 AutomationTimeAxisView::clear_lines ()
824 automation_connection.disconnect ();
828 AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
832 assert(line->the_list() == _control->list());
834 automation_connection = _control->alist()->automation_state_changed.connect
835 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
838 //_controller = AutomationController::create(_session, line->the_list(), _control);
840 line->set_height (height);
842 /* pick up the current state */
843 automation_state_changed ();
849 AutomationTimeAxisView::entered()
852 _line->track_entered();
856 AutomationTimeAxisView::exited ()
859 _line->track_exited();
863 AutomationTimeAxisView::color_handler ()
871 AutomationTimeAxisView::set_state (const XMLNode& node, int version)
873 TimeAxisView::set_state (node, version);
875 XMLProperty const * type = node.property ("automation-id");
876 if (type && type->value () == ARDOUR::EventTypeMap::instance().to_symbol (_control->parameter())) {
877 XMLProperty const * shown = node.property ("shown");
878 if (shown && shown->value () == "yes") {
879 set_marked_for_display (true);
880 _canvas_display->show (); /* FIXME: necessary? show_at? */
884 if (!_marked_for_display) {
892 AutomationTimeAxisView::get_state_node ()
894 TimeAxisView* state_parent = get_parent_with_state ();
897 return state_parent->get_automation_child_xml_node (_control->parameter());
904 AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
906 XMLNode* xml_node = get_state_node();
908 xml_node->add_property ("shown", editor_shown ? "yes" : "no");
913 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
915 update_extra_xml_shown (true);
917 return TimeAxisView::show_at (y, nth, parent);
921 AutomationTimeAxisView::hide ()
923 update_extra_xml_shown (false);
925 TimeAxisView::hide ();