From b368afd56c97e518d6a27a194f3ac287f4555e18 Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Thu, 3 Mar 2022 00:08:21 +0900 Subject: [PATCH 01/12] [Chart-Serie: modify] Now, Serie is removable from Chart/Series. --- examples/live-chart.vala | 7 ++++++- src/chart.vala | 4 ++++ src/legend.vala | 7 ++++++- src/series.vala | 28 +++++++++++++++++++++++++--- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/examples/live-chart.vala b/examples/live-chart.vala index 07e073c..5244bdf 100644 --- a/examples/live-chart.vala +++ b/examples/live-chart.vala @@ -57,7 +57,12 @@ public class Example : Gtk.Window { heat.add(heat_value); return true; }); - + + Timeout.add(20000, () => { + chart.remove_serie(rss); + return false; + }); + var export_button = new Gtk.Button.with_label("Export to PNG"); export_button.clicked.connect (() => { try { diff --git a/src/chart.vala b/src/chart.vala index 822e0d8..2c35503 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -36,6 +36,10 @@ namespace LiveChart { this.series.register(serie); } + public void remove_serie(Serie serie){ + this.series.remove_serie(serie); + } + [Version (deprecated = true, deprecated_since = "1.7.0", replacement = "Retrieve the Serie from Chart.series (or from the serie you created) and add the value using serie.add")] public void add_value(Serie serie, double value) { serie.add(value); diff --git a/src/legend.vala b/src/legend.vala index ee4a88f..ab010af 100644 --- a/src/legend.vala +++ b/src/legend.vala @@ -25,7 +25,12 @@ namespace LiveChart { public void add_legend(Serie serie) { series.add(serie); } - + public void remove_legend(Serie serie){ + if(series.contains(serie)){ + series.remove(serie); + } + } + public abstract void draw(Context ctx, Config config); public BoundingBox get_bounding_box() { return bounding_box; diff --git a/src/series.vala b/src/series.vala index 1b01c7f..a53683c 100644 --- a/src/series.vala +++ b/src/series.vala @@ -2,7 +2,7 @@ using Gee; namespace LiveChart { public class Series : Object { - + private Gee.Map signals = new Gee.HashMap(); private Gee.ArrayList series = new Gee.ArrayList(); private Chart chart; @@ -11,14 +11,18 @@ namespace LiveChart { } public Serie register(Serie serie) { + if(signals.has_key(serie)){ + return serie; + } this.series.add(serie); //if values were added to serie before registration serie.get_values().foreach((value) => {chart.config.y_axis.update_bounds(value.value); return true;}); if(chart.legend != null) chart.legend.add_legend(serie); - serie.value_added.connect((value) => { + var sh = serie.value_added.connect((value) => { chart.config.y_axis.update_bounds(value); }); + signals[serie] = sh; return serie; } @@ -35,9 +39,27 @@ namespace LiveChart { } throw new ChartError.SERIE_NOT_FOUND("Serie with name %s not found".printf(name)); } - + + public void remove_serie(Serie serie){ + if(signals.has_key(serie) && series.contains(serie)){ + var sh = signals[serie]; + serie.disconnect(sh); + series.remove(serie); + signals.unset(serie); + } + if(chart.legend != null){ + chart.legend.remove_legend(serie); + } + } + public Iterator iterator() { return series.list_iterator(); } + + ~Series(){ + foreach(var entry in signals){ + entry.key.disconnect(entry.value); + } + } } } \ No newline at end of file From 32820ac65f91debb2b51761e2f7c8aaaa0e5dece Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Thu, 3 Mar 2022 00:10:26 +0900 Subject: [PATCH 02/12] [live-chart: modify] Safety for refresh-rate/Stop using anti-aliasing(for my own use) --- src/chart.vala | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/chart.vala b/src/chart.vala index 2c35503..64d9188 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -87,15 +87,18 @@ namespace LiveChart { public void refresh_every(int ms) { if (source_timeout != 0) { GLib.Source.remove(source_timeout); + source_timeout = 0; + } + if(ms > 0){ + source_timeout = Timeout.add(ms, () => { + this.queue_draw(); + return true; + }); } - source_timeout = Timeout.add(ms, () => { - this.queue_draw(); - return true; - }); } private bool render(Gtk.Widget _, Context ctx) { - + ctx.set_antialias(Cairo.Antialias.NONE); config.configure(ctx, legend); this.background.draw(ctx, config); From 020246d2d08281ffdad654188ed4afbcdbdc01cb Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Thu, 3 Mar 2022 22:36:28 +0900 Subject: [PATCH 03/12] [Chart: modify] - Add new function to remove all series from chart. --- src/chart.vala | 4 ++++ src/legend.vala | 3 +++ src/series.vala | 17 ++++++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/chart.vala b/src/chart.vala index 64d9188..a9fb773 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -40,6 +40,10 @@ namespace LiveChart { this.series.remove_serie(serie); } + public void remove_all_series(){ + this.series.remove_all(); + } + [Version (deprecated = true, deprecated_since = "1.7.0", replacement = "Retrieve the Serie from Chart.series (or from the serie you created) and add the value using serie.add")] public void add_value(Serie serie, double value) { serie.add(value); diff --git a/src/legend.vala b/src/legend.vala index ab010af..5ef00c0 100644 --- a/src/legend.vala +++ b/src/legend.vala @@ -30,6 +30,9 @@ namespace LiveChart { series.remove(serie); } } + public void remove_all_legend(){ + series.clear(); + } public abstract void draw(Context ctx, Config config); public BoundingBox get_bounding_box() { diff --git a/src/series.vala b/src/series.vala index a53683c..3b61949 100644 --- a/src/series.vala +++ b/src/series.vala @@ -47,9 +47,20 @@ namespace LiveChart { series.remove(serie); signals.unset(serie); } - if(chart.legend != null){ - chart.legend.remove_legend(serie); - } + if(chart.legend != null){ + chart.legend.remove_legend(serie); + } + } + + public void remove_all(){ + foreach(var entry in signals){ + entry.key.disconnect(entry.value); + } + signals.clear(); + series.clear(); + if(chart.legend != null){ + chart.legend.remove_all_legend(); + } } public Iterator iterator() { From 096522812c49612667d069741b772ee60a6e1e95 Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Thu, 3 Mar 2022 22:39:05 +0900 Subject: [PATCH 04/12] [Chart: fix] - Fix the issue causing memory leak on removing Chart from widget. -> Caused by circular reference between Chart and Series. --- src/chart.vala | 4 ++++ src/series.vala | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/chart.vala b/src/chart.vala index a9fb773..18c562a 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -30,6 +30,10 @@ namespace LiveChart { this.refresh_every(100); series = new Series(this); + this.destroy.connect(() => { + refresh_every(-1); + remove_all_series(); + }); } public void add_serie(Serie serie) { diff --git a/src/series.vala b/src/series.vala index 3b61949..3109e44 100644 --- a/src/series.vala +++ b/src/series.vala @@ -4,7 +4,7 @@ namespace LiveChart { public class Series : Object { private Gee.Map signals = new Gee.HashMap(); private Gee.ArrayList series = new Gee.ArrayList(); - private Chart chart; + private unowned Chart chart; public Series(Chart chart) { this.chart = chart; From 1882f91270b9bbd09a58faead718c86300ce88ec Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Sun, 6 Mar 2022 11:28:34 +0900 Subject: [PATCH 05/12] [LiveChart: experiment] - Make livechart rewindable. --- src/chart.vala | 7 ++++++- src/config.vala | 15 ++++++++++++++- src/grid.vala | 3 ++- src/points.vala | 3 ++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/chart.vala b/src/chart.vala index 18c562a..3e77b96 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -17,6 +17,7 @@ namespace LiveChart { public Series series; private uint source_timeout = 0; + private int64 play_rate = 0; public Chart(Config config = new Config()) { this.config = config; @@ -92,13 +93,17 @@ namespace LiveChart { pixbuff.savev(filename, "png", {}, {}); } - public void refresh_every(int ms) { + public void refresh_every(int ms, bool mod_play_rate = true) { + if(mod_play_rate){ + this.play_rate = (int64)ms; + } if (source_timeout != 0) { GLib.Source.remove(source_timeout); source_timeout = 0; } if(ms > 0){ source_timeout = Timeout.add(ms, () => { + config.time.current += this.play_rate; this.queue_draw(); return true; }); diff --git a/src/config.vala b/src/config.vala index c855686..d2ec572 100644 --- a/src/config.vala +++ b/src/config.vala @@ -38,6 +38,8 @@ namespace LiveChart { public int width; public int height; } + + public class Config { @@ -53,7 +55,18 @@ namespace LiveChart { public YAxis y_axis = new YAxis(); public XAxis x_axis = new XAxis(); - + + public struct TimeSeek { + int64 current; + int64 head_offset; + int64 tail_offset; + } + public TimeSeek time = { + GLib.get_real_time() / 1000, + 0, + 0 + }; + internal Gee.ArrayList categories; public Boundaries boundaries() { diff --git a/src/grid.vala b/src/grid.vala index 539d17f..05c3a47 100644 --- a/src/grid.vala +++ b/src/grid.vala @@ -67,7 +67,8 @@ namespace LiveChart { } protected void render_vgrid(Context ctx, Config config) { - var time = new DateTime.now().to_unix(); + // var time = new DateTime.now().to_unix(); + var time = config.time.current / 1000; for (double i = config.width - config.padding.right; i > config.padding.left; i -= config.x_axis.tick_length) { if (config.x_axis.lines.visible) { config.x_axis.lines.configure(ctx); diff --git a/src/points.vala b/src/points.vala index 0d4795d..0b48912 100644 --- a/src/points.vala +++ b/src/points.vala @@ -57,7 +57,8 @@ namespace LiveChart { Points points = new Points(); if (values.size > 0) { var last_value = values.last(); - points.realtime_delta = (((GLib.get_real_time() / 1000) - last_value.timestamp) * config.x_axis.get_ratio()) / 1000; + //points.realtime_delta = (((GLib.get_real_time() / 1000) - last_value.timestamp) * config.x_axis.get_ratio()) / 1000; + points.realtime_delta = ((config.time.current - last_value.timestamp) * config.x_axis.get_ratio()) / 1000; foreach (TimestampedValue value in values) { var point = Points.value_to_point(last_value, value, config, boundaries, points.realtime_delta); From d135c5767eddfa594c3fa8e2c318a66ed95808ce Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Sun, 6 Mar 2022 14:13:30 +0900 Subject: [PATCH 06/12] [dependency: examination] - Try adapting to Gtk4. (but may not be recommended) --- meson.build | 18 +++++++++++++++--- src/axis.vala | 8 ++++---- src/background.vala | 8 ++++---- src/chart.vala | 15 ++++++++++++--- src/font.vala | 2 +- src/grid.vala | 8 ++++---- src/legend.vala | 11 ++++++----- src/path.vala | 2 +- src/static/static_chart.vala | 10 +++++++++- src/static/static_grid.vala | 8 ++++---- 10 files changed, 60 insertions(+), 30 deletions(-) diff --git a/meson.build b/meson.build index 6a4a55e..0e74d6f 100644 --- a/meson.build +++ b/meson.build @@ -1,13 +1,25 @@ -project('live-chart', ['vala', 'c'], version: '1.9.1') +project('live-chart', ['vala', 'c'], version: '1.9.1-RO') cc = meson.get_compiler('c') libm = cc.find_library('m', required: true) -gtk = dependency('gtk+-3.0', version: '>= 3.22') +#setting up GEE gee = dependency('gee-0.8') - vala_args = ['--target-glib=2.50'] +#setting up gtk +gtk_major = 3 + +if gtk_major == 3 + gtk = dependency('gtk+-3.0', version: '>= 3.22') + vala_args += ['--define=GTK3'] +endif + +if gtk_major == 4 + gtk = dependency('gtk4') + vala_args += ['--define=GTK4'] +endif + if meson.version().version_compare('>= 0.47') if get_option('debug') == true vala_args += ['--ccode', '--debug'] diff --git a/src/axis.vala b/src/axis.vala index 7a4b6b8..85badaf 100644 --- a/src/axis.vala +++ b/src/axis.vala @@ -10,8 +10,8 @@ namespace LiveChart { public Path lines = new Path(); public XAxis() { - axis.color = {0.5, 0.5, 0.5, 0.5}; - lines.color = {0.5, 0.5, 0.5, 0.2}; + axis.color = {0.5f, 0.5f, 0.5f, 0.5f}; + lines.color = {0.5f, 0.5f, 0.5f, 0.2f}; } public double get_ratio() { @@ -51,8 +51,8 @@ namespace LiveChart { public YAxis(string unit = "") { this.unit = unit; ticks = get_ticks(); - axis.color = {0.5, 0.5, 0.5, 0.5}; - lines.color = {0.5, 0.5, 0.5, 0.2}; + axis.color = {0.5f, 0.5f, 0.5f, 0.5f}; + lines.color = {0.5f, 0.5f, 0.5f, 0.2f}; bounds.notify["upper"].connect(() => { this.ticks = get_ticks(); }); diff --git a/src/background.vala b/src/background.vala index 8bf0517..b485966 100644 --- a/src/background.vala +++ b/src/background.vala @@ -23,10 +23,10 @@ namespace LiveChart { [Version (deprecated = true, deprecated_since = "1.8.0", replacement = "Background.color")] public Gdk.RGBA main_color { get; set; default= Gdk.RGBA() { - red = 0.1, - green = 0.1, - blue = 0.1, - alpha = 1.0 + red = 0.1f, + green = 0.1f, + blue = 0.1f, + alpha = 1.0f }; } diff --git a/src/chart.vala b/src/chart.vala index 3e77b96..d0cab22 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -18,16 +18,23 @@ namespace LiveChart { private uint source_timeout = 0; private int64 play_rate = 0; - public Chart(Config config = new Config()) { this.config = config; + +#if GTK3 this.size_allocate.connect((allocation) => { this.config.height = allocation.height; this.config.width = allocation.width; }); - this.draw.connect(render); - +#endif +#if GTK4 + this.set_draw_func((_, ctx, width, height) => { + this.config.height = height; + this.config.width = width; + this.render(_, ctx); + }); +#endif this.refresh_every(100); series = new Series(this); @@ -85,12 +92,14 @@ namespace LiveChart { } public void to_png(string filename) throws Error { +#if GTK3 var window = this.get_window(); if (window == null) { throw new ChartError.EXPORT_ERROR("Chart is not realized yet"); } var pixbuff = Gdk.pixbuf_get_from_window(window, 0, 0, window.get_width(), window.get_height()); pixbuff.savev(filename, "png", {}, {}); +#endif } public void refresh_every(int ms, bool mod_play_rate = true) { diff --git a/src/font.vala b/src/font.vala index 3f6a382..71e5f9a 100644 --- a/src/font.vala +++ b/src/font.vala @@ -14,7 +14,7 @@ namespace LiveChart { face = "Sans serif"; slant = FontSlant.NORMAL; weight = FontWeight.NORMAL; - color = {0.4, 0.4, 0.4, 1.0}; + color = {0.4f, 0.4f, 0.4f, 1.0f}; } public void configure(Context ctx) { diff --git a/src/grid.vala b/src/grid.vala index 05c3a47..e75accb 100644 --- a/src/grid.vala +++ b/src/grid.vala @@ -14,10 +14,10 @@ namespace LiveChart { public bool visible { get; set; default = true; } public Gdk.RGBA main_color { get; set; default= Gdk.RGBA() { - red = 0.4, - green = 0.4, - blue = 0.4, - alpha = 1.0 + red = 0.4f, + green = 0.4f, + blue = 0.4f, + alpha = 1.0f }; } diff --git a/src/legend.vala b/src/legend.vala index 5ef00c0..d318524 100644 --- a/src/legend.vala +++ b/src/legend.vala @@ -15,11 +15,12 @@ namespace LiveChart { height=0 }; public Gdk.RGBA main_color { - get; set; default= Gdk.RGBA() { - red = 1.0, - green = 1.0, - blue = 1.0, - alpha = 1.0 + get; set; + default= Gdk.RGBA() { + red = 1.0f, + green = 1.0f, + blue = 1.0f, + alpha = 1.0f }; } public void add_legend(Serie serie) { diff --git a/src/path.vala b/src/path.vala index 87d0a58..2a0949e 100644 --- a/src/path.vala +++ b/src/path.vala @@ -16,7 +16,7 @@ namespace LiveChart { public Gdk.RGBA color { get; set; } public bool visible {get; set; } - public Path(double width = 0.5, Gdk.RGBA color = {1.0, 1.0, 1.0, 1.0}, bool visible = true, Dash? dash = null) { + public Path(double width = 0.5, Gdk.RGBA color = {1.0f, 1.0f, 1.0f, 1.0f}, bool visible = true, Dash? dash = null) { this.width = width; this.color = color; this.visible = true; diff --git a/src/static/static_chart.vala b/src/static/static_chart.vala index db87f94..88b03ce 100644 --- a/src/static/static_chart.vala +++ b/src/static/static_chart.vala @@ -15,12 +15,20 @@ namespace LiveChart.Static { public StaticChart(Config config = new Config()) { this.config = config; +#if GTK3 this.size_allocate.connect((allocation) => { this.config.height = allocation.height; this.config.width = allocation.width; }); - this.draw.connect(render); +#endif +#if GTK4 + this.set_draw_func((_, ctx, width, height) => { + this.config.height = height; + this.config.width = width; + this.render(_, ctx); + }); +#endif series = new StaticSeries(this); } diff --git a/src/static/static_grid.vala b/src/static/static_grid.vala index bef2a4c..94a354b 100644 --- a/src/static/static_grid.vala +++ b/src/static/static_grid.vala @@ -15,10 +15,10 @@ namespace LiveChart.Static { public bool visible { get; set; default = true; } public Gdk.RGBA main_color { get; set; default= Gdk.RGBA() { - red = 0.4, - green = 0.4, - blue = 0.4, - alpha = 1.0 + red = 0.4f, + green = 0.4f, + blue = 0.4f, + alpha = 1.0f }; } From f6bbf628caca1a3b9066c224b8a839319533399e Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Sun, 6 Mar 2022 14:34:32 +0900 Subject: [PATCH 07/12] [Chart: fix] - The issue delaying "the newest time" from real-time. --- src/chart.vala | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/chart.vala b/src/chart.vala index d0cab22..d485c94 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -17,7 +17,10 @@ namespace LiveChart { public Series series; private uint source_timeout = 0; - private int64 play_rate = 0; + private double play_ratio = 1.0; + + private int64 prev_time; + public Chart(Config config = new Config()) { this.config = config; @@ -29,11 +32,11 @@ namespace LiveChart { this.draw.connect(render); #endif #if GTK4 - this.set_draw_func((_, ctx, width, height) => { - this.config.height = height; - this.config.width = width; - this.render(_, ctx); - }); + this.set_draw_func((_, ctx, width, height) => { + this.config.height = height; + this.config.width = width; + this.render(_, ctx); + }); #endif this.refresh_every(100); @@ -102,17 +105,18 @@ namespace LiveChart { #endif } - public void refresh_every(int ms, bool mod_play_rate = true) { - if(mod_play_rate){ - this.play_rate = (int64)ms; - } + public void refresh_every(int ms, double play_ratio = 1.0) { + this.play_ratio = play_ratio; if (source_timeout != 0) { GLib.Source.remove(source_timeout); source_timeout = 0; } if(ms > 0){ + this.prev_time = GLib.get_real_time() / 1000; source_timeout = Timeout.add(ms, () => { - config.time.current += this.play_rate; + var now = GLib.get_real_time() / 1000; + config.time.current += (int64)((now - this.prev_time) * this.play_ratio); + this.prev_time = now; this.queue_draw(); return true; }); From 065da7a0d3bb978a9e404766912482fed224d28e Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Sun, 6 Mar 2022 14:44:31 +0900 Subject: [PATCH 08/12] [Chart: tweak] - Change time counting method to GLib.get_monotonic_time(). -> To avoid warping time-diff by NTP. --- src/chart.vala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chart.vala b/src/chart.vala index d485c94..affe9a4 100644 --- a/src/chart.vala +++ b/src/chart.vala @@ -112,9 +112,9 @@ namespace LiveChart { source_timeout = 0; } if(ms > 0){ - this.prev_time = GLib.get_real_time() / 1000; + this.prev_time = GLib.get_monotonic_time() / 1000; source_timeout = Timeout.add(ms, () => { - var now = GLib.get_real_time() / 1000; + var now = GLib.get_monotonic_time() / 1000; config.time.current += (int64)((now - this.prev_time) * this.play_ratio); this.prev_time = now; this.queue_draw(); From f9bc1f842ca82411594491801464eb3888bb7d73 Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Sun, 6 Mar 2022 23:36:35 +0900 Subject: [PATCH 09/12] [Points - Values: mod] Changed from List to TreeSet. - To reduce draw call by limiting the range efficiently(?) with using RBST. - I encountered a problem by pushing values with random timepoint on List. --- src/config.vala | 23 ++++++++++++++++++----- src/points.vala | 23 +++++++++++++++++++---- src/values.vala | 38 +++++++++++++++++++++++++++++++++----- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/config.vala b/src/config.vala index d2ec572..84b2095 100644 --- a/src/config.vala +++ b/src/config.vala @@ -42,9 +42,24 @@ namespace LiveChart { public class Config { - + private int _width = 0; public int width { - get; set; default = 0; + get{ + return _width; + } + set{ + if(_width != value){ + //i = config.width - config.padding.right; i > config.padding.left; i -= config.x_axis.tick_length + if(x_axis.tick_length <= 0.0){ + time.head_offset = -1.0; + } + else{ + var tmp = value / x_axis.tick_length; + time.head_offset = tmp * x_axis.tick_interval * 1000.0; + } + } + _width = value; + } } public int height { @@ -58,12 +73,10 @@ namespace LiveChart { public struct TimeSeek { int64 current; - int64 head_offset; - int64 tail_offset; + double head_offset; } public TimeSeek time = { GLib.get_real_time() / 1000, - 0, 0 }; diff --git a/src/points.vala b/src/points.vala index 0b48912..bc3f982 100644 --- a/src/points.vala +++ b/src/points.vala @@ -55,12 +55,27 @@ namespace LiveChart { var boundaries = config.boundaries(); Points points = new Points(); - if (values.size > 0) { - var last_value = values.last(); + if (values.size > 1) { + /// \note SortedSet.sub_set won't work as I expected correctly. + SortedSet renderee = null; + TimestampedValue border = {(double)config.time.current, 0.0}; + renderee = values.head_set(border); + + if(config.time.head_offset >= 0.0 && renderee.size > 0){ + border.timestamp -= config.time.head_offset; + if(renderee.first().timestamp < border.timestamp){ + renderee = renderee.tail_set(border); + } + } + + //var renderee = values; + if(renderee.size <= 2){ + return points; + } + var last_value = renderee.last(); //points.realtime_delta = (((GLib.get_real_time() / 1000) - last_value.timestamp) * config.x_axis.get_ratio()) / 1000; points.realtime_delta = ((config.time.current - last_value.timestamp) * config.x_axis.get_ratio()) / 1000; - - foreach (TimestampedValue value in values) { + foreach (TimestampedValue value in renderee) { var point = Points.value_to_point(last_value, value, config, boundaries, points.realtime_delta); points.add(point); } diff --git a/src/values.vala b/src/values.vala index f6faaa1..01bed5e 100644 --- a/src/values.vala +++ b/src/values.vala @@ -7,22 +7,50 @@ namespace LiveChart { public double value; } - public class Values : LinkedList { - + public class Values : TreeSet { public Bounds bounds { get; construct set; } private int buffer_size; - + + private static int cmp(TimestampedValue? a, TimestampedValue? b){ + double r = a.timestamp - b.timestamp; + if(r < 0.0){ + return -1; + } + if(r > 0.0){ + return 1; + } + return 0; + } public Values(int buffer_size = 1000) { + base(cmp); this.bounds = new Bounds(); this.buffer_size = buffer_size; } - +/* + public new TimestampedValue @get(int index){ + assert (index >= 0); + assert (index < buffer_size); + int i = 0; + TimestampedValue ret = {}; + this.foreach((v) => { + if(i == index){ + ret = v; + return false; + } + i++; + return true; + }); + return ret; + } + +*/ public new void add(TimestampedValue value) { if (this.size == buffer_size) { - this.remove_at(0); + //this.remove_at(0); + this.remove(this.first()); } bounds.update(value.value); base.add(value); From 5ecbe3655420150c82ce2ad1bc100f611d7bb939 Mon Sep 17 00:00:00 2001 From: Robert-Ordis Date: Mon, 7 Mar 2022 09:49:35 +0900 Subject: [PATCH 10/12] [test-code: commit] Forgot to commit --- tests/chart.vala | 39 ++++++++++++++++++++++++++++++++++----- tests/serie.vala | 4 ++-- tests/values.vala | 8 +++++--- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/tests/chart.vala b/tests/chart.vala index 8b94556..642b9a4 100644 --- a/tests/chart.vala +++ b/tests/chart.vala @@ -1,4 +1,19 @@ - +private LiveChart.TimestampedValue get_at(int index, LiveChart.Values values){ + assert(values.size < index); + assert(index >= 0); + + LiveChart.TimestampedValue ret = {}; + int i = 0; + + values.foreach((v) => { + if(i == index){ + ret = v; + return false; + } + return true; + }); + return ret; +} private void register_chart() { Test.add_func("/LiveChart/Chart/serie/add_value#should_update_bounds_when_adding_a_value", () => { @@ -88,13 +103,20 @@ private void register_chart() { //then assert(serie.get_values().size == 3); + /* assert(serie.get_values().get(0).value == 5); assert(serie.get_values().get(1).value == 10); assert(serie.get_values().get(2).value == 15); assert(serie.get_values().get(2).timestamp == now); assert(serie.get_values().get(1).timestamp == now - 5000); assert(serie.get_values().get(0).timestamp == now - 10000); - + */ + assert(get_at(0, serie.get_values()).value == 5); + assert(get_at(1, serie.get_values()).value == 10); + assert(get_at(2, serie.get_values()).value == 15); + assert(get_at(2, serie.get_values()).timestamp == now); + assert(get_at(1, serie.get_values()).timestamp == now - 5000); + assert(get_at(0, serie.get_values()).timestamp == now - 10000); assert(chart.config.y_axis.get_bounds().lower == 5); assert(chart.config.y_axis.get_bounds().upper == 15); }); @@ -115,7 +137,7 @@ private void register_chart() { //then assert(serie.get_values().size == 1); - assert(serie.get_values().get(0).value == 100); + assert(serie.get_values().first().value == 100); }); //Deprecated @@ -135,7 +157,7 @@ private void register_chart() { //then assert(serie.get_values().size == 1); - assert(serie.get_values().get(0).value == 100); + assert(serie.get_values().first().value == 100); }); Test.add_func("/LiveChart/Chart/add_unaware_timestamp_collection_by_index", () => { @@ -162,13 +184,20 @@ private void register_chart() { //then assert(serie.get_values().size == 3); +/* assert(serie.get_values().get(0).value == 5); assert(serie.get_values().get(1).value == 10); assert(serie.get_values().get(2).value == 15); assert(serie.get_values().get(2).timestamp == now); assert(serie.get_values().get(1).timestamp == now - 5000); assert(serie.get_values().get(0).timestamp == now - 10000); - +*/ + assert(get_at(0, serie.get_values()).value == 5); + assert(get_at(1, serie.get_values()).value == 10); + assert(get_at(2, serie.get_values()).value == 15); + assert(get_at(2, serie.get_values()).timestamp == now); + assert(get_at(1, serie.get_values()).timestamp == now - 5000); + assert(get_at(0, serie.get_values()).timestamp == now - 10000); assert(chart.config.y_axis.get_bounds().lower == 5); assert(chart.config.y_axis.get_bounds().upper == 15); }); diff --git a/tests/serie.vala b/tests/serie.vala index c32d89a..735438f 100644 --- a/tests/serie.vala +++ b/tests/serie.vala @@ -52,7 +52,7 @@ private void register_serie() { //then assert(serie.get_values().size == 1); - assert(serie.get_values().get(0).value == 100.0); - assert(serie.get_values().get(0).timestamp == 5); + assert(serie.get_values().first().value == 100.0); + assert(serie.get_values().first().timestamp == 5); }); } \ No newline at end of file diff --git a/tests/values.vala b/tests/values.vala index f9c0b18..2be1ddd 100644 --- a/tests/values.vala +++ b/tests/values.vala @@ -7,12 +7,14 @@ private void register_values() { //when values.add({0, 1}); - values.add({1, 10}); values.add({2, 100}); + values.add({1, 10}); //then assert(values.size == 2); - assert(values.get(0) == LiveChart.TimestampedValue(){timestamp = 1, value = 10}); - assert(values.get(1) == LiveChart.TimestampedValue(){timestamp = 2, value = 100}); + //assert(values.get(0) == LiveChart.TimestampedValue(){timestamp = 1, value = 10}); + //assert(values.get(1) == LiveChart.TimestampedValue(){timestamp = 2, value = 100}); + assert(values.first() == LiveChart.TimestampedValue(){timestamp = 1, value = 10}); + assert(values.last() == LiveChart.TimestampedValue(){timestamp = 2, value = 100}); }); } \ No newline at end of file From 03c963be1024dd140f813499d13c61e608994d64 Mon Sep 17 00:00:00 2001 From: Robert-Ordis Date: Sat, 19 Mar 2022 10:56:10 +0900 Subject: [PATCH 11/12] [Points: fix] Make test passable. --- src/points.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/points.vala b/src/points.vala index bc3f982..1847a57 100644 --- a/src/points.vala +++ b/src/points.vala @@ -58,7 +58,7 @@ namespace LiveChart { if (values.size > 1) { /// \note SortedSet.sub_set won't work as I expected correctly. SortedSet renderee = null; - TimestampedValue border = {(double)config.time.current, 0.0}; + TimestampedValue border = {(double)config.time.current + 1, 0.0}; renderee = values.head_set(border); if(config.time.head_offset >= 0.0 && renderee.size > 0){ From 35b69a42a455773f79f774e295e18a30a2a8a4ac Mon Sep 17 00:00:00 2001 From: Robert_Ordis Date: Wed, 7 Dec 2022 17:44:03 +0900 Subject: [PATCH 12/12] Update README.md Caution of memory leak. --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index d815531..7895031 100644 --- a/README.md +++ b/README.md @@ -662,6 +662,24 @@ chart.add_unaware_timestamp_collection_by_index(0, unaware_timestamp_collection, Et voilĂ  ! +## CAUTIONS + +### Removing LiveChart.Chart from Gtk.Widget + +Removing LiveChart.Chart from Gtk.Widget without stopping auto-refresh causes memory leak. + +```vala +var window = new Gtk.Window(); +var chart = new LiveChart.Chart(); +window.add(chart); + +//... +chart.refresh_every(-1); //Don't forget to stop auto-refresh if your app replaces the LiveChart.Chart widget. +window.remove(chart); + +``` + + ## How LiveChart versions works ? * For each new feature, the `minor` version number will be bumped