Skip to content

Commit

Permalink
Rest
Browse files Browse the repository at this point in the history
  • Loading branch information
lcallarec committed Oct 15, 2022
1 parent fa099bd commit 5bb985d
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 34 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -589,15 +589,19 @@ Both `from` and `to` are standards Gdk.RGBA() structs.

## Legend

### Visibility
**Visibility**

```vala
var chart = new LiveChart.Chart(config);
chart.legend.visible = false; // Hide legend
```

### Fonts
**Symbols**



**Fonts**

```vala
var chart = new LiveChart.Chart(config);
Expand Down
1 change: 1 addition & 0 deletions examples/basic.vala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class Basic {
config.x_axis.lines.visible = false;

var chart = new Chart(config);
chart.legend.symbol = {width: 8, height: 8, radius: 4};

chart.add_serie(heat);
chart.add_serie(heap);
Expand Down
1 change: 1 addition & 0 deletions examples/fixed-max.vala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class FixedMax {
config.y_axis.fixed_max = cap(96);

var chart = new Chart(config);
chart.legend.symbol = {width: 15, height: 10, radius: 3};
chart.grid.gradient = {from: {0.2, 0.1, 0.1, 1}, to: {0.12, 0.12, 0.12, 1}};

var export_button = new Gtk.Button.with_label("Export to PNG");
Expand Down
8 changes: 6 additions & 2 deletions examples/hide-parts.vala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class HideParts {
var chart = new Chart(config);
chart.legend.visible = false;
chart.grid.visible = false;

chart.background.visible = false;
chart.add_serie(cpu);

var cpu_value = 50.0;
Expand Down Expand Up @@ -43,6 +43,10 @@ public class HideParts {
widget.pack_start(row2, true, true, 5);

row1.pack_start(new Gtk.Label("All parts may be hidden"), false, false, 5);
row2.pack_start(chart, true, true, 0);
var b = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
b.get_style_context().add_class("circular");
b.pack_start(chart, true, true, 0);

row2.pack_start(b, true, true, 0);
}
}
34 changes: 34 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,37 @@ deps = [
subdir('src')
subdir('tests')
subdir('examples')

if get_option('docs') == true
valadoc = find_program('valadoc')
doc_cmd_base = [valadoc,
'--package-name=livechart',
'--package-version=' + meson.project_version(),
'--target-glib=2.50',
'--force',
'--pkg=gtk+-3.0',
'--pkg=glib-2.0',
'--pkg=gobject-2.0',
'--pkg=gee-0.8',
'--directory=@OUTPUT@',
'@INPUT@'
]

gtkdoc_cmd = [doc_cmd_base,
'--doclet=gtkdoc',
'--doclet-arg=' + (meson.current_build_dir() / 'src' / 'livechart.h')
]
custom_target('gtkdoc',
command: gtkdoc_cmd,
input: sources,
output: 'gtkdoc',
depends: livechart_lib
)

custom_target('valadoc',
command: doc_cmd_base,
input: sources,
output: 'valadoc',
depends: livechart_lib
)
endif
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
option('docs', type: 'boolean', value: false, description: 'Build the documentation')
80 changes: 57 additions & 23 deletions src/legend.vala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace LiveChart {

public bool visible { get; set; default = true; }
public Labels labels = new Labels();
public LegendSymbol symbol = LegendSymbol();

protected Gee.ArrayList<Seriable> series = new Gee.ArrayList<Seriable>();
protected BoundingBox bounding_box = BoundingBox() {
Expand All @@ -26,19 +27,21 @@ namespace LiveChart {
}
}

public enum LegendSymbolType {
QUADRILATERAL,
CIRCLE
public struct LegendSymbol {
public double width;
public double height;
public double radius;
public LegendSymbol() {
width = 15;
height = 10;
radius = 0;
}
}

public class HorizontalLegend : Legend {

public LegendSymbolType symbol_type { get; set; default = LegendSymbolType.QUADRILATERAL; }
public uint8 symbol_width { get; set; default = 10; }
public uint8 symbol_height { get; set; default = 10; }

private double needed_height = 10;

private LegendSymbolDrawer symbol_drawer = new LegendSymbolDrawer();
public override double get_needed_height() {
return needed_height;
}
Expand All @@ -50,30 +53,23 @@ namespace LiveChart {

labels.font.configure(ctx);
TextExtents size = name_extents("A", ctx);
needed_height = double.max(size.height, symbol_height) * 2;
needed_height = double.max(size.height, symbol.height) * 2;

var x_labels_height = config.x_axis.get_labels_needed_size().height;
var base_y = boundaries.y.max + x_labels_height;
var pos = 0;
var pos = 0.0;
series.foreach((serie) => {
labels.font.configure(ctx);
TextExtents extents = name_extents(serie.name, ctx);
ctx.move_to(
boundaries.x.min + pos + symbol_width + 2,
boundaries.x.min + pos + symbol.width + 2,
base_y + (needed_height - size.height) / 2 + size.height
);
ctx.show_text(serie.name);

ctx.set_source_rgba(serie.line.color.red, serie.line.color.green, serie.line.color.blue, 1);
ctx.rectangle(
boundaries.x.min + pos,
base_y + (needed_height - symbol_height) / 2,
symbol_width,
symbol_height
);
ctx.fill();

pos += symbol_width + (int) extents.width + 20;

symbol_drawer.draw(ctx, {boundaries.x.min + pos, base_y + (needed_height - symbol.height) / 2}, symbol, serie.line.color);

pos += symbol.width + extents.width + 20;

return true;
});
Expand All @@ -90,7 +86,7 @@ namespace LiveChart {
return name_extents;
}

private void update_bounding_box(Config config, int width) {
private void update_bounding_box(Config config, double width) {
var boundaries = config.boundaries();
this.bounding_box = BoundingBox() {
x=boundaries.x.min,
Expand All @@ -113,4 +109,42 @@ namespace LiveChart {
public override void draw(Context ctx, Config config) {}
public override double get_needed_height() {return 0;}
}

public class LegendSymbolDrawer {
public void draw(Context ctx, Coordinate at, LegendSymbol symbol, Gdk.RGBA color) {

ctx.set_source_rgba(color.red, color.green, color.blue, color.alpha);
if (symbol.radius > 0) {
Coordinate p1 = {at.x, at.y + symbol.radius};
ctx.move_to(p1.x, p1.y);
//top-left corner
ctx.curve_to(p1.x, p1.y, at.x, at.y, at.x + symbol.radius, at.y);
//top line
Coordinate p2 = {at.x + symbol.width - symbol.radius, at.y};
ctx.line_to(p2.x, p2.y);
//top-right corner
ctx.curve_to(p2.x, p2.y, at.x + symbol.width, at.y, at.x + symbol.width, at.y + symbol.radius);
//right line
Coordinate p3 = {at.x + symbol.width, at.y + symbol.height - symbol.radius};
ctx.line_to(p3.x, p3.y);
//bottom-right corner
ctx.curve_to(p3.x, p3.y, at.x + symbol.width, at.y + symbol.height, at.x + symbol.width - symbol.radius, at.y + symbol.height);
//bottom line
Coordinate p4 = {at.x + symbol.radius, at.y + symbol.height};
ctx.line_to(p4.x, p4.y);
//bottom-left corner
ctx.curve_to(p4.x, p4.y, at.x, at.y + symbol.height, at.x, at.y + symbol.height - symbol.radius);
//left line
ctx.line_to(p1.x, p1.y);
} else {
ctx.rectangle(
at.x,
at.y,
symbol.width,
symbol.height
);
}
ctx.fill();
}
}
}
4 changes: 2 additions & 2 deletions tests/bar.vala
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ private void register_experimental_bar() {

// Test.add_func("/LiveChart/BarSerie/draw#gradient", () => {
// //Given
// var WIDTH = 10;
// var HEIGHT = 10;
// var WIDTH = 100;
// var HEIGHT = 100;
// Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, WIDTH, HEIGHT);
// Cairo.Context context = new Cairo.Context(surface);
// context.set_antialias(Cairo.Antialias.NONE);
Expand Down
91 changes: 86 additions & 5 deletions tests/legend.vala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
private void register_legend() {
Test.add_func("/LiveChart/Legend#draw", () => {
Test.add_func("/LiveChart/Legend/draw", () => {
//Given
var WIDTH = 50;
var HEIGHT = 50;
Expand All @@ -8,7 +8,7 @@ private void register_legend() {
cairo_background(context, {0.0, 0.0, 0.0, 1.0 }, WIDTH, HEIGHT);

var legend = new LiveChart.HorizontalLegend();
var serie = new LiveChart.Serie("TEST", new LiveChart.Line());;
var serie = new LiveChart.Serie("TEST", new LiveChart.Line());
legend.add_legend(serie);

//When
Expand Down Expand Up @@ -42,7 +42,7 @@ private void register_legend() {
}
});

Test.add_func("/LiveChart/Legend#draw_hidden", () => {
Test.add_func("/LiveChart/Legend/draw_hidden", () => {
//Given
var WIDTH = 50;
var HEIGHT = 50;
Expand All @@ -51,7 +51,7 @@ private void register_legend() {
cairo_background(context, {0.0, 0.0, 0.0, 1.0 }, WIDTH, HEIGHT);

var legend = new LiveChart.HorizontalLegend();
var serie = new LiveChart.Serie("TEST", new LiveChart.Line());;
var serie = new LiveChart.Serie("TEST", new LiveChart.Line());
legend.add_legend(serie);
legend.visible = false;

Expand Down Expand Up @@ -82,5 +82,86 @@ private void register_legend() {
} else {
assert_not_reached();
}
});
});

Test.add_func("/LiveChart/LegendSymbolDrawer/draw#rectangle", () => {
//Given
var WIDTH = 10;
var HEIGHT = 10;
Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, WIDTH, HEIGHT);
Cairo.Context context = new Cairo.Context(surface);
context.set_antialias(Cairo.Antialias.NONE);
cairo_background(context, {0.0, 0.0, 0.0, 1.0 }, WIDTH, HEIGHT);

var drawer = new LiveChart.LegendSymbolDrawer();
drawer.draw(context, {x: 0, y: 0}, {width: 10, height: 10, radius: 0}, red());

//then
var pixbuff = Gdk.pixbuf_get_from_surface(surface, 0, 0, WIDTH, HEIGHT);
if (pixbuff != null) {
var at = color_at(pixbuff);
assert(at(0, 0).to_string() == "rgb(255,0,0)");
assert(at(9, 9).to_string() == "rgb(255,0,0)");
} else {
assert_not_reached();
}
});

Test.add_func("/LiveChart/LegendSymbolDrawer/draw#rounded_rectangle", () => {
//Given
var WIDTH = 20;
var HEIGHT = 20;
Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, WIDTH, HEIGHT);
Cairo.Context context = new Cairo.Context(surface);
context.set_antialias(Cairo.Antialias.NONE);
cairo_background(context, {0.0, 0.0, 0.0, 1.0 }, WIDTH, HEIGHT);

var drawer = new LiveChart.LegendSymbolDrawer();
drawer.draw(context, {x: 0, y: 0}, {width: 20, height: 20, radius: 5}, red());

//then
var pixbuff = Gdk.pixbuf_get_from_surface(surface, 0, 0, WIDTH, HEIGHT);
if (pixbuff != null) {
var at = color_at(pixbuff);
assert(at(0, 0).to_string() == "rgb(0,0,0)");
assert(at(19, 0).to_string() == "rgb(0,0,0)");
assert(at(0, 19).to_string() == "rgb(0,0,0)");
assert(at(19, 19).to_string() == "rgb(0,0,0)");

assert(at(5, 0).to_string() == "rgb(255,0,0)");
assert(at(5, 5).to_string() == "rgb(255,0,0)");
assert(at(0, 5).to_string() == "rgb(255,0,0)");
} else {
assert_not_reached();
}
});

Test.add_func("/LiveChart/LegendSymbolDrawer/draw#circle", () => {
//Given
var WIDTH = 10;
var HEIGHT = 10;
Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, WIDTH, HEIGHT);
Cairo.Context context = new Cairo.Context(surface);
context.set_antialias(Cairo.Antialias.NONE);
cairo_background(context, {0.0, 0.0, 0.0, 1.0 }, WIDTH, HEIGHT);

var drawer = new LiveChart.LegendSymbolDrawer();
drawer.draw(context, {x: 0, y: 0}, {width: 10, height: 10, radius: 5}, red());

//then
var pixbuff = Gdk.pixbuf_get_from_surface(surface, 0, 0, WIDTH, HEIGHT);
if (pixbuff != null) {
var at = color_at(pixbuff);
assert(at(0, 0).to_string() == "rgb(0,0,0)");
assert(at(9, 0).to_string() == "rgb(0,0,0)");
assert(at(0, 9).to_string() == "rgb(0,0,0)");
assert(at(9, 9).to_string() == "rgb(0,0,0)");

assert(at(5, 0).to_string() == "rgb(255,0,0)");
assert(at(5, 5).to_string() == "rgb(255,0,0)");
assert(at(0, 5).to_string() == "rgb(255,0,0)");
} else {
assert_not_reached();
}
});
}

0 comments on commit 5bb985d

Please sign in to comment.