Several cursors methods added. Make rel_zoom_{x,y}_m{in,ax} readonly properties.
This commit is contained in:
parent
8a7ce14f5d
commit
b465034bc3
317
src/Chart.vala
317
src/Chart.vala
|
@ -87,17 +87,21 @@ namespace Gtk.CairoChart {
|
|||
}
|
||||
}
|
||||
|
||||
double rel_zoom_x_min = 0.0;
|
||||
double rel_zoom_x_max = 1.0;
|
||||
double rel_zoom_y_min = 0.0;
|
||||
double rel_zoom_y_max = 1.0;
|
||||
double _rel_zoom_x_min = 0.0;
|
||||
double _rel_zoom_x_max = 1.0;
|
||||
double _rel_zoom_y_min = 0.0;
|
||||
double _rel_zoom_y_max = 1.0;
|
||||
public double rel_zoom_x_min { get { return _rel_zoom_x_min; } default = 0.0; }
|
||||
public double rel_zoom_x_max { get { return _rel_zoom_x_max; } default = 1.0; }
|
||||
public double rel_zoom_y_min { get { return _rel_zoom_y_min; } default = 0.0; }
|
||||
public double rel_zoom_y_max { get { return _rel_zoom_y_max; } default = 1.0; }
|
||||
|
||||
int zoom_first_show = 0;
|
||||
|
||||
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.zoom_show) continue;
|
||||
if (!s.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);
|
||||
|
@ -105,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.zoom_show = false;
|
||||
s.show = false;
|
||||
continue;
|
||||
}
|
||||
if (real_x0 >= s.axis_x.zoom_min) {
|
||||
|
@ -136,24 +140,24 @@ namespace Gtk.CairoChart {
|
|||
|
||||
zoom_first_show = 0;
|
||||
for (var si = 0, max_i = series.length; si < max_i; ++si)
|
||||
if (series[si].zoom_show) {
|
||||
if (series[si].show) {
|
||||
zoom_first_show = si;
|
||||
break;
|
||||
}
|
||||
|
||||
var new_rel_zoom_x_min = rel_zoom_x_min + (x0 - plot_area_x_min) / (plot_area_x_max - plot_area_x_min) * (rel_zoom_x_max - rel_zoom_x_min);
|
||||
var new_rel_zoom_x_max = rel_zoom_x_min + (x1 - plot_area_x_min) / (plot_area_x_max - plot_area_x_min) * (rel_zoom_x_max - rel_zoom_x_min);
|
||||
var new_rel_zoom_y_min = rel_zoom_y_min + (y0 - plot_area_y_min) / (plot_area_y_max - plot_area_y_min) * (rel_zoom_y_max - rel_zoom_y_min);
|
||||
var new_rel_zoom_y_max = rel_zoom_y_min + (y1 - plot_area_y_min) / (plot_area_y_max - plot_area_y_min) * (rel_zoom_y_max - rel_zoom_y_min);
|
||||
rel_zoom_x_min = new_rel_zoom_x_min;
|
||||
rel_zoom_x_max = new_rel_zoom_x_max;
|
||||
rel_zoom_y_min = new_rel_zoom_y_min;
|
||||
rel_zoom_y_max = new_rel_zoom_y_max;
|
||||
var new_rel_zoom_x_min = _rel_zoom_x_min + (x0 - plot_area_x_min) / (plot_area_x_max - plot_area_x_min) * (_rel_zoom_x_max - _rel_zoom_x_min);
|
||||
var new_rel_zoom_x_max = _rel_zoom_x_min + (x1 - plot_area_x_min) / (plot_area_x_max - plot_area_x_min) * (_rel_zoom_x_max - _rel_zoom_x_min);
|
||||
var new_rel_zoom_y_min = _rel_zoom_y_min + (y0 - plot_area_y_min) / (plot_area_y_max - plot_area_y_min) * (_rel_zoom_y_max - _rel_zoom_y_min);
|
||||
var new_rel_zoom_y_max = _rel_zoom_y_min + (y1 - plot_area_y_min) / (plot_area_y_max - plot_area_y_min) * (_rel_zoom_y_max - _rel_zoom_y_min);
|
||||
_rel_zoom_x_min = new_rel_zoom_x_min;
|
||||
_rel_zoom_x_max = new_rel_zoom_x_max;
|
||||
_rel_zoom_y_min = new_rel_zoom_y_min;
|
||||
_rel_zoom_y_max = new_rel_zoom_y_max;
|
||||
}
|
||||
|
||||
public virtual void zoom_out () {
|
||||
foreach (var s in series) {
|
||||
s.zoom_show = true;
|
||||
s.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;
|
||||
|
@ -163,10 +167,10 @@ namespace Gtk.CairoChart {
|
|||
s.place.zoom_y_low = s.place.y_low;
|
||||
s.place.zoom_y_high = s.place.y_high;
|
||||
}
|
||||
rel_zoom_x_min = 0;
|
||||
rel_zoom_x_max = 1;
|
||||
rel_zoom_y_min = 0;
|
||||
rel_zoom_y_max = 1;
|
||||
_rel_zoom_x_min = 0;
|
||||
_rel_zoom_x_max = 1;
|
||||
_rel_zoom_y_min = 0;
|
||||
_rel_zoom_y_max = 1;
|
||||
|
||||
zoom_first_show = 0;
|
||||
}
|
||||
|
@ -174,7 +178,7 @@ namespace Gtk.CairoChart {
|
|||
public virtual void move (double delta_x, double delta_y) {
|
||||
delta_x /= plot_area_x_max - plot_area_x_min; delta_x *= - 1.0;
|
||||
delta_y /= plot_area_y_max - plot_area_y_min; delta_y *= - 1.0;
|
||||
var rzxmin = rel_zoom_x_min, rzxmax = rel_zoom_x_max, rzymin = rel_zoom_y_min, rzymax = rel_zoom_y_max;
|
||||
var rzxmin = _rel_zoom_x_min, rzxmax = _rel_zoom_x_max, rzymin = _rel_zoom_y_min, rzymax = _rel_zoom_y_max;
|
||||
zoom_out();
|
||||
//draw(); // TODO: optimize here
|
||||
delta_x *= plot_area_x_max - plot_area_x_min;
|
||||
|
@ -355,7 +359,7 @@ namespace Gtk.CairoChart {
|
|||
|
||||
foreach (var s in series) {
|
||||
|
||||
if (!s.zoom_show) continue;
|
||||
if (!s.show) continue;
|
||||
|
||||
// carry
|
||||
switch (legend.position) {
|
||||
|
@ -554,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.zoom_show) continue;
|
||||
if (!s.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
|
||||
|
@ -575,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.zoom_show) continue;
|
||||
if (!s.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);
|
||||
|
@ -585,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.zoom_show) continue;
|
||||
if (!s2.show) continue;
|
||||
bool has_intersection = false;
|
||||
for (int sk = si; sk > sj; --sk) {
|
||||
var s3 = series[sk];
|
||||
if (!s3.zoom_show) continue;
|
||||
if (!s3.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) {
|
||||
|
@ -623,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.zoom_show) continue;
|
||||
if (!s.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);
|
||||
|
@ -633,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.zoom_show) continue;
|
||||
if (!s2.show) continue;
|
||||
bool has_intersection = false;
|
||||
for (int sk = si; sk > sj; --sk) {
|
||||
var s3 = series[sk];
|
||||
if (!s3.zoom_show) continue;
|
||||
if (!s3.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) {
|
||||
|
@ -678,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.zoom_show) continue;
|
||||
if (!s.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;
|
||||
|
@ -829,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.zoom_show) continue;
|
||||
if (!s2.show) continue;
|
||||
bool has_intersection = false;
|
||||
for (int sk = si; sk > sj; --sk) {
|
||||
var s3 = series[sk];
|
||||
if (!s3.zoom_show) continue;
|
||||
if (!s3.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) {
|
||||
|
@ -869,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.zoom_show) continue;
|
||||
if (!s.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;
|
||||
|
@ -972,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.zoom_show) continue;
|
||||
if (!s2.show) continue;
|
||||
bool has_intersection = false;
|
||||
for (int sk = si; sk > sj; --sk) {
|
||||
var s3 = series[sk];
|
||||
if (!s3.zoom_show) continue;
|
||||
if (!s3.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;
|
||||
|
@ -1027,16 +1031,21 @@ namespace Gtk.CairoChart {
|
|||
return plot_area_y_max - (plot_area_y_max - plot_area_y_min) * (s.place.zoom_y_low + (y - s.axis_y.zoom_min)
|
||||
/ (s.axis_y.zoom_max - s.axis_y.zoom_min) * (s.place.zoom_y_high - s.place.zoom_y_low));
|
||||
}
|
||||
protected virtual Point get_scr_point (Series s, Point p) {
|
||||
return Point (get_scr_x(s, p.x), get_scr_y(s, p.y));
|
||||
}
|
||||
|
||||
protected virtual Float128 get_real_x (Series s, double scr_x) {
|
||||
return s.axis_x.zoom_min + ((scr_x - plot_area_x_min) / (plot_area_x_max - plot_area_x_min) - s.place.zoom_x_low)
|
||||
* (s.axis_x.zoom_max - s.axis_x.zoom_min) / (s.place.zoom_x_high - s.place.zoom_x_low);
|
||||
}
|
||||
|
||||
protected virtual Float128 get_real_y (Series s, double scr_y) {
|
||||
return s.axis_y.zoom_min + ((plot_area_y_max - scr_y) / (plot_area_y_max - plot_area_y_min) - s.place.zoom_y_low)
|
||||
* (s.axis_y.zoom_max - s.axis_y.zoom_min) / (s.place.zoom_y_high - s.place.zoom_y_low);
|
||||
}
|
||||
protected virtual Point get_real_point (Series s, Point p) {
|
||||
return Point (get_real_x(s, p.x), get_real_y(s, p.y));
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -1072,7 +1081,7 @@ namespace Gtk.CairoChart {
|
|||
}
|
||||
|
||||
delegate int PointComparator(Point a, Point b);
|
||||
void sort_points(Point[] points, PointComparator compare) {
|
||||
void sort_points_delegate(Point[] points, PointComparator compare) {
|
||||
for(var i = 0; i < points.length; ++i) {
|
||||
for(var j = i + 1; j < points.length; ++j) {
|
||||
if(compare(points[i], points[j]) > 0) {
|
||||
|
@ -1121,28 +1130,33 @@ namespace Gtk.CairoChart {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected virtual Point[] sort_points (Series s) {
|
||||
var points = s.points.copy();
|
||||
switch(s.sort) {
|
||||
case Series.Sort.BY_X:
|
||||
sort_points_delegate(points, (a, b) => {
|
||||
if (a.x < b.x) return -1;
|
||||
if (a.x > b.x) return 1;
|
||||
return 0;
|
||||
});
|
||||
break;
|
||||
case Series.Sort.BY_Y:
|
||||
sort_points_delegate(points, (a, b) => {
|
||||
if (a.y < b.y) return -1;
|
||||
if (a.y > b.y) return 1;
|
||||
return 0;
|
||||
});
|
||||
break;
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
protected virtual void draw_series () {
|
||||
for (var si = 0; si < series.length; ++si) {
|
||||
var s = series[si];
|
||||
if (!s.zoom_show) continue;
|
||||
if (!s.show) continue;
|
||||
if (s.points.length == 0) continue;
|
||||
var points = s.points.copy();
|
||||
switch(s.sort) {
|
||||
case Series.Sort.BY_X:
|
||||
sort_points(points, (a, b) => {
|
||||
if (a.x < b.x) return -1;
|
||||
if (a.x > b.x) return 1;
|
||||
return 0;
|
||||
});
|
||||
break;
|
||||
case Series.Sort.BY_Y:
|
||||
sort_points(points, (a, b) => {
|
||||
if (a.y < b.y) return -1;
|
||||
if (a.y > b.y) return 1;
|
||||
return 0;
|
||||
});
|
||||
break;
|
||||
}
|
||||
var points = sort_points(s);
|
||||
set_line_style(s.line_style);
|
||||
// draw series line
|
||||
for (int i = 1; i < points.length; ++i) {
|
||||
|
@ -1164,8 +1178,193 @@ namespace Gtk.CairoChart {
|
|||
}
|
||||
}
|
||||
|
||||
protected List<Point?> cursors = new List<Point?> ();
|
||||
protected Point active_cursor = Point ();
|
||||
protected bool is_cursor_active = false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public virtual void add_active_cursor () {
|
||||
cursors.append (active_cursor);
|
||||
is_cursor_active = false;
|
||||
}
|
||||
|
||||
public enum CursorOrientation {
|
||||
VERTICAL = 0, // default
|
||||
HORIZONTAL
|
||||
}
|
||||
|
||||
public CursorOrientation cursors_orientation = CursorOrientation.VERTICAL;
|
||||
|
||||
public double cursor_max_distance = 32;
|
||||
|
||||
public virtual void remove_active_cursor () {
|
||||
if (cursors.length() == 0) return;
|
||||
var distance = width * width;
|
||||
uint rm_indx = 0;
|
||||
uint i = 0;
|
||||
foreach (var c in cursors) {
|
||||
double d = distance;
|
||||
switch (cursors_orientation) {
|
||||
case CursorOrientation.VERTICAL:
|
||||
d = (c.x - active_cursor.x).abs();
|
||||
break;
|
||||
case CursorOrientation.HORIZONTAL:
|
||||
d = (c.y - active_cursor.y).abs();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (distance > d) {
|
||||
distance = d;
|
||||
rm_indx = i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (distance < cursor_max_distance)
|
||||
cursors.delete_link(cursors.nth(rm_indx));
|
||||
}
|
||||
|
||||
// TODO:
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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.BOTH:
|
||||
low.y = plot_area_y_max + s.axis_x.font_indent;
|
||||
high.y = plot_area_y_min - s.axis_x.font_indent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (common_y_axes) {
|
||||
switch (s.axis_y.position) {
|
||||
case Axis.Position.LOW: low.x = plot_area_x_min - s.axis_y.font_indent; break;
|
||||
case Axis.Position.HIGH: high.x = plot_area_x_max + s.axis_y.font_indent; break;
|
||||
case Axis.Position.BOTH:
|
||||
low.x = plot_area_x_min - s.axis_y.font_indent;
|
||||
high.x = plot_area_x_max + s.axis_y.font_indent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
case CursorOrientation.HORIZONTAL:
|
||||
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
|
||||
foreach (var s in series) {
|
||||
var l = Point(), h = Point();
|
||||
if (get_cursor_limits (s, c, out l, out h)) {
|
||||
if (l.x < low.x) low.x = l.x;
|
||||
if (l.y < low.y) low.y = l.y;
|
||||
if (h.x > high.x) high.x = h.x;
|
||||
if (h.y > high.y) high.y = h.y;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cursors_orientation) {
|
||||
case CursorOrientation.VERTICAL:
|
||||
// TODO: draw cursor line
|
||||
set_line_style(cursor_line_style);
|
||||
context.move_to (rel2scr_x(c.x), low.y);
|
||||
context.line_to (rel2scr_x(c.x), high.y);
|
||||
context.stroke();
|
||||
|
||||
// TODO: show values
|
||||
if (common_x_axes)
|
||||
// TODO: show only Y value
|
||||
;
|
||||
else
|
||||
// TODO: show [X;Y]
|
||||
;
|
||||
break;
|
||||
case CursorOrientation.HORIZONTAL:
|
||||
// TODO: draw cursor line
|
||||
set_line_style(cursor_line_style);
|
||||
context.move_to (low.x, rel2scr_y(c.y));
|
||||
context.line_to (high.x, rel2scr_y(c.y));
|
||||
context.stroke();
|
||||
|
||||
// TODO: show values
|
||||
if (common_y_axes)
|
||||
// TODO: show only X value
|
||||
;
|
||||
else
|
||||
// TODO: show [X;Y]
|
||||
;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Chart copy () {
|
||||
|
@ -1193,10 +1392,10 @@ namespace Gtk.CairoChart {
|
|||
chart.plot_area_x_min = this.plot_area_x_min;
|
||||
chart.plot_area_y_max = this.plot_area_y_max;
|
||||
chart.plot_area_y_min = this.plot_area_y_min;
|
||||
chart.rel_zoom_x_min = this.rel_zoom_x_min;
|
||||
chart.rel_zoom_x_max = this.rel_zoom_x_max;
|
||||
chart.rel_zoom_y_min = this.rel_zoom_y_min;
|
||||
chart.rel_zoom_y_max = this.rel_zoom_y_max;
|
||||
chart._rel_zoom_x_min = this._rel_zoom_x_min;
|
||||
chart._rel_zoom_x_max = this._rel_zoom_x_max;
|
||||
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.show_legend = this.show_legend;
|
||||
chart.title = this.title.copy().copy();
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace Gtk.CairoChart {
|
|||
Float128 x;
|
||||
Float128 y;
|
||||
|
||||
public Point (Float128 x, Float128 y) {
|
||||
public Point (Float128 x = 0.0, Float128 y = 0.0) {
|
||||
this.x = x; this.y = y;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Gtk.CairoChart {
|
|||
default = Color (0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
public bool zoom_show = true;
|
||||
public bool 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.zoom_show = this.zoom_show;
|
||||
series.show = this.show;
|
||||
return series;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,6 +203,13 @@ bool point_in_chart (Chart chart, double x, double y) {
|
|||
return true;
|
||||
}
|
||||
|
||||
enum MouseState {
|
||||
FREE = 0, // default
|
||||
DRAW_SELECTION,
|
||||
MOVING_CHART,
|
||||
CURSOR_SELECTION
|
||||
}
|
||||
|
||||
int main (string[] args) {
|
||||
init (ref args);
|
||||
|
||||
|
@ -346,9 +353,40 @@ int main (string[] args) {
|
|||
}
|
||||
});
|
||||
|
||||
bool draw_selection = false;
|
||||
|
||||
/* var radio_button5 = new RadioButton.with_label (null, "Labels");
|
||||
var radio_button6 = new RadioButton.with_label_from_widget (radio_button5, "Cursors");
|
||||
radio_button5.toggled.connect ((button) => {
|
||||
// TODO: set labels
|
||||
if (button.get_active()) {
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
}
|
||||
});
|
||||
radio_button6.toggled.connect ((button) => {
|
||||
// TODO: set cursors
|
||||
if (button.get_active()) {
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
}
|
||||
});*/
|
||||
|
||||
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;
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
}
|
||||
});
|
||||
radio_button8.toggled.connect ((button) => {
|
||||
if (button.get_active()) {
|
||||
chart.cursors_orientation = Chart.CursorOrientation.HORIZONTAL;
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
}
|
||||
});
|
||||
|
||||
MouseState mouse_state = MouseState.FREE;
|
||||
|
||||
double sel_x0 = 0, sel_x1 = 0, sel_y0 = 0, sel_y1 = 0;
|
||||
bool moving_chart = false;
|
||||
double mov_x0 = 0, mov_y0 = 0;
|
||||
|
||||
da.draw.connect((context) => {
|
||||
|
@ -363,7 +401,7 @@ int main (string[] args) {
|
|||
/*var ret = */chart.draw();
|
||||
|
||||
// user's post draw operations here...
|
||||
if (draw_selection) {
|
||||
if (mouse_state == MouseState.DRAW_SELECTION) {
|
||||
context.set_source_rgba (0.5, 0.5, 0.5, 0.7);
|
||||
context.set_line_join(Cairo.LineJoin.MITER);
|
||||
context.set_line_cap(Cairo.LineCap.ROUND);
|
||||
|
@ -381,18 +419,30 @@ int main (string[] args) {
|
|||
da.button_press_event.connect((event) => {
|
||||
if (!point_in_chart(chart, event.x, event.y)) return true;
|
||||
|
||||
if (event.button == 2) {
|
||||
draw_selection = true;
|
||||
switch (event.button) {
|
||||
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);
|
||||
} else { // add cursor
|
||||
chart.set_active_cursor (event.x, event.y);
|
||||
}
|
||||
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
|
||||
sel_x0 = sel_x1 = event.x;
|
||||
sel_y0 = sel_y1 = event.y;
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
}
|
||||
mouse_state = MouseState.DRAW_SELECTION;
|
||||
break;
|
||||
|
||||
if (event.button == 3) {
|
||||
moving_chart = true;
|
||||
case 3: // start moving
|
||||
mov_x0 = event.x;
|
||||
mov_y0 = event.y;
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
mouse_state = MouseState.MOVING_CHART;
|
||||
break;
|
||||
}
|
||||
|
||||
return true; // return ret;
|
||||
|
@ -401,9 +451,20 @@ int main (string[] args) {
|
|||
|
||||
if (!point_in_chart(chart, event.x, event.y)) return true;
|
||||
|
||||
//var ret = chart.button_release_event(event);
|
||||
if (event.button == 2) {
|
||||
draw_selection = false;
|
||||
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;
|
||||
} else { // add cursor
|
||||
chart.add_active_cursor ();
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
mouse_state = MouseState.FREE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
sel_x1 = event.x;
|
||||
sel_y1 = event.y;
|
||||
if (sel_x1 > sel_x0 && sel_y1 > sel_y0)
|
||||
|
@ -411,11 +472,13 @@ int main (string[] args) {
|
|||
else
|
||||
chart.zoom_out ();
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
}
|
||||
mouse_state = MouseState.FREE;
|
||||
break;
|
||||
|
||||
if (event.button == 3) {
|
||||
moving_chart = false;
|
||||
case 3:
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
mouse_state = MouseState.FREE;
|
||||
break;
|
||||
}
|
||||
|
||||
return true; // return ret;
|
||||
|
@ -423,20 +486,25 @@ int main (string[] args) {
|
|||
da.motion_notify_event.connect((event) => {
|
||||
if (!point_in_chart(chart, event.x, event.y)) return true;
|
||||
|
||||
//var ret = chart.motion_notify_event(event);
|
||||
|
||||
if (draw_selection) {
|
||||
switch (mouse_state) {
|
||||
case MouseState.DRAW_SELECTION:
|
||||
sel_x1 = event.x;
|
||||
sel_y1 = event.y;
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
}
|
||||
break;
|
||||
|
||||
if (moving_chart) {
|
||||
case MouseState.MOVING_CHART:
|
||||
var delta_x = event.x - mov_x0, delta_y = event.y - mov_y0;
|
||||
chart.move (delta_x, delta_y);
|
||||
mov_x0 = event.x;
|
||||
mov_y0 = event.y;
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
break;
|
||||
|
||||
case MouseState.CURSOR_SELECTION:
|
||||
chart.set_active_cursor (event.x, event.y, true);
|
||||
da.queue_draw_area(0, 0, da.get_allocated_width(), da.get_allocated_height());
|
||||
break;
|
||||
}
|
||||
|
||||
return true; // return ret;
|
||||
|
@ -462,6 +530,10 @@ int main (string[] args) {
|
|||
vbox2.pack_start(radio_button2, false, false, 0);
|
||||
vbox2.pack_start(radio_button3, false, false, 0);
|
||||
vbox2.pack_start(radio_button4, false, false, 0);
|
||||
//vbox2.pack_start(radio_button5, false, false, 0);
|
||||
//vbox2.pack_start(radio_button6, false, false, 0);
|
||||
vbox2.pack_start(radio_button7, false, false, 0);
|
||||
vbox2.pack_start(radio_button8, false, false, 0);
|
||||
|
||||
var hbox = new Box(Orientation.HORIZONTAL, 0);
|
||||
hbox.pack_start(da, true, true, 0);
|
||||
|
|
Loading…
Reference in New Issue