+
+void
+AutomationLine::track_entered()
+{
+ if (alist->interpolation() != AutomationList::Discrete) {
+ show_all_control_points();
+ }
+}
+
+void
+AutomationLine::track_exited()
+{
+ if (alist->interpolation() != AutomationList::Discrete) {
+ hide_all_but_selected_control_points();
+ }
+}
+
+XMLNode &
+AutomationLine::get_state (void)
+{
+ /* function as a proxy for the model */
+ return alist->get_state();
+}
+
+int
+AutomationLine::set_state (const XMLNode &node, int version)
+{
+ /* function as a proxy for the model */
+ return alist->set_state (node, version);
+}
+
+void
+AutomationLine::view_to_model_coord (double& x, double& y) const
+{
+ /* TODO: This should be more generic ... */
+ if (alist->parameter().type() == GainAutomation ||
+ alist->parameter().type() == EnvelopeAutomation) {
+ y = slider_position_to_gain (y);
+ y = max (0.0, y);
+ y = min (2.0, y);
+ } else if (alist->parameter().type() == PanAutomation) {
+ // vertical coordinate axis reversal
+ y = 1.0 - y;
+ } else if (alist->parameter().type() == PluginAutomation) {
+ y = y * (double)(alist->get_max_y()- alist->get_min_y()) + alist->get_min_y();
+ } else {
+ y = (int)(y * alist->parameter().max());
+ }
+
+ x = _time_converter.from(x);
+}
+
+void
+AutomationLine::model_to_view_coord (double& x, double& y) const
+{
+ /* TODO: This should be more generic ... */
+ if (alist->parameter().type() == GainAutomation ||
+ alist->parameter().type() == EnvelopeAutomation) {
+ y = gain_to_slider_position (y);
+ } else if (alist->parameter().type() == PanAutomation) {
+ // vertical coordinate axis reversal
+ y = 1.0 - y;
+ } else if (alist->parameter().type() == PluginAutomation) {
+ y = (y - alist->get_min_y()) / (double)(alist->get_max_y()- alist->get_min_y());
+ } else {
+ y = y / (double)alist->parameter().max(); /* ... like this */
+ }
+
+ x = _time_converter.to(x);
+}
+
+
+void
+AutomationLine::set_interpolation(AutomationList::InterpolationStyle style)
+{
+ _interpolation = style;
+
+ if (style == AutomationList::Discrete) {
+ show_all_control_points();
+ line->hide();
+ } else {
+ hide_all_but_selected_control_points();
+ line->show();
+ }
+}
+
+void
+AutomationLine::add_visible_control_point (uint32_t view_index, uint32_t pi, double tx, double ty, AutomationList::iterator model, uint32_t npoints)
+{
+ if (view_index >= control_points.size()) {
+
+ /* make sure we have enough control points */
+
+ ControlPoint* ncp = new ControlPoint (*this);
+ ncp->set_size (control_point_box_size ());
+
+ control_points.push_back (ncp);
+ }
+
+ ControlPoint::ShapeType shape;
+
+ if (!terminal_points_can_slide) {
+ if (pi == 0) {
+ control_points[view_index]->set_can_slide(false);
+ if (tx == 0) {
+ shape = ControlPoint::Start;
+ } else {
+ shape = ControlPoint::Full;
+ }
+ } else if (pi == npoints - 1) {
+ control_points[view_index]->set_can_slide(false);
+ shape = ControlPoint::End;
+ } else {
+ control_points[view_index]->set_can_slide(true);
+ shape = ControlPoint::Full;
+ }
+ } else {
+ control_points[view_index]->set_can_slide(true);
+ shape = ControlPoint::Full;
+ }
+
+ control_points[view_index]->reset (tx, ty, model, view_index, shape);
+
+ /* finally, control visibility */
+
+ if (_visible && points_visible) {
+ control_points[view_index]->show ();
+ control_points[view_index]->set_visible (true);
+ } else {
+ if (!points_visible) {
+ control_points[view_index]->set_visible (false);
+ }
+ }
+}
+
+void
+AutomationLine::add_always_in_view (double x)
+{
+ _always_in_view.push_back (x);
+ alist->apply_to_points (*this, &AutomationLine::reset_callback);
+}
+
+void
+AutomationLine::clear_always_in_view ()
+{
+ _always_in_view.clear ();
+ alist->apply_to_points (*this, &AutomationLine::reset_callback);
+}
+