Fixes in get_cursor_limits() and other methods.

This commit is contained in:
Kolan Sh 2017-11-28 21:51:58 +03:00
parent b465034bc3
commit 22761fa04f
4 changed files with 162 additions and 97 deletions

View File

@ -101,7 +101,7 @@ namespace Gtk.CairoChart {
public virtual void zoom_in (double x0, double y0, double x1, double y1) {
for (var si = 0, max_i = series.length; si < max_i; ++si) {
var s = series[si];
if (!s.show) continue;
if (!s.zoom_show) continue;
var real_x0 = get_real_x (s, x0);
var real_x1 = get_real_x (s, x1);
var real_y0 = get_real_y (s, y0);
@ -109,7 +109,7 @@ namespace Gtk.CairoChart {
// if selected square does not intersect with the series's square
if ( real_x1 <= s.axis_x.zoom_min || real_x0 >= s.axis_x.zoom_max
|| real_y0 <= s.axis_y.zoom_min || real_y1 >= s.axis_y.zoom_max) {
s.show = false;
s.zoom_show = false;
continue;
}
if (real_x0 >= s.axis_x.zoom_min) {
@ -140,7 +140,7 @@ namespace Gtk.CairoChart {
zoom_first_show = 0;
for (var si = 0, max_i = series.length; si < max_i; ++si)
if (series[si].show) {
if (series[si].zoom_show) {
zoom_first_show = si;
break;
}
@ -157,7 +157,7 @@ namespace Gtk.CairoChart {
public virtual void zoom_out () {
foreach (var s in series) {
s.show = true;
s.zoom_show = true;
s.axis_x.zoom_min = s.axis_x.min;
s.axis_x.zoom_max = s.axis_x.max;
s.axis_y.zoom_min = s.axis_y.min;
@ -359,7 +359,7 @@ namespace Gtk.CairoChart {
foreach (var s in series) {
if (!s.show) continue;
if (!s.zoom_show) continue;
// carry
switch (legend.position) {
@ -558,7 +558,7 @@ namespace Gtk.CairoChart {
int nzoom_series_show = 0;
for (var si = series.length - 1; si >=0; --si) {
var s = series[si];
if (!s.show) continue;
if (!s.zoom_show) continue;
++nzoom_series_show;
if ( s.axis_x.position != series[0].axis_x.position
|| s.axis_x.zoom_min != series[0].axis_x.zoom_min
@ -579,7 +579,7 @@ namespace Gtk.CairoChart {
// Join and calc X-axes
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
var s = series[si];
if (!s.show) continue;
if (!s.zoom_show) continue;
if (nskip != 0) {--nskip; continue;}
double max_rec_width = 0; double max_rec_height = 0;
calc_axis_rec_sizes (s.axis_x, out max_rec_width, out max_rec_height, true);
@ -589,11 +589,11 @@ namespace Gtk.CairoChart {
// join relative x-axes with non-intersect places
for (int sj = si - 1; sj >= 0; --sj) {
var s2 = series[sj];
if (!s2.show) continue;
if (!s2.zoom_show) continue;
bool has_intersection = false;
for (int sk = si; sk > sj; --sk) {
var s3 = series[sk];
if (!s3.show) continue;
if (!s3.zoom_show) continue;
if (are_intersect(s2.place.zoom_x_low, s2.place.zoom_x_high, s3.place.zoom_x_low, s3.place.zoom_x_high)
|| s2.axis_x.position != s3.axis_x.position
|| s2.axis_x.type != s3.axis_x.type) {
@ -627,7 +627,7 @@ namespace Gtk.CairoChart {
// Join and calc Y-axes
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
var s = series[si];
if (!s.show) continue;
if (!s.zoom_show) continue;
if (nskip != 0) {--nskip; continue;}
double max_rec_width = 0; double max_rec_height = 0;
calc_axis_rec_sizes (s.axis_y, out max_rec_width, out max_rec_height, false);
@ -637,11 +637,11 @@ namespace Gtk.CairoChart {
// join relative x-axes with non-intersect places
for (int sj = si - 1; sj >= 0; --sj) {
var s2 = series[sj];
if (!s2.show) continue;
if (!s2.zoom_show) continue;
bool has_intersection = false;
for (int sk = si; sk > sj; --sk) {
var s3 = series[sk];
if (!s3.show) continue;
if (!s3.zoom_show) continue;
if (are_intersect(s2.place.zoom_y_low, s2.place.zoom_y_high, s3.place.zoom_y_low, s3.place.zoom_y_high)
|| s2.axis_y.position != s3.axis_y.position
|| s2.axis_x.type != s3.axis_x.type) {
@ -682,7 +682,7 @@ namespace Gtk.CairoChart {
protected virtual void draw_horizontal_axis () {
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
var s = series[si];
if (!s.show) continue;
if (!s.zoom_show) continue;
if (common_x_axes && si != zoom_first_show) continue;
// 1. Detect max record width/height by axis_rec_npoints equally selected points using format.
double max_rec_width, max_rec_height;
@ -833,11 +833,11 @@ namespace Gtk.CairoChart {
// join relative x-axes with non-intersect places
for (int sj = si - 1; sj >= 0; --sj) {
var s2 = series[sj];
if (!s2.show) continue;
if (!s2.zoom_show) continue;
bool has_intersection = false;
for (int sk = si; sk > sj; --sk) {
var s3 = series[sk];
if (!s3.show) continue;
if (!s3.zoom_show) continue;
if (are_intersect(s2.place.zoom_x_low, s2.place.zoom_x_high, s3.place.zoom_x_low, s3.place.zoom_x_high)
|| s2.axis_x.position != s3.axis_x.position
|| s2.axis_x.type != s3.axis_x.type) {
@ -873,7 +873,7 @@ namespace Gtk.CairoChart {
protected virtual void draw_vertical_axis () {
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
var s = series[si];
if (!s.show) continue;
if (!s.zoom_show) continue;
if (common_y_axes && si != zoom_first_show) continue;
// 1. Detect max record width/height by axis_rec_npoints equally selected points using format.
double max_rec_width, max_rec_height;
@ -976,11 +976,11 @@ namespace Gtk.CairoChart {
// join relative x-axes with non-intersect places
for (int sj = si - 1; sj >= 0; --sj) {
var s2 = series[sj];
if (!s2.show) continue;
if (!s2.zoom_show) continue;
bool has_intersection = false;
for (int sk = si; sk > sj; --sk) {
var s3 = series[sk];
if (!s3.show) continue;
if (!s3.zoom_show) continue;
if (are_intersect(s2.place.zoom_y_low, s2.place.zoom_y_high, s3.place.zoom_y_low, s3.place.zoom_y_high)
|| s2.axis_y.position != s3.axis_y.position) {
has_intersection = true;
@ -1047,9 +1047,32 @@ namespace Gtk.CairoChart {
return Point (get_real_x(s, p.x), get_real_y(s, p.y));
}
protected virtual bool x_in_range (double x, double x0, double x1) {
if (x0 <= x <= x1 || x1 <= x <= x0)
return true;
return false;
}
protected virtual bool y_in_range (double y, double y0, double y1) {
if (y0 <= y <= y1 || y1 <= y <= y0)
return true;
return false;
}
protected virtual bool x_in_plot_area (double x) {
if (x_in_range(x, plot_area_x_min, plot_area_x_max))
return true;
return false;
}
protected virtual bool y_in_plot_area (double y) {
if (y_in_range(y, plot_area_y_min, plot_area_y_max))
return true;
return false;
}
protected virtual bool point_in_rect (Point p, double x0, double x1, double y0, double y1) {
if ( (x0 <= p.x <= x1 || x1 <= p.x <= x0)
&& (y0 <= p.y <= y1 || y1 <= p.y <= y0))
if (x_in_range(p.x, x0, x1) && y_in_range(p.y, y0, y1))
return true;
return false;
}
@ -1130,9 +1153,9 @@ namespace Gtk.CairoChart {
return false;
}
protected virtual Point[] sort_points (Series s) {
protected virtual Point[] sort_points (Series s, Series.Sort sort) {
var points = s.points.copy();
switch(s.sort) {
switch(sort) {
case Series.Sort.BY_X:
sort_points_delegate(points, (a, b) => {
if (a.x < b.x) return -1;
@ -1154,9 +1177,9 @@ namespace Gtk.CairoChart {
protected virtual void draw_series () {
for (var si = 0; si < series.length; ++si) {
var s = series[si];
if (!s.show) continue;
if (!s.zoom_show) continue;
if (s.points.length == 0) continue;
var points = sort_points(s);
var points = sort_points(s, s.sort);
set_line_style(s.line_style);
// draw series line
for (int i = 1; i < points.length; ++i) {
@ -1184,7 +1207,7 @@ namespace Gtk.CairoChart {
public virtual void set_active_cursor (double x, double y, bool remove = false) {
active_cursor = Point (scr2rel_x(x), scr2rel_y(y));
is_cursor_active = true;
is_cursor_active = ! remove;
}
public virtual void add_active_cursor () {
@ -1199,7 +1222,7 @@ namespace Gtk.CairoChart {
public CursorOrientation cursors_orientation = CursorOrientation.VERTICAL;
public double cursor_max_distance = 32;
public double cursor_max_rm_distance = 32;
public virtual void remove_active_cursor () {
if (cursors.length() == 0) return;
@ -1210,47 +1233,81 @@ namespace Gtk.CairoChart {
double d = distance;
switch (cursors_orientation) {
case CursorOrientation.VERTICAL:
d = (c.x - active_cursor.x).abs();
d = (rel2scr_x(c.x) - rel2scr_x(active_cursor.x)).abs();
break;
case CursorOrientation.HORIZONTAL:
d = (c.y - active_cursor.y).abs();
d = (rel2scr_y(c.y) - rel2scr_y(active_cursor.y)).abs();
break;
default:
break;
}
if (distance > d) {
if (d < distance) {
distance = d;
rm_indx = i;
}
++i;
}
if (distance < cursor_max_distance)
if (distance < cursor_max_rm_distance)
cursors.delete_link(cursors.nth(rm_indx));
is_cursor_active = false;
}
// TODO:
protected virtual Float128 scr2rel_x (Float128 x) {
return _rel_zoom_x_min + (x - plot_area_x_min) / (plot_area_x_max - plot_area_x_min) * (_rel_zoom_x_max - _rel_zoom_x_min);
}
protected virtual Float128 scr2rel_y (Float128 y) {
return _rel_zoom_y_max - (plot_area_y_max - y) / (plot_area_y_max - plot_area_y_min) * (_rel_zoom_y_max - _rel_zoom_y_min);
}
protected virtual Point scr2rel_point (Point p) {
return Point (scr2rel_x(p.x), scr2rel_y(p.y));
}
protected virtual Float128 rel2scr_x(Float128 x) {
return plot_area_x_min + (plot_area_x_max - plot_area_x_min) * (x - _rel_zoom_x_min) / (_rel_zoom_x_max - _rel_zoom_x_min);
}
protected virtual Float128 rel2scr_y(Float128 y) {
return plot_area_y_min + (plot_area_y_max - plot_area_y_min) * (y - _rel_zoom_y_min) / (_rel_zoom_y_max - _rel_zoom_y_min);
}
protected virtual Point rel2scr_point (Point p) {
return Point (rel2scr_x(p.x), rel2scr_y(p.y));
}
public LineStyle cursor_line_style = LineStyle(Color(0.2, 0.2, 0.2, 0.8));
protected virtual bool get_cursor_limits (Series s, Point cursor, out Point low, out Point high) {
var points = sort_points (s);
bool ret = false;
low.x = plot_area_x_min;
low.y = plot_area_y_min;
high.x = plot_area_x_max;
high.y = plot_area_y_max;
low.x = plot_area_x_max;
low.y = plot_area_y_max;
high.x = plot_area_x_min;
high.y = plot_area_y_min;
Point[] points = {};
switch (cursors_orientation) {
case CursorOrientation.VERTICAL:
points = sort_points (s, s.sort);
break;
case CursorOrientation.HORIZONTAL:
points = sort_points (s, s.sort);
break;
}
for (var i = 0; i + 1 < points.length; ++i) {
switch (cursors_orientation) {
case CursorOrientation.VERTICAL:
Float128 y = 0.0;
if (vcross(get_scr_point(s, s.points[i]), get_scr_point(s, s.points[i+1]), cursor.x, plot_area_y_min, plot_area_y_max, out y)) {
if (y < low.y) low.y = y;
if (y > high.y) high.y = y;
if (vcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]), rel2scr_x(cursor.x),
plot_area_y_min, plot_area_y_max, out y)) {
if (y < low.y /*&& y_in_plot_area(y)*/) low.y = y;
if (y > high.y /*&& y_in_plot_area(y)*/) high.y = y;
ret = true;
}
break;
case CursorOrientation.HORIZONTAL:
Float128 x = 0.0;
if (hcross(get_scr_point(s, s.points[i]), get_scr_point(s, s.points[i+1]), cursor.y, plot_area_x_min, plot_area_x_max, out x)) {
if (x < low.x) low.x = x;
if (x > high.x) high.x = x;
if (hcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]),
plot_area_x_min, plot_area_x_max, rel2scr_y(cursor.y), out x)) {
if (x < low.x /*&& x_in_plot_area(x)*/) low.x = x;
if (x > high.x /*&& x_in_plot_area(x)*/) high.x = x;
ret = true;
}
break;
@ -1259,13 +1316,14 @@ namespace Gtk.CairoChart {
if (common_x_axes) {
switch (s.axis_x.position) {
case Axis.Position.LOW: low.y = plot_area_y_max + s.axis_x.font_indent; break;
case Axis.Position.HIGH: high.y = plot_area_y_min - s.axis_x.font_indent; break;
case Axis.Position.LOW: high.y = plot_area_y_max + s.axis_x.font_indent; break;
case Axis.Position.HIGH: low.y = plot_area_y_min - s.axis_x.font_indent; break;
case Axis.Position.BOTH:
low.y = plot_area_y_max + s.axis_x.font_indent;
high.y = plot_area_y_min - s.axis_x.font_indent;
high.y = plot_area_y_max + s.axis_x.font_indent;
low.y = plot_area_y_min - s.axis_x.font_indent;
break;
}
ret = true;
}
if (common_y_axes) {
switch (s.axis_y.position) {
@ -1276,53 +1334,31 @@ namespace Gtk.CairoChart {
high.x = plot_area_x_max + s.axis_y.font_indent;
break;
}
ret = true;
}
return false;
return ret;
}
protected virtual Float128 scr2rel_x (Float128 x) {
return (x - plot_area_x_min) / (plot_area_x_max - plot_area_x_min);
}
protected virtual Float128 scr2rel_y (Float128 y) {
return (y - plot_area_y_min) / (plot_area_y_max - plot_area_y_min);
}
protected virtual Point scr2rel_point (Point p) {
return Point (scr2rel_x(p.x), scr2rel_y(p.y));
}
protected virtual Float128 rel2scr_x(Float128 x) {
return plot_area_x_min + (plot_area_x_max - plot_area_x_min) * x;
}
protected virtual Float128 rel2scr_y(Float128 y) {
return plot_area_y_max - (plot_area_y_max - plot_area_y_min) * y;
}
protected virtual Point rel2scr_point (Point p) {
return Point (rel2scr_x(p.x), rel2scr_y(p.y));
}
public LineStyle cursor_line_style = LineStyle();
// TODO:
protected virtual void draw_cursors () {
if (series.length == 0) return;
var all_cursors = cursors.copy();
all_cursors.append(active_cursor);
var all_cursors = cursors.copy_deep ((src) => { return src; });
if (is_cursor_active)
all_cursors.append(active_cursor);
foreach (var c in all_cursors) {
switch (cursors_orientation) {
case CursorOrientation.VERTICAL:
if (c.x <= rel_zoom_x_min || c.x >= rel_zoom_x_max) continue; break;
if (c.x <= _rel_zoom_x_min || c.x >= _rel_zoom_x_max) continue; break;
case CursorOrientation.HORIZONTAL:
if (c.y <= rel_zoom_y_min || c.y >= rel_zoom_y_max) continue; break;
if (c.y <= _rel_zoom_y_min || c.y >= _rel_zoom_y_max) continue; break;
}
var low = Point(plot_area_x_max, plot_area_y_min); // low and high
var high = Point(plot_area_x_min, plot_area_y_max); // points of the cursor
var low = Point(plot_area_x_max, plot_area_y_max); // low and high
var high = Point(plot_area_x_min, plot_area_y_min); // points of the cursor
foreach (var s in series) {
if (!s.zoom_show) continue;
var l = Point(), h = Point();
if (get_cursor_limits (s, c, out l, out h)) {
if (l.x < low.x) low.x = l.x;
@ -1334,7 +1370,7 @@ namespace Gtk.CairoChart {
switch (cursors_orientation) {
case CursorOrientation.VERTICAL:
// TODO: draw cursor line
if (low.y > high.y) continue;
set_line_style(cursor_line_style);
context.move_to (rel2scr_x(c.x), low.y);
context.line_to (rel2scr_x(c.x), high.y);
@ -1342,14 +1378,14 @@ namespace Gtk.CairoChart {
// TODO: show values
if (common_x_axes)
// TODO: show only Y value
// show only Y value
;
else
// TODO: show [X;Y]
// show [X;Y]
;
break;
case CursorOrientation.HORIZONTAL:
// TODO: draw cursor line
if (low.x > high.x) continue;
set_line_style(cursor_line_style);
context.move_to (low.x, rel2scr_y(c.y));
context.line_to (high.x, rel2scr_y(c.y));
@ -1357,10 +1393,10 @@ namespace Gtk.CairoChart {
// TODO: show values
if (common_y_axes)
// TODO: show only X value
// show only X value
;
else
// TODO: show [X;Y]
// show [X;Y]
;
break;
}
@ -1369,6 +1405,7 @@ namespace Gtk.CairoChart {
public Chart copy () {
var chart = new Chart ();
chart.active_cursor = this.active_cursor;
chart.axis_rec_npoints = this.axis_rec_npoints;
chart.bg_color = this.bg_color;
chart.border_color = this.border_color;
@ -1379,7 +1416,12 @@ namespace Gtk.CairoChart {
chart.cur_x_min = this.cur_x_min;
chart.cur_y_max = this.cur_y_max;
chart.cur_y_min = this.cur_y_min;
chart.cursor_line_style = this.cursor_line_style;
chart.cursor_max_rm_distance = this.cursor_max_rm_distance;
chart.cursors = this.cursors.copy();
chart.cursors_orientation = this.cursors_orientation;
chart.height = this.height;
chart.is_cursor_active = this.is_cursor_active;
chart.legend = this.legend.copy();
chart.legend_height = this.legend_height;
chart.legend_line_length = this.legend_line_length;
@ -1397,12 +1439,16 @@ namespace Gtk.CairoChart {
chart._rel_zoom_y_min = this._rel_zoom_y_min;
chart._rel_zoom_y_max = this._rel_zoom_y_max;
chart.selection_style = this.selection_style;
chart.series = this.series.copy();
chart.show_legend = this.show_legend;
chart.title = this.title.copy().copy();
chart.title_height = this.title_height;
chart.title_vindent = this.title_vindent;
chart.title_width = this.title_width;
chart.width = this.width;
chart.x_min = this.x_min;
chart.y_min = this.y_min;
chart.zoom_first_show = this.zoom_first_show;
return chart;
}
}

View File

@ -7,11 +7,12 @@ namespace Gtk.CairoChart {
double dash_offset;
Color color;
public LineStyle (double width = 1,
Cairo.LineJoin line_join = Cairo.LineJoin.MITER,
Cairo.LineCap line_cap = Cairo.LineCap.ROUND,
public LineStyle (Color color = Color(),
double width = 1,
double[]? dashes = null, double dash_offset = 0,
Color color = Color()) {
Cairo.LineJoin line_join = Cairo.LineJoin.MITER,
Cairo.LineCap line_cap = Cairo.LineCap.ROUND
) {
this.width = width;
this.line_join = line_join;
this.line_cap = line_cap;

View File

@ -49,7 +49,7 @@ namespace Gtk.CairoChart {
default = Color (0.0, 0.0, 0.0, 1.0);
}
public bool show = true;
public bool zoom_show = true;
public Series copy () {
var series = new Series ();
@ -63,7 +63,7 @@ namespace Gtk.CairoChart {
series.points = this.points.copy();
series.sort = this.sort;
series.title = this.title.copy();
series.show = this.show;
series.zoom_show = this.zoom_show;
return series;
}

View File

@ -251,6 +251,8 @@ int main (string[] args) {
var radio_button2 = new RadioButton.with_label (radio_button1.get_group(), "Right Legend");
var radio_button3 = new RadioButton.with_label_from_widget (radio_button1, "Left Legend");
var radio_button4 = new RadioButton.with_label_from_widget (radio_button1, "Bottom Legend");
var radio_button7 = new RadioButton.with_label (null, "Vertical Cursors");
var radio_button8 = new RadioButton.with_label_from_widget (radio_button7, "Horizontal Cursors");
button1.clicked.connect (() => {
chart = chart1; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
@ -261,6 +263,10 @@ int main (string[] args) {
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
default: break;
}
switch (chart.cursors_orientation) {
case Chart.CursorOrientation.VERTICAL: radio_button7.set_active(true); break;
case Chart.CursorOrientation.HORIZONTAL: radio_button8.set_active(true); break;
}
});
button2.clicked.connect (() => {
chart = chart2; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
@ -271,6 +277,10 @@ int main (string[] args) {
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
default: break;
}
switch (chart.cursors_orientation) {
case Chart.CursorOrientation.VERTICAL: radio_button7.set_active(true); break;
case Chart.CursorOrientation.HORIZONTAL: radio_button8.set_active(true); break;
}
});
button3.clicked.connect (() => {
chart = chart3; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
@ -281,6 +291,10 @@ int main (string[] args) {
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
default: break;
}
switch (chart.cursors_orientation) {
case Chart.CursorOrientation.VERTICAL: radio_button7.set_active(true); break;
case Chart.CursorOrientation.HORIZONTAL: radio_button8.set_active(true); break;
}
});
button4.clicked.connect (() => {
chart = chart4; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
@ -291,6 +305,10 @@ int main (string[] args) {
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
default: break;
}
switch (chart.cursors_orientation) {
case Chart.CursorOrientation.VERTICAL: radio_button7.set_active(true); break;
case Chart.CursorOrientation.HORIZONTAL: radio_button8.set_active(true); break;
}
});
button5.clicked.connect (() => {
for (var i = 0; i < chart.series.length; ++i) {
@ -369,8 +387,6 @@ int main (string[] args) {
}
});*/
var radio_button7 = new RadioButton.with_label (null, "Vertical Cursors");
var radio_button8 = new RadioButton.with_label_from_widget (radio_button7, "Horizontal Cursors");
radio_button7.toggled.connect ((button) => {
if (button.get_active()) {
chart.cursors_orientation = Chart.CursorOrientation.VERTICAL;
@ -423,11 +439,13 @@ int main (string[] args) {
case 1: // start cursor position selection
if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { // remove cursor
chart.set_active_cursor (event.x, event.y, true);
chart.remove_active_cursor();
mouse_state = MouseState.FREE;
} else { // add cursor
chart.set_active_cursor (event.x, event.y);
mouse_state = MouseState.CURSOR_SELECTION;
}
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
mouse_state = MouseState.CURSOR_SELECTION;
break;
case 2: // start zoom area selection
@ -454,9 +472,9 @@ int main (string[] args) {
switch (event.button) {
case 1: // start cursor position selection
if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { // remove cursor
chart.remove_active_cursor ();
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
mouse_state = MouseState.FREE;
//chart.remove_active_cursor ();
//da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
//mouse_state = MouseState.FREE;
} else { // add cursor
chart.add_active_cursor ();
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
@ -502,7 +520,7 @@ int main (string[] args) {
break;
case MouseState.CURSOR_SELECTION:
chart.set_active_cursor (event.x, event.y, true);
chart.set_active_cursor (event.x, event.y);
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
break;
}