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

View File

@ -27,19 +27,24 @@ pub const ViewOptions = struct {
};
pub const Cache = struct {
const Key = struct {
options: ViewOptions,
drawn_x_range: RangeF64
};
texture: ?rl.RenderTexture2D = null,
options: ?ViewOptions = null,
key: ?Key = null,
pub fn deinit(self: *Cache) void {
if (self.texture) |texture| {
texture.unload();
self.texture = null;
}
self.options = null;
self.key = null;
}
pub fn invalidate(self: *Cache) void {
self.options = null;
self.key = null;
}
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) {
render_texture.unload();
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.?;
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.
return;
}
cache.options = options;
cache.key = cache_key;
render_texture.begin();
defer render_texture.end();

View File

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

View File

@ -76,6 +76,7 @@ fn pushChannelMoveCommand(self: *MainScreen, channel_view: *ChannelView, x_range
view_rect.x_range = x_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 {
@ -100,6 +101,8 @@ fn showChannelViewGraph(self: *MainScreen, channel_view: *ChannelView) *UI.Box {
.size_y = UI.Sizing.initGrowFull(),
.background = srcery.black,
.flags = &.{ .clickable, .draggable, .scrollable },
.align_x = .center,
.align_y = .center,
});
graph_box.beginChildren();
defer graph_box.endChildren();
@ -154,6 +157,15 @@ fn showChannelViewGraph(self: *MainScreen, channel_view: *ChannelView) *UI.Box {
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;
}
@ -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 {
var ui = &self.app.ui;
const show_ruler = true;
const channel_view_box = ui.createBox(.{
.key = UI.Key.initPtr(channel_view),
.layout_direction = .top_to_bottom,
@ -522,7 +536,34 @@ fn showChannelView(self: *MainScreen, channel_view: *ChannelView, height: UI.Siz
channel_view_box.beginChildren();
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) {
_ = self.showChannelViewGraph(channel_view);
@ -645,16 +686,18 @@ pub fn tick(self: *MainScreen) !void {
if (self.app.started_collecting) {
for (self.app.listChannelViews()) |*channel_view| {
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 samples = device_channel.samples.items;
const sample_count: f32 = @floatFromInt(samples.len);
const sample_count: f32 = @floatFromInt(device_channel.samples.items.len);
channel_view.view_rect.y_range = channel_view.y_range;
channel_view.view_rect.x_range.lower = 0;
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_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"));
defer ui.endScrollbar();
scroll_area.layout_direction = .top_to_bottom;
scroll_area.layout_gap = 4;
for (self.app.listChannelViews()) |*channel_view| {
try self.showChannelView(channel_view, UI.Sizing.initFixed(.{ .pixels = channel_view.height }));

View File

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