add following of started collection

This commit is contained in:
Rokas Puzonas 2025-03-16 14:21:25 +02:00
parent d8867cb3d6
commit 25377c8b4f
5 changed files with 72 additions and 11 deletions

View File

@ -62,6 +62,7 @@ pub const ChannelView = struct {
y_range: RangeF64, y_range: RangeF64,
sample_rate: ?f64 = null, sample_rate: ?f64 = null,
unit: ?NIDaq.Unit = null, unit: ?NIDaq.Unit = null,
follow: bool = false,
source: union(enum) { source: union(enum) {
file: usize, file: usize,
@ -338,6 +339,7 @@ pub fn startDeviceChannelReading(self: *App, channel_view: *ChannelView) void {
}; };
device_channel.active_task = task; device_channel.active_task = task;
channel_view.follow = true;
} }
pub fn appendChannelFromFile(self: *App, path: []const u8) !void { pub fn appendChannelFromFile(self: *App, path: []const u8) !void {

View File

@ -27,19 +27,24 @@ pub const ViewOptions = struct {
}; };
pub const Cache = struct { pub const Cache = struct {
const Key = struct {
options: ViewOptions,
drawn_x_range: RangeF64
};
texture: ?rl.RenderTexture2D = null, texture: ?rl.RenderTexture2D = null,
options: ?ViewOptions = null, key: ?Key = null,
pub fn deinit(self: *Cache) void { pub fn deinit(self: *Cache) void {
if (self.texture) |texture| { if (self.texture) |texture| {
texture.unload(); texture.unload();
self.texture = null; self.texture = null;
} }
self.options = null; self.key = null;
} }
pub fn invalidate(self: *Cache) void { pub fn invalidate(self: *Cache) void {
self.options = null; self.key = null;
} }
pub fn draw(self: Cache, rect: rl.Rectangle) void { pub fn draw(self: Cache, rect: rl.Rectangle) void {
@ -178,7 +183,7 @@ pub fn drawCached(cache: *Cache, render_size: Vec2, options: ViewOptions, sample
if (texure.width != render_width or texure.height != render_height) { if (texure.width != render_width or texure.height != render_height) {
render_texture.unload(); render_texture.unload();
cache.texture = null; cache.texture = null;
cache.options = null; cache.key = null;
} }
} }
@ -191,12 +196,17 @@ pub fn drawCached(cache: *Cache, render_size: Vec2, options: ViewOptions, sample
const render_texture = cache.texture.?; const render_texture = cache.texture.?;
if (cache.options != null and std.meta.eql(cache.options.?, options)) { const cache_key = Cache.Key{
.options = options,
.drawn_x_range = RangeF64.init(0, @max(@as(f64, @floatFromInt(samples.len)) - 1, 0)).intersectPositive(options.x_range)
};
if (cache.key != null and std.meta.eql(cache.key.?, cache_key)) {
// Cached graph hasn't changed, no need to redraw. // Cached graph hasn't changed, no need to redraw.
return; return;
} }
cache.options = options; cache.key = cache_key;
render_texture.begin(); render_texture.begin();
defer render_texture.end(); defer render_texture.end();

View File

@ -74,7 +74,6 @@ fn readAnalog(task_pool: *TaskPool, entry: *Entry, timeout: f64) !void {
task_pool.mutex.lock(); task_pool.mutex.lock();
defer task_pool.mutex.unlock(); defer task_pool.mutex.unlock();
if (entry.sampling.sample_count) |sample_count| { if (entry.sampling.sample_count) |sample_count| {
try entry.samples.ensureTotalCapacity(sample_count); try entry.samples.ensureTotalCapacity(sample_count);
} else { } else {

View File

@ -76,6 +76,7 @@ fn pushChannelMoveCommand(self: *MainScreen, channel_view: *ChannelView, x_range
view_rect.x_range = x_range; view_rect.x_range = x_range;
view_rect.y_range = y_range; view_rect.y_range = y_range;
channel_view.follow = false;
} }
fn pushChannelMoveCommandAxis(self: *MainScreen, channel_view: *ChannelView, axis: UI.Axis, view_range: RangeF64) void { fn pushChannelMoveCommandAxis(self: *MainScreen, channel_view: *ChannelView, axis: UI.Axis, view_range: RangeF64) void {
@ -100,6 +101,8 @@ fn showChannelViewGraph(self: *MainScreen, channel_view: *ChannelView) *UI.Box {
.size_y = UI.Sizing.initGrowFull(), .size_y = UI.Sizing.initGrowFull(),
.background = srcery.black, .background = srcery.black,
.flags = &.{ .clickable, .draggable, .scrollable }, .flags = &.{ .clickable, .draggable, .scrollable },
.align_x = .center,
.align_y = .center,
}); });
graph_box.beginChildren(); graph_box.beginChildren();
defer graph_box.endChildren(); defer graph_box.endChildren();
@ -154,6 +157,15 @@ fn showChannelViewGraph(self: *MainScreen, channel_view: *ChannelView) *UI.Box {
graph_box.texture = texture.texture; graph_box.texture = texture.texture;
} }
if (view_rect.x_range.size() == 0 or view_rect.y_range.size() == 0) {
graph_box.setText("<Empty>");
graph_box.text_color = srcery.hard_black;
graph_box.font = .{
.variant = .bold_italic,
.size = ui.rem(3)
};
}
return graph_box; return graph_box;
} }
@ -513,6 +525,8 @@ fn showRuler(self: *MainScreen, ruler: *UI.Box, graph_box: *UI.Box, channel_view
fn showChannelView(self: *MainScreen, channel_view: *ChannelView, height: UI.Sizing) !void { fn showChannelView(self: *MainScreen, channel_view: *ChannelView, height: UI.Sizing) !void {
var ui = &self.app.ui; var ui = &self.app.ui;
const show_ruler = true;
const channel_view_box = ui.createBox(.{ const channel_view_box = ui.createBox(.{
.key = UI.Key.initPtr(channel_view), .key = UI.Key.initPtr(channel_view),
.layout_direction = .top_to_bottom, .layout_direction = .top_to_bottom,
@ -522,7 +536,34 @@ fn showChannelView(self: *MainScreen, channel_view: *ChannelView, height: UI.Siz
channel_view_box.beginChildren(); channel_view_box.beginChildren();
defer channel_view_box.endChildren(); defer channel_view_box.endChildren();
const show_ruler = true; const toolbar = ui.createBox(.{
.layout_direction = .left_to_right,
.layout_gap = 16,
.background = srcery.hard_black,
.size_x = UI.Sizing.initGrowFull(),
.size_y = UI.Sizing.initFixed(.{ .pixels = ui.rem(2) })
});
{
toolbar.beginChildren();
defer toolbar.endChildren();
if (self.app.getChannelSourceDevice(channel_view)) |device_channel| {
_ = device_channel;
const follow = ui.button("Follow");
follow.background = srcery.hard_black;
if (channel_view.follow) {
follow.borders = UI.Borders.bottom(.{
.color = srcery.green,
.size = 4
});
}
if (ui.signal(follow).clicked()) {
channel_view.follow = !channel_view.follow;
}
}
}
if (!show_ruler) { if (!show_ruler) {
_ = self.showChannelViewGraph(channel_view); _ = self.showChannelViewGraph(channel_view);
@ -645,16 +686,18 @@ pub fn tick(self: *MainScreen) !void {
if (self.app.started_collecting) { if (self.app.started_collecting) {
for (self.app.listChannelViews()) |*channel_view| { for (self.app.listChannelViews()) |*channel_view| {
const device_channel = self.app.getChannelSourceDevice(channel_view) orelse continue; const device_channel = self.app.getChannelSourceDevice(channel_view) orelse continue;
if (!channel_view.follow) continue;
const sample_rate = device_channel.active_task.?.sampling.sample_rate; const sample_rate = device_channel.active_task.?.sampling.sample_rate;
const samples = device_channel.samples.items; const sample_count: f32 = @floatFromInt(device_channel.samples.items.len);
const sample_count: f32 = @floatFromInt(samples.len);
channel_view.view_rect.y_range = channel_view.y_range;
channel_view.view_rect.x_range.lower = 0; channel_view.view_rect.x_range.lower = 0;
if (sample_count > channel_view.view_rect.x_range.upper) { if (sample_count > channel_view.view_rect.x_range.upper) {
channel_view.view_rect.x_range.upper = sample_count + @as(f32, @floatCast(sample_rate)) * 10; channel_view.view_rect.x_range.upper = sample_count + @as(f32, @floatCast(sample_rate)) * 10;
} }
channel_view.view_cache.invalidate(); // channel_view.view_cache.invalidate();
} }
} }
@ -665,6 +708,7 @@ pub fn tick(self: *MainScreen) !void {
const scroll_area = ui.beginScrollbar(ui.keyFromString("Channels")); const scroll_area = ui.beginScrollbar(ui.keyFromString("Channels"));
defer ui.endScrollbar(); defer ui.endScrollbar();
scroll_area.layout_direction = .top_to_bottom; scroll_area.layout_direction = .top_to_bottom;
scroll_area.layout_gap = 4;
for (self.app.listChannelViews()) |*channel_view| { for (self.app.listChannelViews()) |*channel_view| {
try self.showChannelView(channel_view, UI.Sizing.initFixed(.{ .pixels = channel_view.height })); try self.showChannelView(channel_view, UI.Sizing.initFixed(.{ .pixels = channel_view.height }));

View File

@ -420,6 +420,12 @@ pub const Borders = struct {
.right = border, .right = border,
}; };
} }
pub fn bottom(border: Border) Borders {
return Borders{
.bottom = border,
};
}
}; };
const BoxIndex = std.math.IntFittingRange(0, max_boxes); const BoxIndex = std.math.IntFittingRange(0, max_boxes);