Fixes in get_cursor_limits() and other methods.
This commit is contained in:
parent
b465034bc3
commit
22761fa04f
214
src/Chart.vala
214
src/Chart.vala
|
@ -101,7 +101,7 @@ namespace Gtk.CairoChart {
|
||||||
public virtual void zoom_in (double x0, double y0, double x1, double y1) {
|
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) {
|
for (var si = 0, max_i = series.length; si < max_i; ++si) {
|
||||||
var s = series[si];
|
var s = series[si];
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
var real_x0 = get_real_x (s, x0);
|
var real_x0 = get_real_x (s, x0);
|
||||||
var real_x1 = get_real_x (s, x1);
|
var real_x1 = get_real_x (s, x1);
|
||||||
var real_y0 = get_real_y (s, y0);
|
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 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
|
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) {
|
|| real_y0 <= s.axis_y.zoom_min || real_y1 >= s.axis_y.zoom_max) {
|
||||||
s.show = false;
|
s.zoom_show = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (real_x0 >= s.axis_x.zoom_min) {
|
if (real_x0 >= s.axis_x.zoom_min) {
|
||||||
|
@ -140,7 +140,7 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
zoom_first_show = 0;
|
zoom_first_show = 0;
|
||||||
for (var si = 0, max_i = series.length; si < max_i; ++si)
|
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;
|
zoom_first_show = si;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
public virtual void zoom_out () {
|
public virtual void zoom_out () {
|
||||||
foreach (var s in series) {
|
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_min = s.axis_x.min;
|
||||||
s.axis_x.zoom_max = s.axis_x.max;
|
s.axis_x.zoom_max = s.axis_x.max;
|
||||||
s.axis_y.zoom_min = s.axis_y.min;
|
s.axis_y.zoom_min = s.axis_y.min;
|
||||||
|
@ -359,7 +359,7 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
foreach (var s in series) {
|
foreach (var s in series) {
|
||||||
|
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
|
|
||||||
// carry
|
// carry
|
||||||
switch (legend.position) {
|
switch (legend.position) {
|
||||||
|
@ -558,7 +558,7 @@ namespace Gtk.CairoChart {
|
||||||
int nzoom_series_show = 0;
|
int nzoom_series_show = 0;
|
||||||
for (var si = series.length - 1; si >=0; --si) {
|
for (var si = series.length - 1; si >=0; --si) {
|
||||||
var s = series[si];
|
var s = series[si];
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
++nzoom_series_show;
|
++nzoom_series_show;
|
||||||
if ( s.axis_x.position != series[0].axis_x.position
|
if ( s.axis_x.position != series[0].axis_x.position
|
||||||
|| s.axis_x.zoom_min != series[0].axis_x.zoom_min
|
|| s.axis_x.zoom_min != series[0].axis_x.zoom_min
|
||||||
|
@ -579,7 +579,7 @@ namespace Gtk.CairoChart {
|
||||||
// Join and calc X-axes
|
// Join and calc X-axes
|
||||||
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
||||||
var s = series[si];
|
var s = series[si];
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
if (nskip != 0) {--nskip; continue;}
|
if (nskip != 0) {--nskip; continue;}
|
||||||
double max_rec_width = 0; double max_rec_height = 0;
|
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);
|
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
|
// join relative x-axes with non-intersect places
|
||||||
for (int sj = si - 1; sj >= 0; --sj) {
|
for (int sj = si - 1; sj >= 0; --sj) {
|
||||||
var s2 = series[sj];
|
var s2 = series[sj];
|
||||||
if (!s2.show) continue;
|
if (!s2.zoom_show) continue;
|
||||||
bool has_intersection = false;
|
bool has_intersection = false;
|
||||||
for (int sk = si; sk > sj; --sk) {
|
for (int sk = si; sk > sj; --sk) {
|
||||||
var s3 = series[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)
|
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.position != s3.axis_x.position
|
||||||
|| s2.axis_x.type != s3.axis_x.type) {
|
|| s2.axis_x.type != s3.axis_x.type) {
|
||||||
|
@ -627,7 +627,7 @@ namespace Gtk.CairoChart {
|
||||||
// Join and calc Y-axes
|
// Join and calc Y-axes
|
||||||
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
||||||
var s = series[si];
|
var s = series[si];
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
if (nskip != 0) {--nskip; continue;}
|
if (nskip != 0) {--nskip; continue;}
|
||||||
double max_rec_width = 0; double max_rec_height = 0;
|
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);
|
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
|
// join relative x-axes with non-intersect places
|
||||||
for (int sj = si - 1; sj >= 0; --sj) {
|
for (int sj = si - 1; sj >= 0; --sj) {
|
||||||
var s2 = series[sj];
|
var s2 = series[sj];
|
||||||
if (!s2.show) continue;
|
if (!s2.zoom_show) continue;
|
||||||
bool has_intersection = false;
|
bool has_intersection = false;
|
||||||
for (int sk = si; sk > sj; --sk) {
|
for (int sk = si; sk > sj; --sk) {
|
||||||
var s3 = series[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)
|
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_y.position != s3.axis_y.position
|
||||||
|| s2.axis_x.type != s3.axis_x.type) {
|
|| s2.axis_x.type != s3.axis_x.type) {
|
||||||
|
@ -682,7 +682,7 @@ namespace Gtk.CairoChart {
|
||||||
protected virtual void draw_horizontal_axis () {
|
protected virtual void draw_horizontal_axis () {
|
||||||
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
||||||
var s = series[si];
|
var s = series[si];
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
if (common_x_axes && si != zoom_first_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.
|
// 1. Detect max record width/height by axis_rec_npoints equally selected points using format.
|
||||||
double max_rec_width, max_rec_height;
|
double max_rec_width, max_rec_height;
|
||||||
|
@ -833,11 +833,11 @@ namespace Gtk.CairoChart {
|
||||||
// join relative x-axes with non-intersect places
|
// join relative x-axes with non-intersect places
|
||||||
for (int sj = si - 1; sj >= 0; --sj) {
|
for (int sj = si - 1; sj >= 0; --sj) {
|
||||||
var s2 = series[sj];
|
var s2 = series[sj];
|
||||||
if (!s2.show) continue;
|
if (!s2.zoom_show) continue;
|
||||||
bool has_intersection = false;
|
bool has_intersection = false;
|
||||||
for (int sk = si; sk > sj; --sk) {
|
for (int sk = si; sk > sj; --sk) {
|
||||||
var s3 = series[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)
|
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.position != s3.axis_x.position
|
||||||
|| s2.axis_x.type != s3.axis_x.type) {
|
|| s2.axis_x.type != s3.axis_x.type) {
|
||||||
|
@ -873,7 +873,7 @@ namespace Gtk.CairoChart {
|
||||||
protected virtual void draw_vertical_axis () {
|
protected virtual void draw_vertical_axis () {
|
||||||
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
for (var si = series.length - 1, nskip = 0; si >=0; --si) {
|
||||||
var s = series[si];
|
var s = series[si];
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
if (common_y_axes && si != zoom_first_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.
|
// 1. Detect max record width/height by axis_rec_npoints equally selected points using format.
|
||||||
double max_rec_width, max_rec_height;
|
double max_rec_width, max_rec_height;
|
||||||
|
@ -976,11 +976,11 @@ namespace Gtk.CairoChart {
|
||||||
// join relative x-axes with non-intersect places
|
// join relative x-axes with non-intersect places
|
||||||
for (int sj = si - 1; sj >= 0; --sj) {
|
for (int sj = si - 1; sj >= 0; --sj) {
|
||||||
var s2 = series[sj];
|
var s2 = series[sj];
|
||||||
if (!s2.show) continue;
|
if (!s2.zoom_show) continue;
|
||||||
bool has_intersection = false;
|
bool has_intersection = false;
|
||||||
for (int sk = si; sk > sj; --sk) {
|
for (int sk = si; sk > sj; --sk) {
|
||||||
var s3 = series[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)
|
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_y.position != s3.axis_y.position) {
|
||||||
has_intersection = true;
|
has_intersection = true;
|
||||||
|
@ -1047,9 +1047,32 @@ namespace Gtk.CairoChart {
|
||||||
return Point (get_real_x(s, p.x), get_real_y(s, p.y));
|
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) {
|
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)
|
if (x_in_range(p.x, x0, x1) && y_in_range(p.y, y0, y1))
|
||||||
&& (y0 <= p.y <= y1 || y1 <= p.y <= y0))
|
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1130,9 +1153,9 @@ namespace Gtk.CairoChart {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual Point[] sort_points (Series s) {
|
protected virtual Point[] sort_points (Series s, Series.Sort sort) {
|
||||||
var points = s.points.copy();
|
var points = s.points.copy();
|
||||||
switch(s.sort) {
|
switch(sort) {
|
||||||
case Series.Sort.BY_X:
|
case Series.Sort.BY_X:
|
||||||
sort_points_delegate(points, (a, b) => {
|
sort_points_delegate(points, (a, b) => {
|
||||||
if (a.x < b.x) return -1;
|
if (a.x < b.x) return -1;
|
||||||
|
@ -1154,9 +1177,9 @@ namespace Gtk.CairoChart {
|
||||||
protected virtual void draw_series () {
|
protected virtual void draw_series () {
|
||||||
for (var si = 0; si < series.length; ++si) {
|
for (var si = 0; si < series.length; ++si) {
|
||||||
var s = series[si];
|
var s = series[si];
|
||||||
if (!s.show) continue;
|
if (!s.zoom_show) continue;
|
||||||
if (s.points.length == 0) 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);
|
set_line_style(s.line_style);
|
||||||
// draw series line
|
// draw series line
|
||||||
for (int i = 1; i < points.length; ++i) {
|
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) {
|
public virtual void set_active_cursor (double x, double y, bool remove = false) {
|
||||||
active_cursor = Point (scr2rel_x(x), scr2rel_y(y));
|
active_cursor = Point (scr2rel_x(x), scr2rel_y(y));
|
||||||
is_cursor_active = true;
|
is_cursor_active = ! remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void add_active_cursor () {
|
public virtual void add_active_cursor () {
|
||||||
|
@ -1199,7 +1222,7 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
public CursorOrientation cursors_orientation = CursorOrientation.VERTICAL;
|
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 () {
|
public virtual void remove_active_cursor () {
|
||||||
if (cursors.length() == 0) return;
|
if (cursors.length() == 0) return;
|
||||||
|
@ -1210,47 +1233,81 @@ namespace Gtk.CairoChart {
|
||||||
double d = distance;
|
double d = distance;
|
||||||
switch (cursors_orientation) {
|
switch (cursors_orientation) {
|
||||||
case CursorOrientation.VERTICAL:
|
case CursorOrientation.VERTICAL:
|
||||||
d = (c.x - active_cursor.x).abs();
|
d = (rel2scr_x(c.x) - rel2scr_x(active_cursor.x)).abs();
|
||||||
break;
|
break;
|
||||||
case CursorOrientation.HORIZONTAL:
|
case CursorOrientation.HORIZONTAL:
|
||||||
d = (c.y - active_cursor.y).abs();
|
d = (rel2scr_y(c.y) - rel2scr_y(active_cursor.y)).abs();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (distance > d) {
|
if (d < distance) {
|
||||||
distance = d;
|
distance = d;
|
||||||
rm_indx = i;
|
rm_indx = i;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if (distance < cursor_max_distance)
|
if (distance < cursor_max_rm_distance)
|
||||||
cursors.delete_link(cursors.nth(rm_indx));
|
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) {
|
protected virtual bool get_cursor_limits (Series s, Point cursor, out Point low, out Point high) {
|
||||||
var points = sort_points (s);
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
low.x = plot_area_x_min;
|
low.x = plot_area_x_max;
|
||||||
low.y = plot_area_y_min;
|
low.y = plot_area_y_max;
|
||||||
high.x = plot_area_x_max;
|
high.x = plot_area_x_min;
|
||||||
high.y = plot_area_y_max;
|
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) {
|
for (var i = 0; i + 1 < points.length; ++i) {
|
||||||
switch (cursors_orientation) {
|
switch (cursors_orientation) {
|
||||||
case CursorOrientation.VERTICAL:
|
case CursorOrientation.VERTICAL:
|
||||||
Float128 y = 0.0;
|
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 (vcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]), rel2scr_x(cursor.x),
|
||||||
if (y < low.y) low.y = y;
|
plot_area_y_min, plot_area_y_max, out y)) {
|
||||||
if (y > high.y) high.y = 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;
|
ret = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CursorOrientation.HORIZONTAL:
|
case CursorOrientation.HORIZONTAL:
|
||||||
Float128 x = 0.0;
|
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 (hcross(get_scr_point(s, points[i]), get_scr_point(s, points[i+1]),
|
||||||
if (x < low.x) low.x = x;
|
plot_area_x_min, plot_area_x_max, rel2scr_y(cursor.y), out x)) {
|
||||||
if (x > high.x) high.x = 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;
|
ret = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1259,13 +1316,14 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
if (common_x_axes) {
|
if (common_x_axes) {
|
||||||
switch (s.axis_x.position) {
|
switch (s.axis_x.position) {
|
||||||
case Axis.Position.LOW: low.y = plot_area_y_max + 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: high.y = plot_area_y_min - 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:
|
case Axis.Position.BOTH:
|
||||||
low.y = plot_area_y_max + s.axis_x.font_indent;
|
high.y = plot_area_y_max + s.axis_x.font_indent;
|
||||||
high.y = plot_area_y_min - s.axis_x.font_indent;
|
low.y = plot_area_y_min - s.axis_x.font_indent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ret = true;
|
||||||
}
|
}
|
||||||
if (common_y_axes) {
|
if (common_y_axes) {
|
||||||
switch (s.axis_y.position) {
|
switch (s.axis_y.position) {
|
||||||
|
@ -1276,53 +1334,31 @@ namespace Gtk.CairoChart {
|
||||||
high.x = plot_area_x_max + s.axis_y.font_indent;
|
high.x = plot_area_x_max + s.axis_y.font_indent;
|
||||||
break;
|
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 () {
|
protected virtual void draw_cursors () {
|
||||||
if (series.length == 0) return;
|
if (series.length == 0) return;
|
||||||
|
|
||||||
var all_cursors = cursors.copy();
|
var all_cursors = cursors.copy_deep ((src) => { return src; });
|
||||||
all_cursors.append(active_cursor);
|
if (is_cursor_active)
|
||||||
|
all_cursors.append(active_cursor);
|
||||||
|
|
||||||
foreach (var c in all_cursors) {
|
foreach (var c in all_cursors) {
|
||||||
switch (cursors_orientation) {
|
switch (cursors_orientation) {
|
||||||
case CursorOrientation.VERTICAL:
|
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:
|
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 low = Point(plot_area_x_max, plot_area_y_max); // low and high
|
||||||
var high = Point(plot_area_x_min, plot_area_y_max); // points of the cursor
|
var high = Point(plot_area_x_min, plot_area_y_min); // points of the cursor
|
||||||
foreach (var s in series) {
|
foreach (var s in series) {
|
||||||
|
if (!s.zoom_show) continue;
|
||||||
var l = Point(), h = Point();
|
var l = Point(), h = Point();
|
||||||
if (get_cursor_limits (s, c, out l, out h)) {
|
if (get_cursor_limits (s, c, out l, out h)) {
|
||||||
if (l.x < low.x) low.x = l.x;
|
if (l.x < low.x) low.x = l.x;
|
||||||
|
@ -1334,7 +1370,7 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
switch (cursors_orientation) {
|
switch (cursors_orientation) {
|
||||||
case CursorOrientation.VERTICAL:
|
case CursorOrientation.VERTICAL:
|
||||||
// TODO: draw cursor line
|
if (low.y > high.y) continue;
|
||||||
set_line_style(cursor_line_style);
|
set_line_style(cursor_line_style);
|
||||||
context.move_to (rel2scr_x(c.x), low.y);
|
context.move_to (rel2scr_x(c.x), low.y);
|
||||||
context.line_to (rel2scr_x(c.x), high.y);
|
context.line_to (rel2scr_x(c.x), high.y);
|
||||||
|
@ -1342,14 +1378,14 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
// TODO: show values
|
// TODO: show values
|
||||||
if (common_x_axes)
|
if (common_x_axes)
|
||||||
// TODO: show only Y value
|
// show only Y value
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
// TODO: show [X;Y]
|
// show [X;Y]
|
||||||
;
|
;
|
||||||
break;
|
break;
|
||||||
case CursorOrientation.HORIZONTAL:
|
case CursorOrientation.HORIZONTAL:
|
||||||
// TODO: draw cursor line
|
if (low.x > high.x) continue;
|
||||||
set_line_style(cursor_line_style);
|
set_line_style(cursor_line_style);
|
||||||
context.move_to (low.x, rel2scr_y(c.y));
|
context.move_to (low.x, rel2scr_y(c.y));
|
||||||
context.line_to (high.x, rel2scr_y(c.y));
|
context.line_to (high.x, rel2scr_y(c.y));
|
||||||
|
@ -1357,10 +1393,10 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
// TODO: show values
|
// TODO: show values
|
||||||
if (common_y_axes)
|
if (common_y_axes)
|
||||||
// TODO: show only X value
|
// show only X value
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
// TODO: show [X;Y]
|
// show [X;Y]
|
||||||
;
|
;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1369,6 +1405,7 @@ namespace Gtk.CairoChart {
|
||||||
|
|
||||||
public Chart copy () {
|
public Chart copy () {
|
||||||
var chart = new Chart ();
|
var chart = new Chart ();
|
||||||
|
chart.active_cursor = this.active_cursor;
|
||||||
chart.axis_rec_npoints = this.axis_rec_npoints;
|
chart.axis_rec_npoints = this.axis_rec_npoints;
|
||||||
chart.bg_color = this.bg_color;
|
chart.bg_color = this.bg_color;
|
||||||
chart.border_color = this.border_color;
|
chart.border_color = this.border_color;
|
||||||
|
@ -1379,7 +1416,12 @@ namespace Gtk.CairoChart {
|
||||||
chart.cur_x_min = this.cur_x_min;
|
chart.cur_x_min = this.cur_x_min;
|
||||||
chart.cur_y_max = this.cur_y_max;
|
chart.cur_y_max = this.cur_y_max;
|
||||||
chart.cur_y_min = this.cur_y_min;
|
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.height = this.height;
|
||||||
|
chart.is_cursor_active = this.is_cursor_active;
|
||||||
chart.legend = this.legend.copy();
|
chart.legend = this.legend.copy();
|
||||||
chart.legend_height = this.legend_height;
|
chart.legend_height = this.legend_height;
|
||||||
chart.legend_line_length = this.legend_line_length;
|
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_min = this._rel_zoom_y_min;
|
||||||
chart._rel_zoom_y_max = this._rel_zoom_y_max;
|
chart._rel_zoom_y_max = this._rel_zoom_y_max;
|
||||||
chart.selection_style = this.selection_style;
|
chart.selection_style = this.selection_style;
|
||||||
|
chart.series = this.series.copy();
|
||||||
chart.show_legend = this.show_legend;
|
chart.show_legend = this.show_legend;
|
||||||
chart.title = this.title.copy().copy();
|
chart.title = this.title.copy().copy();
|
||||||
chart.title_height = this.title_height;
|
chart.title_height = this.title_height;
|
||||||
chart.title_vindent = this.title_vindent;
|
chart.title_vindent = this.title_vindent;
|
||||||
chart.title_width = this.title_width;
|
chart.title_width = this.title_width;
|
||||||
chart.width = this.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;
|
return chart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,12 @@ namespace Gtk.CairoChart {
|
||||||
double dash_offset;
|
double dash_offset;
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
public LineStyle (double width = 1,
|
public LineStyle (Color color = Color(),
|
||||||
Cairo.LineJoin line_join = Cairo.LineJoin.MITER,
|
double width = 1,
|
||||||
Cairo.LineCap line_cap = Cairo.LineCap.ROUND,
|
|
||||||
double[]? dashes = null, double dash_offset = 0,
|
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.width = width;
|
||||||
this.line_join = line_join;
|
this.line_join = line_join;
|
||||||
this.line_cap = line_cap;
|
this.line_cap = line_cap;
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace Gtk.CairoChart {
|
||||||
default = Color (0.0, 0.0, 0.0, 1.0);
|
default = Color (0.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool show = true;
|
public bool zoom_show = true;
|
||||||
|
|
||||||
public Series copy () {
|
public Series copy () {
|
||||||
var series = new Series ();
|
var series = new Series ();
|
||||||
|
@ -63,7 +63,7 @@ namespace Gtk.CairoChart {
|
||||||
series.points = this.points.copy();
|
series.points = this.points.copy();
|
||||||
series.sort = this.sort;
|
series.sort = this.sort;
|
||||||
series.title = this.title.copy();
|
series.title = this.title.copy();
|
||||||
series.show = this.show;
|
series.zoom_show = this.zoom_show;
|
||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,8 @@ int main (string[] args) {
|
||||||
var radio_button2 = new RadioButton.with_label (radio_button1.get_group(), "Right Legend");
|
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_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_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 (() => {
|
button1.clicked.connect (() => {
|
||||||
chart = chart1; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
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;
|
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
|
||||||
default: 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 (() => {
|
button2.clicked.connect (() => {
|
||||||
chart = chart2; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
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;
|
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
|
||||||
default: 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 (() => {
|
button3.clicked.connect (() => {
|
||||||
chart = chart3; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
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;
|
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
|
||||||
default: 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 (() => {
|
button4.clicked.connect (() => {
|
||||||
chart = chart4; da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
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;
|
case Legend.Position.BOTTOM: radio_button4.set_active(true); break;
|
||||||
default: 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 (() => {
|
button5.clicked.connect (() => {
|
||||||
for (var i = 0; i < chart.series.length; ++i) {
|
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) => {
|
radio_button7.toggled.connect ((button) => {
|
||||||
if (button.get_active()) {
|
if (button.get_active()) {
|
||||||
chart.cursors_orientation = Chart.CursorOrientation.VERTICAL;
|
chart.cursors_orientation = Chart.CursorOrientation.VERTICAL;
|
||||||
|
@ -423,11 +439,13 @@ int main (string[] args) {
|
||||||
case 1: // start cursor position selection
|
case 1: // start cursor position selection
|
||||||
if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { // remove cursor
|
if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { // remove cursor
|
||||||
chart.set_active_cursor (event.x, event.y, true);
|
chart.set_active_cursor (event.x, event.y, true);
|
||||||
|
chart.remove_active_cursor();
|
||||||
|
mouse_state = MouseState.FREE;
|
||||||
} else { // add cursor
|
} else { // add cursor
|
||||||
chart.set_active_cursor (event.x, event.y);
|
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());
|
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||||
mouse_state = MouseState.CURSOR_SELECTION;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // start zoom area selection
|
case 2: // start zoom area selection
|
||||||
|
@ -454,9 +472,9 @@ int main (string[] args) {
|
||||||
switch (event.button) {
|
switch (event.button) {
|
||||||
case 1: // start cursor position selection
|
case 1: // start cursor position selection
|
||||||
if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { // remove cursor
|
if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { // remove cursor
|
||||||
chart.remove_active_cursor ();
|
//chart.remove_active_cursor ();
|
||||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
//da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||||
mouse_state = MouseState.FREE;
|
//mouse_state = MouseState.FREE;
|
||||||
} else { // add cursor
|
} else { // add cursor
|
||||||
chart.add_active_cursor ();
|
chart.add_active_cursor ();
|
||||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||||
|
@ -502,7 +520,7 @@ int main (string[] args) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MouseState.CURSOR_SELECTION:
|
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());
|
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue