silence extra buffers not handled/touched/filled by an AU (e.g. 2in/1out - silence...
[ardour2.git] / gtk2_ardour / automation_time_axis.cc
blobeeb7cddb7c8edbf58abd7cf2ed20fb375a54eef7
1 /*
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.
20 #include <ardour/route.h>
21 #include <pbd/memento_command.h>
23 #include "ardour_ui.h"
24 #include "automation_time_axis.h"
25 #include "automation_line.h"
26 #include "public_editor.h"
27 #include "simplerect.h"
28 #include "selection.h"
29 #include "ghostregion.h"
30 #include "rgb_macros.h"
31 #include "automation_selectable.h"
32 #include "point_selection.h"
33 #include "canvas_impl.h"
34 #include "utils.h"
36 #include "i18n.h"
38 using namespace ARDOUR;
39 using namespace PBD;
40 using namespace Gtk;
41 using namespace Editing;
43 Pango::FontDescription* AutomationTimeAxisView::name_font = 0;
44 bool AutomationTimeAxisView::have_name_font = false;
46 AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r, PublicEditor& e, TimeAxisView& rent,
47 ArdourCanvas::Canvas& canvas, const string & nom,
48 const string & state_name, const string & nomparent)
50 : AxisView (s),
51 TimeAxisView (s, e, &rent, canvas),
52 route (r),
53 _name (nom),
54 _state_name (state_name),
55 clear_button (_("clear")),
56 auto_button (X_("")) /* force addition of a label */
58 if (!have_name_font) {
59 name_font = get_font_for_style (X_("AutomationTrackName"));
60 have_name_font = true;
63 automation_menu = 0;
64 in_destructor = false;
65 auto_off_item = 0;
66 auto_touch_item = 0;
67 auto_write_item = 0;
68 auto_play_item = 0;
69 ignore_state_request = false;
70 first_call_to_set_height = true;
72 base_rect = new SimpleRect(*canvas_display);
73 base_rect->property_x1() = 0.0;
74 base_rect->property_y1() = 0.0;
75 base_rect->property_x2() = LONG_MAX - 2;
76 base_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackOutline.get();
77 /* outline ends and bottom */
78 base_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);
79 base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AutomationTrackFill.get();
80 //base_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredControlPoint.get();
82 base_rect->set_data ("trackview", this);
84 base_rect->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_automation_track_event),
85 base_rect, this));
87 hide_button.add (*(manage (new Gtk::Image (::get_icon("hide")))));
89 auto_button.set_name ("TrackVisualButton");
90 clear_button.set_name ("TrackVisualButton");
91 hide_button.set_name ("TrackRemoveButton");
93 auto_button.unset_flags (Gtk::CAN_FOCUS);
94 clear_button.unset_flags (Gtk::CAN_FOCUS);
95 hide_button.unset_flags (Gtk::CAN_FOCUS);
97 controls_table.set_no_show_all();
99 ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
100 ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track"));
101 ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
103 /* rearrange the name display */
105 /* we never show these for automation tracks, so make
106 life easier and remove them.
109 hide_name_entry();
111 /* move the name label over a bit */
113 string shortpname = _name;
114 bool shortened = false;
116 int ignore_width;
117 shortpname = fit_to_pixels (_name, 60, *name_font, ignore_width, true);
119 if (shortpname != _name ){
120 shortened = true;
123 name_label.set_text (shortpname);
124 name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
126 if (nomparent.length()) {
128 /* limit the plug name string */
130 string pname = fit_to_pixels (nomparent, 60, *name_font, ignore_width, true);
131 if (pname != nomparent) {
132 shortened = true;
135 plugname = new Label (pname);
136 plugname->set_name (X_("TrackPlugName"));
137 plugname->show();
138 name_label.set_name (X_("TrackParameterName"));
139 controls_table.remove (name_hbox);
140 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
141 plugname_packed = true;
142 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
143 } else {
144 plugname = 0;
145 plugname_packed = false;
148 if (shortened) {
149 string tipname = nomparent;
150 if (!tipname.empty()) {
151 tipname += ": ";
153 tipname += _name;
154 ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
157 /* add the buttons */
158 controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
160 controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
161 controls_table.attach (clear_button, 5, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
163 controls_table.show_all ();
165 clear_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::clear_clicked));
166 hide_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::hide_clicked));
167 auto_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::auto_clicked));
169 controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
170 controls_base_unselected_name = X_("AutomationTrackControlsBase");
171 controls_ebox.set_name (controls_base_unselected_name);
173 controls_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
175 XMLNode* xml_node = get_parent_with_state()->get_child_xml_node (_state_name);
177 if (xml_node) {
178 set_state (*xml_node);
181 /* make sure labels etc. are correct */
183 automation_state_changed ();
184 ColorsChanged.connect (mem_fun (*this, &AutomationTimeAxisView::color_handler));
187 AutomationTimeAxisView::~AutomationTimeAxisView ()
189 in_destructor = true;
191 for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
192 delete *i;
196 void
197 AutomationTimeAxisView::auto_clicked ()
199 using namespace Menu_Helpers;
201 if (automation_menu == 0) {
202 automation_menu = manage (new Menu);
203 automation_menu->set_name ("ArdourContextMenu");
204 MenuList& items (automation_menu->items());
206 items.push_back (MenuElem (_("Manual"),
207 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
208 items.push_back (MenuElem (_("Play"),
209 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
210 items.push_back (MenuElem (_("Write"),
211 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
212 items.push_back (MenuElem (_("Touch"),
213 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
216 automation_menu->popup (1, gtk_get_current_event_time());
220 void
221 AutomationTimeAxisView::automation_state_changed ()
223 AutoState state;
225 /* update button label */
227 if (lines.empty()) {
228 state = Off;
229 } else {
230 state = lines.front()->the_list().automation_state ();
233 switch (state & (Off|Play|Touch|Write)) {
234 case Off:
235 auto_button.set_label (_("Manual"));
236 if (auto_off_item) {
237 ignore_state_request = true;
238 auto_off_item->set_active (true);
239 auto_play_item->set_active (false);
240 auto_touch_item->set_active (false);
241 auto_write_item->set_active (false);
242 ignore_state_request = false;
244 break;
245 case Play:
246 auto_button.set_label (_("Play"));
247 if (auto_play_item) {
248 ignore_state_request = true;
249 auto_play_item->set_active (true);
250 auto_off_item->set_active (false);
251 auto_touch_item->set_active (false);
252 auto_write_item->set_active (false);
253 ignore_state_request = false;
255 break;
256 case Write:
257 auto_button.set_label (_("Write"));
258 if (auto_write_item) {
259 ignore_state_request = true;
260 auto_write_item->set_active (true);
261 auto_off_item->set_active (false);
262 auto_play_item->set_active (false);
263 auto_touch_item->set_active (false);
264 ignore_state_request = false;
266 break;
267 case Touch:
268 auto_button.set_label (_("Touch"));
269 if (auto_touch_item) {
270 ignore_state_request = true;
271 auto_touch_item->set_active (true);
272 auto_off_item->set_active (false);
273 auto_play_item->set_active (false);
274 auto_write_item->set_active (false);
275 ignore_state_request = false;
277 break;
278 default:
279 auto_button.set_label (_("???"));
280 break;
284 void
285 AutomationTimeAxisView::clear_clicked ()
287 _session.begin_reversible_command (_("clear automation"));
288 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
289 (*i)->clear ();
291 _session.commit_reversible_command ();
294 void
295 AutomationTimeAxisView::set_height (uint32_t h)
297 bool changed = (height != (uint32_t) h);
298 bool changed_between_small_and_normal = ( (height < hNormal && h >= hNormal) || (height >= hNormal || h < hNormal) );
300 TimeAxisView* state_parent = get_parent_with_state ();
301 XMLNode* xml_node = (state_parent ? state_parent->get_child_xml_node (_state_name) : NULL);
303 TimeAxisView::set_height (h);
304 base_rect->property_y2() = h;
306 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
307 (*i)->set_height (h);
310 for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
311 (*i)->set_height ();
314 char buf[32];
315 snprintf (buf, sizeof (buf), "%u", height);
316 if (xml_node) {
317 xml_node->add_property ("height", buf);
320 if (changed_between_small_and_normal || first_call_to_set_height) {
321 first_call_to_set_height = false;
323 if (h >= hNormal) {
324 controls_table.remove (name_hbox);
326 if (plugname) {
327 if (plugname_packed) {
328 controls_table.remove (*plugname);
329 plugname_packed = false;
331 controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
332 plugname_packed = true;
333 controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
334 } else {
335 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
337 hide_name_entry ();
338 show_name_label ();
339 name_hbox.show_all ();
341 auto_button.show();
342 clear_button.show();
343 hide_button.show_all();
345 } else if (h >= hSmall) {
346 controls_table.remove (name_hbox);
347 if (plugname) {
348 if (plugname_packed) {
349 controls_table.remove (*plugname);
350 plugname_packed = false;
353 controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
354 controls_table.hide_all ();
355 hide_name_entry ();
356 show_name_label ();
357 name_hbox.show_all ();
359 auto_button.hide();
360 clear_button.hide();
361 hide_button.hide();
363 } else if (h >= hNormal){
364 cerr << "track grown, but neither changed_between_small_and_normal nor first_call_to_set_height set!" << endl;
367 if (changed) {
368 /* only emit the signal if the height really changed */
369 route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */
373 void
374 AutomationTimeAxisView::set_samples_per_unit (double spu)
376 TimeAxisView::set_samples_per_unit (editor.get_current_zoom());
378 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
379 (*i)->reset ();
383 void
384 AutomationTimeAxisView::hide_clicked ()
386 // LAME fix for refreshing the hide button
387 hide_button.set_sensitive(false);
389 set_marked_for_display (false);
390 hide ();
392 hide_button.set_sensitive(true);
395 void
396 AutomationTimeAxisView::build_display_menu ()
398 using namespace Menu_Helpers;
400 /* get the size menu ready */
402 build_size_menu ();
404 /* prepare it */
406 TimeAxisView::build_display_menu ();
408 /* now fill it with our stuff */
410 MenuList& items = display_menu->items();
412 items.push_back (MenuElem (_("Height"), *size_menu));
413 items.push_back (SeparatorElem());
414 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &AutomationTimeAxisView::hide_clicked)));
415 items.push_back (SeparatorElem());
416 items.push_back (MenuElem (_("Clear"), mem_fun(*this, &AutomationTimeAxisView::clear_clicked)));
417 items.push_back (SeparatorElem());
419 Menu* auto_state_menu = manage (new Menu);
420 auto_state_menu->set_name ("ArdourContextMenu");
421 MenuList& as_items = auto_state_menu->items();
423 as_items.push_back (CheckMenuElem (_("Manual"),
424 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
425 auto_off_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
427 as_items.push_back (CheckMenuElem (_("Play"),
428 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
429 auto_play_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
431 as_items.push_back (CheckMenuElem (_("Write"),
432 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
433 auto_write_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
435 as_items.push_back (CheckMenuElem (_("Touch"),
436 bind (mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
437 auto_touch_item = dynamic_cast<CheckMenuItem*>(&as_items.back());
439 items.push_back (MenuElem (_("State"), *auto_state_menu));
441 /* make sure the automation menu state is correct */
443 automation_state_changed ();
446 bool
447 AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
449 bool ret = false;
451 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
452 ret = cut_copy_clear_one ((**i), selection, op);
455 return ret;
458 bool
459 AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
461 AutomationList* what_we_got = 0;
462 AutomationList& alist (line.the_list());
463 bool ret = false;
465 XMLNode &before = alist.get_state();
467 switch (op) {
468 case Cut:
469 if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
470 editor.get_cut_buffer().add (what_we_got);
471 _session.add_command(new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
472 ret = true;
474 break;
475 case Copy:
476 if ((what_we_got = alist.copy (selection.time.front().start, selection.time.front().end)) != 0) {
477 editor.get_cut_buffer().add (what_we_got);
479 break;
481 case Clear:
482 if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
483 _session.add_command(new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
484 delete what_we_got;
485 what_we_got = 0;
486 ret = true;
488 break;
491 if (what_we_got) {
492 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
493 double foo = (*x)->value;
494 line.model_to_view_y (foo);
495 (*x)->value = foo;
499 return ret;
502 void
503 AutomationTimeAxisView::reset_objects (PointSelection& selection)
505 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
506 reset_objects_one ((**i), selection);
510 void
511 AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
513 AutomationList& alist (line.the_list());
515 _session.add_command (new MementoCommand<AutomationList>(alist, &alist.get_state(), 0));
517 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
519 if (&(*i).track != this) {
520 continue;
523 alist.reset_range ((*i).start, (*i).end);
527 bool
528 AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
530 bool ret = false;
532 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
533 ret = cut_copy_clear_objects_one ((**i), selection, op);
536 return ret;
539 bool
540 AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
542 AutomationList* what_we_got = 0;
543 AutomationList& alist (line.the_list());
544 bool ret = false;
546 XMLNode &before = alist.get_state();
548 for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
550 if (&(*i).track != this) {
551 continue;
554 switch (op) {
555 case Cut:
556 if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
557 editor.get_cut_buffer().add (what_we_got);
558 _session.add_command (new MementoCommand<AutomationList>(alist, new XMLNode (before), &alist.get_state()));
559 ret = true;
561 break;
562 case Copy:
563 if ((what_we_got = alist.copy ((*i).start, (*i).end)) != 0) {
564 editor.get_cut_buffer().add (what_we_got);
566 break;
568 case Clear:
569 if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
570 _session.add_command (new MementoCommand<AutomationList>(alist, new XMLNode (before), &alist.get_state()));
571 delete what_we_got;
572 what_we_got = 0;
573 ret = true;
575 break;
579 delete &before;
581 if (what_we_got) {
582 for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
583 double foo = (*x)->value;
584 line.model_to_view_y (foo);
585 (*x)->value = foo;
589 return ret;
592 bool
593 AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, size_t nth)
595 bool ret = true;
597 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
598 ret = paste_one (**i, pos, times, selection, nth);
601 return ret;
604 bool
605 AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth)
607 AutomationSelection::iterator p;
608 AutomationList& alist (line.the_list());
610 for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth);
612 if (p == selection.lines.end()) {
613 return false;
616 /* Make a copy of the list because we have to scale the
617 values from view coordinates to model coordinates, and we're
618 not supposed to modify the points in the selection.
621 AutomationList copy (**p);
623 for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
624 double foo = (*x)->value;
625 line.view_to_model_y (foo);
626 (*x)->value = foo;
629 XMLNode &before = alist.get_state();
630 alist.paste (copy, pos, times);
631 _session.add_command (new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
633 return true;
636 void
637 AutomationTimeAxisView::add_ghost (GhostRegion* gr)
639 ghosts.push_back (gr);
640 gr->GoingAway.connect (mem_fun(*this, &AutomationTimeAxisView::remove_ghost));
643 void
644 AutomationTimeAxisView::remove_ghost (GhostRegion* gr)
646 if (in_destructor) {
647 return;
650 list<GhostRegion*>::iterator i;
652 for (i = ghosts.begin(); i != ghosts.end(); ++i) {
653 if ((*i) == gr) {
654 ghosts.erase (i);
655 break;
660 void
661 AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
663 if (!lines.empty() && touched (top, bot)) {
664 double topfrac;
665 double botfrac;
667 /* remember: this is X Window - coordinate space starts in upper left and moves down.
668 y_position is the "origin" or "top" of the track.
671 double mybot = y_position + height;
673 if (y_position >= top && mybot <= bot) {
675 /* y_position is below top, mybot is above bot, so we're fully
676 covered vertically.
679 topfrac = 1.0;
680 botfrac = 0.0;
682 } else {
684 /* top and bot are within y_position .. mybot */
686 topfrac = 1.0 - ((top - y_position) / height);
687 botfrac = 1.0 - ((bot - y_position) / height);
690 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
691 (*i)->get_selectables (start, end, botfrac, topfrac, results);
696 void
697 AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
699 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
700 (*i)->get_inverted_selectables (sel, result);
704 void
705 AutomationTimeAxisView::set_selected_points (PointSelection& points)
707 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
708 (*i)->set_selected_points (points);
712 void
713 AutomationTimeAxisView::clear_lines ()
715 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
716 delete *i;
719 lines.clear ();
720 automation_connection.disconnect ();
723 void
724 AutomationTimeAxisView::add_line (AutomationLine& line)
726 bool get = false;
728 if (lines.empty()) {
729 /* first line is the Model for automation state */
730 automation_connection = line.the_list().automation_state_changed.connect
731 (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed));
732 get = true;
735 lines.push_back (&line);
736 line.set_height (height);
738 if (get) {
739 /* pick up the current state */
740 automation_state_changed ();
744 void
745 AutomationTimeAxisView::show_all_control_points ()
747 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
748 (*i)->show_all_control_points ();
752 void
753 AutomationTimeAxisView::hide_all_but_selected_control_points ()
755 for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
756 (*i)->hide_all_but_selected_control_points ();
760 void
761 AutomationTimeAxisView::entered()
763 show_all_control_points ();
766 void
767 AutomationTimeAxisView::exited ()
769 hide_all_but_selected_control_points ();
772 void
773 AutomationTimeAxisView::set_colors () {
775 for( list<GhostRegion *>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) {
776 (*i)->set_colors();
779 for( vector<AutomationLine *>::iterator i=lines.begin(); i != lines.end(); i++ ) {
780 (*i)->set_colors();
785 void
786 AutomationTimeAxisView::color_handler ()
788 set_colors();
794 AutomationTimeAxisView::set_state (const XMLNode& node)
796 return TimeAxisView::set_state (node);
799 XMLNode*
800 AutomationTimeAxisView::get_state_node ()
802 TimeAxisView* state_parent = get_parent_with_state ();
804 if (state_parent) {
805 return state_parent->get_child_xml_node (_state_name);
806 } else {
807 return 0;