From 4db4b9fa811313bc022071098b8b09717144fd28 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Fri, 7 Feb 2025 01:50:22 +0200 Subject: [PATCH] allow dropping sample files --- src/app.zig | 40 ++++++++++++++++++++++++- src/main.zig | 4 +-- src/ui.zig | 83 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 96 insertions(+), 31 deletions(-) diff --git a/src/app.zig b/src/app.zig index 65f9c78..245e527 100644 --- a/src/app.zig +++ b/src/app.zig @@ -536,11 +536,38 @@ fn showChannelsWindow(self: *App) !void { const scroll_area = self.ui.pushScrollbar(self.ui.newKeyFromString("Channels")); defer self.ui.popScrollbar(); scroll_area.layout_axis = .Y; - //scroll_area.layout_gap = 16; + scroll_area.layout_gap = 16; for (self.channel_views.slice()) |*channel_view| { try self.showChannelView(channel_view); } + + { + const prompt_box = self.ui.newBoxFromString("Add prompt"); + prompt_box.layout_axis = .X; + prompt_box.size.x = UI.Size.percent(1, 0); + prompt_box.size.y = UI.Size.pixels(150, 1); + self.ui.pushParent(prompt_box); + defer self.ui.popParent(); + + self.ui.spacer(.{ .x = UI.Size.percent(1, 0) }); + + const from_file_button = self.ui.button(.text, "Add from file"); + from_file_button.background = srcery.green; + if (self.ui.signalFromBox(from_file_button).clicked()) { + log.debug("TODO: Not implemented", .{}); + } + + self.ui.spacer(.{ .x = UI.Size.pixels(32, 1) }); + + const from_device_button = self.ui.button(.text, "Add from device"); + from_device_button.background = srcery.green; + if (self.ui.signalFromBox(from_device_button).clicked()) { + log.debug("TODO: Not implemented", .{}); + } + + self.ui.spacer(.{ .x = UI.Size.percent(1, 0) }); + } } fn findChannelIndexByName(haystack: []const [:0]const u8, needle: [:0]const u8) ?usize { @@ -785,6 +812,17 @@ pub fn tick(self: *App) !void { Platform.toggleConsoleWindow(); } + if (rl.isFileDropped()) { + const file_list = rl.loadDroppedFiles(); + defer rl.unloadDroppedFiles(file_list); + + for (file_list.paths[0..file_list.count]) |path| { + const path_len = std.mem.indexOfSentinel(u8, 0, path); + try self.appendChannelFromFile(path[0..path_len]); + } + } + + // On the first frame, render the UI twice. // So that on the second pass widgets that depend on sizes from other widgets have settled if (self.ui.frame_index == 0) { diff --git a/src/main.zig b/src/main.zig index 98d3de7..f89dfe3 100644 --- a/src/main.zig +++ b/src/main.zig @@ -154,8 +154,8 @@ pub fn main() !void { if (builtin.mode == .Debug) { try app.appendChannelFromDevice("Dev1/ai0"); - try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin"); - try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin"); + // try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin"); + // try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin"); } var profiler: ?Profiler = null; diff --git a/src/ui.zig b/src/ui.zig index d9bac54..5c7e461 100644 --- a/src/ui.zig +++ b/src/ui.zig @@ -13,7 +13,7 @@ const clamp = std.math.clamp; const UI = @This(); const debug = false; -const max_boxes = 128; +const max_boxes = 512; const max_events = 256; const RectFormatted = struct { @@ -93,8 +93,8 @@ pub const Size = struct { }; pub const Vec2Size = struct { - x: Size, - y: Size, + x: Size = Size.pixels(0, 1), + y: Size = Size.pixels(0, 1), pub fn zero() Vec2Size { return Vec2Size{ @@ -460,19 +460,20 @@ pub fn begin(self: *UI) void { const mouse = rl.getMousePosition(); self.mouse_delta = mouse.subtract(self.mouse); - const active_box_flags = self.getActiveBoxFlags(); - if (active_box_flags.contains(.draggable_x)) { - rl.setMousePosition( - @mod(rl.getMouseX(), window_width), - rl.getMouseY() - ); - } - if (active_box_flags.contains(.draggable_y)) { - rl.setMousePosition( - rl.getMouseX(), - @mod(rl.getMouseY(), window_height) - ); - } + // TODO: Maybe add a flag to enable this for active box + // const active_box_flags = self.getActiveBoxFlags(); + // if (active_box_flags.contains(.draggable_x)) { + // rl.setMousePosition( + // @mod(rl.getMouseX(), window_width), + // rl.getMouseY() + // ); + // } + // if (active_box_flags.contains(.draggable_y)) { + // rl.setMousePosition( + // rl.getMouseX(), + // @mod(rl.getMouseY(), window_height) + // ); + // } { var i: usize = 0; @@ -893,6 +894,7 @@ fn calcLayoutEnforceConstraints(self: *UI, box: *Box, axis: Axis) void { if (box.layout_axis == axis) { const max_sum_children_size = getVec2Axis(&box.persistent.size, axis).*; var sum_children_size: f32 = 0; + var child_count: f32 = 0; var children_fixups: std.BoundedArray(f32, max_boxes) = .{}; var children_fixup_sum: f32 = 0; @@ -910,9 +912,13 @@ fn calcLayoutEnforceConstraints(self: *UI, box: *Box, axis: Axis) void { const child_fixup = child_size_axis * (1 - child_semantic_size_axis.strictness); children_fixups.appendAssumeCapacity(child_fixup); children_fixup_sum += child_fixup; + + child_count += 1; } } + sum_children_size += @max(child_count - 1, 0 ) * box.layout_gap; + const overflow = sum_children_size - max_sum_children_size; if (overflow > 0) { const overflow_percent = std.math.clamp(overflow / children_fixup_sum, 0, 1); @@ -960,19 +966,22 @@ pub fn newBoxFromPtr(self: *UI, ptr: anytype) *Box { } pub fn newBox(self: *UI, key: Key) *Box { - assert(key.hash != 0); - var box: *Box = undefined; - var box_index: BoxIndex = undefined; + var box_index: ?BoxIndex = null; var persistent: Box.Persistent = .{}; - if (self.findBoxIndexByKey(key)) |found_box_index| { - const found_box = &self.boxes.buffer[found_box_index]; - assert(found_box.last_used_frame < self.frame_index); - persistent = found_box.persistent; - box = found_box; - box_index = found_box_index; - } else { + if (!key.isNil()) { + if (self.findBoxIndexByKey(key)) |found_box_index| { + const found_box = &self.boxes.buffer[found_box_index]; + assert(found_box.last_used_frame < self.frame_index); + + persistent = found_box.persistent; + box = found_box; + box_index = found_box_index; + } + } + + if (box_index == null) { box = self.boxes.addOneAssumeCapacity(); box_index = self.boxes.len - 1; } @@ -983,7 +992,7 @@ pub fn newBox(self: *UI, key: Key) *Box { .last_used_frame = self.frame_index, .persistent = persistent, - .index = box_index + .index = box_index.? }; if (self.getParentIndex()) |parent_index| { @@ -1021,6 +1030,10 @@ fn findBoxByKey(self: *UI, key: Key) ?*Box { } pub fn signalFromBox(self: *UI, box: *Box) Signal { + if (box.key.isNil()) { + return Signal{}; + } + var result = Signal{}; var rect = box.computedRect(); @@ -1172,7 +1185,6 @@ pub fn frameArena(self: *UI) *std.heap.ArenaAllocator { return &self.arenas[@mod(self.frame_index, 2)]; } - pub fn pushScrollbar(self: *UI, key: UI.Key) *Box { const container = self.newBox(key); container.layout_axis = .X; @@ -1250,4 +1262,19 @@ pub fn popScrollbar(self: *UI) void { sroll_offset.* = clamp(sroll_offset.*, 0, 1); self.popParent(); // pop container +} + +pub fn button(self: *UI, font: Assets.FontId, text: []const u8) *Box { + const box = self.newBoxFromString(text); + box.flags.insert(.clickable); + box.size.x = UI.Size.text(1, 1); + box.size.y = UI.Size.text(0.5, 1); + box.setText(font, text); + + return box; +} + +pub fn spacer(self: *UI, size: Vec2Size) void { + const box = self.newBox(UI.Key.initNil()); + box.size = size; } \ No newline at end of file