Cairo-Chart/src/Legend.vala

276 lines
6.1 KiB
Vala
Raw Normal View History

2018-01-08 23:33:13 +03:00
namespace CairoChart {
2018-01-22 16:22:47 +03:00
/**
* {@link Chart} ``Legend``.
*/
2017-08-28 14:47:31 +03:00
public class Legend {
2018-01-08 23:33:13 +03:00
2018-01-23 12:27:02 +03:00
protected unowned Chart chart;
2018-01-22 18:21:29 +03:00
protected double [] max_font_heights;
2018-01-22 16:54:54 +03:00
/**
* Show legend?
*/
public bool show = true;
2018-01-22 16:22:47 +03:00
/**
* ``Legend`` position.
*/
2017-08-28 14:47:31 +03:00
public enum Position {
2018-01-22 16:22:47 +03:00
/**
* Top position.
*/
TOP = 0,
/**
* Left position.
*/
2017-08-28 14:47:31 +03:00
LEFT,
2018-01-22 16:22:47 +03:00
/**
* Right position.
*/
2017-08-28 14:47:31 +03:00
RIGHT,
2018-01-22 16:22:47 +03:00
/**
* Bottom position.
*/
2017-08-28 14:47:31 +03:00
BOTTOM
}
2018-01-08 23:33:13 +03:00
2018-01-22 16:22:47 +03:00
/**
* Position.
*/
2017-08-28 14:47:31 +03:00
public Position position = Position.TOP;
2018-01-22 16:22:47 +03:00
2018-01-22 16:28:09 +03:00
/**
* ``Legend`` background color.
*/
2017-08-28 14:47:31 +03:00
public Color bg_color = Color(1, 1, 1);
2018-01-22 16:28:09 +03:00
/**
* Border line style.
*/
2018-01-20 13:11:17 +03:00
public LineStyle border_style = LineStyle ();
2018-01-22 16:28:09 +03:00
2018-01-22 17:20:45 +03:00
/**
* Both vertical & horizontal spacing.
*/
public double spacing = 5;
/**
* ``Legend`` width.
*/
public double width { get; protected set; }
/**
* ``Legend`` height.
*/
public double height { get; protected set; }
/**
* {@link Series} line length.
*/
2018-01-22 17:47:00 +03:00
public double line_length = 30;
2018-01-22 17:20:45 +03:00
2018-01-22 16:54:54 +03:00
/**
* Constructs a new ``Legend``.
* @param chart ``Chart`` instance.
*/
public Legend (Chart chart) {
this.chart = chart;
border_style.color = Color (0, 0, 0, 0.3);
}
/**
* Gets a copy of the ``Legend``.
*/
2018-01-15 12:05:21 +03:00
public virtual Legend copy () {
2018-01-22 16:54:54 +03:00
var legend = new Legend (chart);
2017-08-28 18:16:48 +03:00
legend.position = this.position;
legend.bg_color = this.bg_color;
2018-01-19 10:52:06 +03:00
legend.spacing = this.spacing;
2018-01-08 23:33:13 +03:00
legend.height = this.height;
legend.line_length = this.line_length;
legend.width = this.width;
legend.show = this.show;
legend.max_font_heights = this.max_font_heights;
2017-08-28 18:16:48 +03:00
return legend;
}
2018-01-22 17:20:45 +03:00
/**
* Draws the ``Legend``.
*/
2018-01-22 16:54:54 +03:00
public virtual void draw () {
if (!show) return;
2018-01-22 16:54:54 +03:00
process (ProcessType.CALC);
process (ProcessType.DRAW);
2018-01-08 23:33:13 +03:00
}
2018-01-22 16:57:15 +03:00
protected virtual void draw_rect (out double x0, out double y0) {
2018-01-22 17:47:00 +03:00
x0 = y0 = 0;
2018-01-17 10:36:10 +03:00
if (chart.ctx != null) {
2018-01-08 23:33:13 +03:00
switch (position) {
case Position.TOP:
2018-01-18 13:52:06 +03:00
x0 = (chart.area.width - width) / 2;
2018-01-23 20:40:23 +03:00
var title_height = chart.title.height + (chart.legend.position == Position.TOP ?
2018-01-22 15:03:10 +03:00
chart.title.font.vspacing * 2 : chart.title.font.vspacing);
2018-01-18 12:55:20 +03:00
y0 = title_height;
2018-01-08 23:33:13 +03:00
break;
case Position.BOTTOM:
2018-01-18 13:52:06 +03:00
x0 = (chart.area.width - width) / 2;
y0 = chart.area.height - height;
2018-01-08 23:33:13 +03:00
break;
case Position.LEFT:
x0 = 0;
2018-01-18 13:52:06 +03:00
y0 = (chart.area.height - height) / 2;
2018-01-08 23:33:13 +03:00
break;
case Position.RIGHT:
2018-01-18 13:52:06 +03:00
x0 = chart.area.width - width;
y0 = (chart.area.height - height) / 2;
2018-01-08 23:33:13 +03:00
break;
}
2018-01-16 20:39:59 +03:00
chart.color = bg_color;
2018-01-17 10:36:10 +03:00
chart.ctx.rectangle (x0, y0, width, height);
chart.ctx.fill();
2018-01-19 11:36:33 +03:00
border_style.apply(chart);
2018-01-17 10:36:10 +03:00
chart.ctx.move_to (x0, y0);
chart.ctx.rel_line_to (width, 0);
chart.ctx.rel_line_to (0, height);
chart.ctx.rel_line_to (-width, 0);
chart.ctx.rel_line_to (0, -height);
chart.ctx.stroke ();
2018-01-08 23:33:13 +03:00
}
}
2018-01-22 16:56:08 +03:00
protected enum ProcessType {
2018-01-08 23:33:13 +03:00
CALC = 0, // default
DRAW
}
2018-01-22 16:56:08 +03:00
protected virtual void process (ProcessType process_type) {
2018-01-08 23:33:13 +03:00
var legend_x0 = 0.0, legend_y0 = 0.0;
var heights_idx = 0;
var leg_width_sum = 0.0;
var leg_height_sum = 0.0;
2018-01-22 17:47:00 +03:00
var max_font_h = 0.0;
2018-01-08 23:33:13 +03:00
2018-01-22 18:21:29 +03:00
double [] mfh = max_font_heights;
2018-01-08 23:33:13 +03:00
// prepare
switch (process_type) {
case ProcessType.CALC:
2018-01-22 17:47:00 +03:00
width = 0;
height = 0;
2018-01-22 18:21:29 +03:00
mfh = {};
2018-01-08 23:33:13 +03:00
heights_idx = 0;
break;
case ProcessType.DRAW:
2018-01-22 16:54:54 +03:00
draw_rect(out legend_x0, out legend_y0);
2018-01-08 23:33:13 +03:00
break;
}
foreach (var s in chart.series) {
if (!s.zoom_show) continue;
// carry
switch (position) {
case Position.TOP:
case Position.BOTTOM:
2018-01-21 18:41:41 +03:00
var ser_title_width = s.title.width + line_length;
2018-01-22 17:31:43 +03:00
if (leg_width_sum + (leg_width_sum == 0 ? 0 : s.title.font.hspacing) + ser_title_width > chart.area.width) { // carry
2018-01-08 23:33:13 +03:00
leg_height_sum += max_font_h;
switch (process_type) {
case ProcessType.CALC:
2018-01-22 18:21:29 +03:00
mfh += max_font_h;
2018-01-08 23:33:13 +03:00
width = double.max(width, leg_width_sum);
break;
case ProcessType.DRAW:
heights_idx++;
break;
}
2018-01-22 17:47:00 +03:00
leg_width_sum = 0;
2018-01-08 23:33:13 +03:00
max_font_h = 0;
}
break;
}
switch (process_type) {
case ProcessType.DRAW:
2018-01-22 17:31:43 +03:00
var x = legend_x0 + leg_width_sum + (leg_width_sum == 0 ? 0 : s.title.font.hspacing);
2018-01-22 18:21:29 +03:00
var y = legend_y0 + leg_height_sum + mfh[heights_idx] / 2 + s.title.height / 2;
2018-01-08 23:33:13 +03:00
// series title
2018-01-17 10:36:10 +03:00
chart.ctx.move_to (x + line_length, y);
2018-01-16 20:39:59 +03:00
chart.color = s.title.color;
2018-01-21 17:27:46 +03:00
s.title.show();
2018-01-08 23:33:13 +03:00
// series line style
2018-01-21 18:41:41 +03:00
chart.ctx.move_to (x, y - s.title.height / 2);
2018-01-19 11:36:33 +03:00
s.line_style.apply(chart);
2018-01-17 10:36:10 +03:00
chart.ctx.rel_line_to (line_length, 0);
chart.ctx.stroke();
2018-01-22 13:10:27 +03:00
s.marker.draw_at_pos (Point(x + line_length / 2, y - s.title.height / 2));
2018-01-08 23:33:13 +03:00
break;
}
switch (position) {
case Position.TOP:
case Position.BOTTOM:
2018-01-21 18:41:41 +03:00
var ser_title_width = s.title.width + line_length;
2018-01-22 17:31:43 +03:00
leg_width_sum += (leg_width_sum == 0 ? 0 : s.title.font.hspacing) + ser_title_width;
max_font_h = double.max (max_font_h, s.title.height) + (leg_height_sum != 0 ? s.title.font.vspacing : 0);
2018-01-08 23:33:13 +03:00
break;
case Position.LEFT:
case Position.RIGHT:
switch (process_type) {
case ProcessType.CALC:
2018-01-22 18:21:29 +03:00
mfh += s.title.height + (leg_height_sum != 0 ? s.title.font.vspacing : 0);
2018-01-21 18:41:41 +03:00
width = double.max (width, s.title.width + line_length);
2018-01-08 23:33:13 +03:00
break;
case ProcessType.DRAW:
heights_idx++;
break;
}
2018-01-22 17:31:43 +03:00
leg_height_sum += s.title.height + (leg_height_sum != 0 ? s.title.font.vspacing : 0);
2018-01-08 23:33:13 +03:00
break;
}
}
// TOP, BOTTOM
switch (position) {
case Position.TOP:
case Position.BOTTOM:
if (leg_width_sum != 0) {
leg_height_sum += max_font_h;
switch (process_type) {
case ProcessType.CALC:
2018-01-22 18:21:29 +03:00
mfh += max_font_h;
2018-01-08 23:33:13 +03:00
width = double.max(width, leg_width_sum);
break;
}
}
break;
}
switch (process_type) {
case ProcessType.CALC:
height = leg_height_sum;
switch (position) {
2018-01-20 20:07:06 +03:00
case Position.TOP: chart.evarea.y0 += height; break;
case Position.BOTTOM: chart.evarea.y1 -= height; break;
case Position.LEFT: chart.evarea.x0 += width; break;
case Position.RIGHT: chart.evarea.x1 -= width; break;
2018-01-08 23:33:13 +03:00
}
break;
}
2018-01-22 18:21:29 +03:00
max_font_heights = mfh;
2018-01-08 23:33:13 +03:00
}
2017-08-28 14:47:31 +03:00
}
}