+void
+AutomationLine::add_visible_control_point (uint32_t view_index, uint32_t pi, double tx, double ty,
+ AutomationList::iterator model, uint32_t npoints)
+{
+ ControlPoint::ShapeType shape;
+
+ 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);
+ }
+
+ 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 & ControlPoints) {
+ control_points[view_index]->show ();
+ control_points[view_index]->set_visible (true);
+ } else {
+ control_points[view_index]->set_visible (false);
+ }
+}
+
+void
+AutomationLine::connect_to_list ()
+{
+ _list_connections.drop_connections ();
+
+ alist->StateChanged.connect (_list_connections, invalidator (*this), boost::bind (&AutomationLine::list_changed, this), gui_context());
+
+ alist->InterpolationChanged.connect (
+ _list_connections, invalidator (*this), boost::bind (&AutomationLine::interpolation_changed, this, _1), gui_context()
+ );
+}
+
+MementoCommandBinder<AutomationList>*
+AutomationLine::memento_command_binder ()
+{
+ return new SimpleMementoCommandBinder<AutomationList> (*alist.get());
+}
+
+/** Set the maximum time that points on this line can be at, relative
+ * to the start of the track or region that it is on.
+ */
+void
+AutomationLine::set_maximum_time (framecnt_t t)
+{
+ if (_maximum_time == t) {
+ return;
+ }
+
+ _maximum_time = t;
+ reset ();
+}
+
+
+/** @return min and max x positions of points that are in the list, in session frames */
+pair<framepos_t, framepos_t>
+AutomationLine::get_point_x_range () const
+{
+ pair<framepos_t, framepos_t> r (max_framepos, 0);
+
+ for (AutomationList::const_iterator i = the_list()->begin(); i != the_list()->end(); ++i) {
+ r.first = min (r.first, session_position (i));
+ r.second = max (r.second, session_position (i));
+ }
+
+ return r;
+}
+
+framepos_t
+AutomationLine::session_position (AutomationList::const_iterator p) const
+{
+ return _time_converter->to ((*p)->when) + _offset + _time_converter->origin_b ();
+}
+
+void
+AutomationLine::set_offset (framepos_t off)
+{
+ if (_offset == off) {
+ return;
+ }
+
+ _offset = off;
+ reset ();
+}