add basic markers to the sides of a channel view
This commit is contained in:
parent
e33ab321d0
commit
a6a66d99fd
504
src/app.zig
504
src/app.zig
@ -8,9 +8,10 @@ const Graph = @import("./graph.zig");
|
||||
const NIDaq = @import("ni-daq/root.zig");
|
||||
const rect_utils = @import("./rect-utils.zig");
|
||||
const TaskPool = @import("ni-daq/task-pool.zig");
|
||||
const utils = @import("./utils.zig");
|
||||
|
||||
const remap = @import("./utils.zig").remap;
|
||||
const lerpColor = @import("./utils.zig").lerpColor;
|
||||
const remap = utils.remap;
|
||||
const lerpColor = utils.lerpColor;
|
||||
const log = std.log.scoped(.app);
|
||||
const assert = std.debug.assert;
|
||||
const clamp = std.math.clamp;
|
||||
@ -53,7 +54,7 @@ const ChannelView = struct {
|
||||
view_rect: Graph.ViewOptions,
|
||||
follow: bool = false,
|
||||
|
||||
height: f32 = 200,
|
||||
height: f32 = 300,
|
||||
|
||||
default_from: f32,
|
||||
default_to: f32,
|
||||
@ -498,7 +499,7 @@ fn showChannelViewSlider(self: *App, view_rect: *Graph.ViewOptions, sample_count
|
||||
));
|
||||
}
|
||||
|
||||
fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
||||
fn showChannelViewGraph(self: *App, channel_view: *ChannelView) !void {
|
||||
const source = self.getChannelSource(channel_view) orelse return;
|
||||
const samples = source.samples();
|
||||
source.lockSamples();
|
||||
@ -506,11 +507,218 @@ fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
||||
|
||||
var channel_rect_opts: *Graph.ViewOptions = &channel_view.view_rect;
|
||||
|
||||
const graph_box = self.ui.newBoxFromString("Graph");
|
||||
graph_box.flags.insert(.clickable);
|
||||
graph_box.flags.insert(.draggable);
|
||||
graph_box.background = srcery.black;
|
||||
graph_box.size.x = UI.Size.percent(1, 0);
|
||||
graph_box.size.y = UI.Size.pixels(channel_view.height, 1);
|
||||
self.ui.pushParent(graph_box);
|
||||
defer self.ui.popParent();
|
||||
|
||||
const graph_rect = graph_box.computedRect();
|
||||
|
||||
const signal = self.ui.signalFromBox(graph_box);
|
||||
|
||||
var axis = UI.Axis.X;
|
||||
var zooming: bool = false;
|
||||
var start_sample: ?f64 = null;
|
||||
var stop_sample: ?f64 = null;
|
||||
|
||||
if (signal.hot) {
|
||||
if (signal.shift_modifier) {
|
||||
axis = UI.Axis.Y;
|
||||
} else {
|
||||
axis = UI.Axis.X;
|
||||
}
|
||||
|
||||
if (self.graph_start_sample) |graph_start_sample| {
|
||||
axis = graph_start_sample.axis;
|
||||
zooming = true;
|
||||
}
|
||||
|
||||
var mouse_sample: f64 = undefined;
|
||||
if (axis == .X) {
|
||||
const mouse_sample_index = channel_rect_opts.mapSampleXToIndex(0, graph_rect.width, signal.relative_mouse.x);
|
||||
mouse_sample = mouse_sample_index;
|
||||
} else if (axis == .Y) {
|
||||
const mouse_sample_value = channel_rect_opts.mapSampleYToValue(0, graph_rect.height, signal.relative_mouse.y);
|
||||
mouse_sample = mouse_sample_value;
|
||||
}
|
||||
|
||||
start_sample = mouse_sample;
|
||||
|
||||
if (signal.flags.contains(.right_pressed)) {
|
||||
self.graph_start_sample = .{
|
||||
.value = mouse_sample,
|
||||
.axis = axis
|
||||
};
|
||||
}
|
||||
|
||||
if (self.graph_start_sample) |graph_start_sample| {
|
||||
start_sample = graph_start_sample.value;
|
||||
stop_sample = mouse_sample;
|
||||
zooming = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (zooming) {
|
||||
if (axis == .X) {
|
||||
graph_box.active_cursor = .mouse_cursor_resize_ew;
|
||||
} else {
|
||||
graph_box.active_cursor = .mouse_cursor_resize_ns;
|
||||
}
|
||||
|
||||
if (signal.flags.contains(.right_released)) {
|
||||
self.graph_start_sample = null;
|
||||
|
||||
if (start_sample != null and stop_sample != null) {
|
||||
const lower_sample: f64 = @min(start_sample.?, stop_sample.?);
|
||||
const higher_sample: f64 = @max(start_sample.?, stop_sample.?);
|
||||
|
||||
if (axis == .X) {
|
||||
if (higher_sample - lower_sample > 1) {
|
||||
channel_rect_opts.from = @floatCast(lower_sample);
|
||||
channel_rect_opts.to = @floatCast(higher_sample);
|
||||
} else {
|
||||
// TODO: Show error message that selected range is too small
|
||||
}
|
||||
} else if (axis == .Y) {
|
||||
if (higher_sample - lower_sample > 0.001) {
|
||||
channel_rect_opts.min_value = lower_sample;
|
||||
channel_rect_opts.max_value = higher_sample;
|
||||
} else {
|
||||
// TODO: Show error message that selected range is too small
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start_sample = null;
|
||||
stop_sample = null;
|
||||
}
|
||||
|
||||
if (start_sample != null and stop_sample != null) {
|
||||
|
||||
const fill = self.ui.newBox(UI.Key.initNil());
|
||||
fill.background = srcery.green.alpha(0.5);
|
||||
|
||||
if (axis == .X) {
|
||||
const start_x = channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, start_sample.?);
|
||||
const stop_x = channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, stop_sample.?);
|
||||
|
||||
fill.setFixedRect(.{
|
||||
.x = @floatCast(@min(start_x, stop_x)),
|
||||
.y = graph_rect.y,
|
||||
.width = @floatCast(@abs(start_x - stop_x)),
|
||||
.height = graph_rect.height
|
||||
});
|
||||
} else if (axis == .Y) {
|
||||
const start_y = channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, start_sample.?);
|
||||
const stop_y = channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, stop_sample.?);
|
||||
|
||||
fill.setFixedRect(.{
|
||||
.x = graph_rect.x,
|
||||
.y = @floatCast(@min(start_y, stop_y)),
|
||||
.width = graph_rect.width,
|
||||
.height = @floatCast(@abs(start_y - stop_y)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (start_sample) |sample| {
|
||||
const marker = self.ui.newBox(UI.Key.initNil());
|
||||
marker.background = srcery.green;
|
||||
|
||||
if (axis == .X) {
|
||||
const value = samples[@intFromFloat(sample)];
|
||||
marker.setFmtText(.text, "{d:0.2} | {d:0.6}", .{sample, value});
|
||||
marker.setFixedRect(UI.Rect{
|
||||
.x = @floatCast(channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, sample)),
|
||||
.y = graph_rect.y,
|
||||
.width = 1,
|
||||
.height = graph_rect.height
|
||||
});
|
||||
|
||||
} else if (axis == .Y) {
|
||||
marker.setFmtText(.text, "{d:0.2}", .{sample});
|
||||
marker.setFixedRect(UI.Rect{
|
||||
.x = graph_rect.x,
|
||||
.y = @floatCast(channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, sample)),
|
||||
.width = graph_rect.width,
|
||||
.height = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (stop_sample) |sample| {
|
||||
const marker = self.ui.newBox(UI.Key.initNil());
|
||||
marker.background = srcery.green;
|
||||
|
||||
marker.setFmtText(.text, "{d:0.2}", .{sample});
|
||||
if (axis == .X) {
|
||||
marker.setFixedRect(.{
|
||||
.x = @floatCast(channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, sample)),
|
||||
.y = graph_rect.y,
|
||||
.width = 1,
|
||||
.height = graph_rect.height
|
||||
});
|
||||
} else if (axis == .Y) {
|
||||
marker.setFixedRect(.{
|
||||
.x = graph_rect.x,
|
||||
.y = @floatCast(channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, sample)),
|
||||
.width = graph_rect.width,
|
||||
.height = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (signal.dragged()) {
|
||||
const middle_mouse_drag = signal.flags.contains(.middle_dragging);
|
||||
var x_offset: f64 = 0;
|
||||
var y_offset: f64 = 0;
|
||||
|
||||
if (signal.shift_modifier or middle_mouse_drag) {
|
||||
y_offset = remap(
|
||||
f64,
|
||||
0, graph_rect.height,
|
||||
0, channel_rect_opts.max_value - channel_rect_opts.min_value,
|
||||
signal.drag.y
|
||||
);
|
||||
}
|
||||
|
||||
if (!signal.shift_modifier or middle_mouse_drag) {
|
||||
x_offset = remap(
|
||||
f64,
|
||||
0, graph_rect.width,
|
||||
0, channel_rect_opts.to - channel_rect_opts.from,
|
||||
signal.drag.x
|
||||
);
|
||||
}
|
||||
|
||||
channel_rect_opts.from -= @floatCast(x_offset);
|
||||
channel_rect_opts.to -= @floatCast(x_offset);
|
||||
channel_rect_opts.max_value += @floatCast(y_offset);
|
||||
channel_rect_opts.min_value += @floatCast(y_offset);
|
||||
}
|
||||
}
|
||||
|
||||
Graph.drawCached(&channel_view.view_cache, graph_box.persistent.size, channel_rect_opts.*, samples);
|
||||
if (channel_view.view_cache.texture) |texture| {
|
||||
graph_box.texture = texture.texture;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
||||
const source = self.getChannelSource(channel_view) orelse return;
|
||||
|
||||
var channel_rect_opts: *Graph.ViewOptions = &channel_view.view_rect;
|
||||
|
||||
const channel_box = self.ui.newBoxFromPtr(channel_view);
|
||||
channel_box.background = rl.Color.blue;
|
||||
channel_box.layout_axis = .Y;
|
||||
channel_box.size.x = UI.Size.percent(1, 0);
|
||||
channel_box.size.y = UI.Size.childrenSum(1);
|
||||
channel_box.size.y = UI.Size.pixels(channel_view.height, 1);
|
||||
self.ui.pushParent(channel_box);
|
||||
defer self.ui.popParent();
|
||||
|
||||
@ -589,207 +797,127 @@ fn showChannelView(self: *App, channel_view: *ChannelView) !void {
|
||||
}
|
||||
}
|
||||
|
||||
// const channel_box = self.ui.newBox(UI.Key.initNil());
|
||||
// channel_box.layout_axis = .Y;
|
||||
// channel_box.size.x = UI.Size.percent(1, 0);
|
||||
// channel_box.size.y = UI.Size.childrenSum(1);
|
||||
// self.ui.pushParent(channel_box);
|
||||
// defer self.ui.popParent();
|
||||
|
||||
var y_axis_markers: *UI.Box = undefined;
|
||||
var x_axis_markers: *UI.Box = undefined;
|
||||
|
||||
{
|
||||
const graph_box = self.ui.newBoxFromString("Graph");
|
||||
graph_box.flags.insert(.clickable);
|
||||
graph_box.flags.insert(.draggable);
|
||||
graph_box.background = srcery.black;
|
||||
graph_box.size.x = UI.Size.percent(1, 0);
|
||||
graph_box.size.y = UI.Size.pixels(channel_view.height, 1);
|
||||
self.ui.pushParent(graph_box);
|
||||
const y_axis_container = self.ui.newBox(UI.Key.initNil());
|
||||
y_axis_container.layout_axis = .X;
|
||||
y_axis_container.size.x = UI.Size.percent(1, 0);
|
||||
y_axis_container.size.y = UI.Size.percent(1, 0);
|
||||
self.ui.pushParent(y_axis_container);
|
||||
defer self.ui.popParent();
|
||||
|
||||
const graph_rect = graph_box.computedRect();
|
||||
y_axis_markers = self.ui.newBoxFromString("Y axis markers");
|
||||
y_axis_markers.background = rl.Color.blue;
|
||||
y_axis_markers.size.x = UI.Size.pixels(64, 1);
|
||||
y_axis_markers.size.y = UI.Size.percent(1, 0);
|
||||
|
||||
const signal = self.ui.signalFromBox(graph_box);
|
||||
try self.showChannelViewGraph(channel_view);
|
||||
}
|
||||
|
||||
var axis = UI.Axis.X;
|
||||
var zooming: bool = false;
|
||||
var start_sample: ?f64 = null;
|
||||
var stop_sample: ?f64 = null;
|
||||
|
||||
if (signal.hot) {
|
||||
if (signal.shift_modifier) {
|
||||
axis = UI.Axis.Y;
|
||||
} else {
|
||||
axis = UI.Axis.X;
|
||||
}
|
||||
{
|
||||
const horizontal_container = self.ui.newBox(UI.Key.initNil());
|
||||
horizontal_container.layout_axis = .X;
|
||||
horizontal_container.size.x = UI.Size.childrenSum(0);
|
||||
horizontal_container.size.y = UI.Size.childrenSum(1);
|
||||
self.ui.pushParent(horizontal_container);
|
||||
defer self.ui.popParent();
|
||||
|
||||
if (self.graph_start_sample) |graph_start_sample| {
|
||||
axis = graph_start_sample.axis;
|
||||
zooming = true;
|
||||
}
|
||||
const fullscreen_button = self.ui.newBoxFromString("Fullscreen");
|
||||
fullscreen_button.background = rl.Color.red;
|
||||
fullscreen_button.size.x = UI.Size.pixels(y_axis_markers.computedRect().width, 1);
|
||||
fullscreen_button.size.y = UI.Size.pixels(32, 1);
|
||||
|
||||
var mouse_sample: f64 = undefined;
|
||||
if (axis == .X) {
|
||||
const mouse_sample_index = channel_rect_opts.mapSampleXToIndex(0, graph_rect.width, signal.relative_mouse.x);
|
||||
mouse_sample = mouse_sample_index;
|
||||
} else if (axis == .Y) {
|
||||
const mouse_sample_value = channel_rect_opts.mapSampleYToValue(0, graph_rect.height, signal.relative_mouse.y);
|
||||
mouse_sample = mouse_sample_value;
|
||||
}
|
||||
x_axis_markers = self.ui.newBoxFromString("X axis markers");
|
||||
x_axis_markers.background = rl.Color.pink;
|
||||
x_axis_markers.size.x = UI.Size.percent(1, 0);
|
||||
x_axis_markers.size.y = UI.Size.pixels(32, 1);
|
||||
self.ui.pushParent(x_axis_markers);
|
||||
defer self.ui.popParent();
|
||||
}
|
||||
|
||||
start_sample = mouse_sample;
|
||||
{
|
||||
self.ui.pushParent(y_axis_markers);
|
||||
defer self.ui.popParent();
|
||||
|
||||
if (signal.flags.contains(.right_pressed)) {
|
||||
self.graph_start_sample = .{
|
||||
.value = mouse_sample,
|
||||
.axis = axis
|
||||
};
|
||||
}
|
||||
const y_axis_rect = y_axis_markers.computedRect();
|
||||
|
||||
if (self.graph_start_sample) |graph_start_sample| {
|
||||
start_sample = graph_start_sample.value;
|
||||
stop_sample = mouse_sample;
|
||||
zooming = true;
|
||||
}
|
||||
}
|
||||
const min_gap_between_markers = 8;
|
||||
|
||||
if (zooming) {
|
||||
if (axis == .X) {
|
||||
graph_box.active_cursor = .mouse_cursor_resize_ew;
|
||||
} else {
|
||||
graph_box.active_cursor = .mouse_cursor_resize_ns;
|
||||
}
|
||||
const y_range = channel_rect_opts.max_value - channel_rect_opts.min_value;
|
||||
|
||||
if (signal.flags.contains(.right_released)) {
|
||||
self.graph_start_sample = null;
|
||||
var axis_marker_size = min_gap_between_markers / y_axis_rect.height * y_range;
|
||||
axis_marker_size = @ceil(axis_marker_size);
|
||||
|
||||
if (start_sample != null and stop_sample != null) {
|
||||
const lower_sample: f64 = @min(start_sample.?, stop_sample.?);
|
||||
const higher_sample: f64 = @max(start_sample.?, stop_sample.?);
|
||||
var marker = utils.roundNearestUp(f64, @max(channel_rect_opts.min_value, channel_view.default_min_value), axis_marker_size);
|
||||
while (marker < @min(channel_rect_opts.max_value, channel_view.default_max_value)) : (marker += axis_marker_size) {
|
||||
const marker_box = self.ui.newBox(UI.Key.initNil());
|
||||
marker_box.background = rl.Color.yellow;
|
||||
marker_box.setFixedRect(.{
|
||||
.width = y_axis_rect.width/5,
|
||||
.height = 1,
|
||||
.x = y_axis_rect.x + y_axis_rect.width/5*4,
|
||||
.y = @floatCast(remap(
|
||||
f64,
|
||||
channel_rect_opts.max_value, channel_rect_opts.min_value,
|
||||
y_axis_rect.y, y_axis_rect.y + y_axis_rect.height,
|
||||
marker
|
||||
))
|
||||
});
|
||||
|
||||
if (axis == .X) {
|
||||
if (higher_sample - lower_sample > 1) {
|
||||
channel_rect_opts.from = @floatCast(lower_sample);
|
||||
channel_rect_opts.to = @floatCast(higher_sample);
|
||||
} else {
|
||||
// TODO: Show error message that selected range is too small
|
||||
}
|
||||
} else if (axis == .Y) {
|
||||
if (higher_sample - lower_sample > 0.01) {
|
||||
channel_rect_opts.min_value = lower_sample;
|
||||
channel_rect_opts.max_value = higher_sample;
|
||||
} else {
|
||||
// TODO: Show error message that selected range is too small
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start_sample = null;
|
||||
stop_sample = null;
|
||||
}
|
||||
|
||||
if (start_sample != null and stop_sample != null) {
|
||||
|
||||
const fill = self.ui.newBox(UI.Key.initNil());
|
||||
fill.background = srcery.green.alpha(0.5);
|
||||
|
||||
if (axis == .X) {
|
||||
const start_x = channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, start_sample.?);
|
||||
const stop_x = channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, stop_sample.?);
|
||||
|
||||
fill.setFixedRect(.{
|
||||
.x = @floatCast(@min(start_x, stop_x)),
|
||||
.y = graph_rect.y,
|
||||
.width = @floatCast(@abs(start_x - stop_x)),
|
||||
.height = graph_rect.height
|
||||
});
|
||||
} else if (axis == .Y) {
|
||||
const start_y = channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, start_sample.?);
|
||||
const stop_y = channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, stop_sample.?);
|
||||
|
||||
fill.setFixedRect(.{
|
||||
.x = graph_rect.x,
|
||||
.y = @floatCast(@min(start_y, stop_y)),
|
||||
.width = graph_rect.width,
|
||||
.height = @floatCast(@abs(start_y - stop_y)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (start_sample) |sample| {
|
||||
const marker = self.ui.newBox(UI.Key.initNil());
|
||||
marker.background = srcery.green;
|
||||
|
||||
if (axis == .X) {
|
||||
const value = samples[@intFromFloat(sample)];
|
||||
marker.setFmtText(.text, "{d:0.2} | {d:0.6}", .{sample, value});
|
||||
marker.setFixedRect(UI.Rect{
|
||||
.x = @floatCast(channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, sample)),
|
||||
.y = graph_rect.y,
|
||||
.width = 1,
|
||||
.height = graph_rect.height
|
||||
});
|
||||
|
||||
} else if (axis == .Y) {
|
||||
marker.setFmtText(.text, "{d:0.2}", .{sample});
|
||||
marker.setFixedRect(UI.Rect{
|
||||
.x = graph_rect.x,
|
||||
.y = @floatCast(channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, sample)),
|
||||
.width = graph_rect.width,
|
||||
.height = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (stop_sample) |sample| {
|
||||
const marker = self.ui.newBox(UI.Key.initNil());
|
||||
marker.background = srcery.green;
|
||||
|
||||
marker.setFmtText(.text, "{d:0.2}", .{sample});
|
||||
if (axis == .X) {
|
||||
marker.setFixedRect(.{
|
||||
.x = @floatCast(channel_rect_opts.mapSampleIndexToX(graph_rect.x, graph_rect.width, sample)),
|
||||
.y = graph_rect.y,
|
||||
.width = 1,
|
||||
.height = graph_rect.height
|
||||
});
|
||||
} else if (axis == .Y) {
|
||||
marker.setFixedRect(.{
|
||||
.x = graph_rect.x,
|
||||
.y = @floatCast(channel_rect_opts.mapSampleValueToY(graph_rect.y, graph_rect.height, sample)),
|
||||
.width = graph_rect.width,
|
||||
.height = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (signal.dragged()) {
|
||||
if (signal.shift_modifier) {
|
||||
const drag_offset = remap(
|
||||
f64,
|
||||
0, graph_rect.height,
|
||||
0, channel_rect_opts.max_value - channel_rect_opts.min_value,
|
||||
signal.drag.y
|
||||
);
|
||||
|
||||
channel_rect_opts.max_value += @floatCast(drag_offset);
|
||||
channel_rect_opts.min_value += @floatCast(drag_offset);
|
||||
} else {
|
||||
const drag_offset = remap(
|
||||
f64,
|
||||
0, graph_rect.width,
|
||||
0, channel_rect_opts.to - channel_rect_opts.from,
|
||||
signal.drag.x
|
||||
);
|
||||
|
||||
channel_rect_opts.from -= @floatCast(drag_offset);
|
||||
channel_rect_opts.to -= @floatCast(drag_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Graph.drawCached(&channel_view.view_cache, graph_box.persistent.size, channel_rect_opts.*, samples);
|
||||
if (channel_view.view_cache.texture) |texture| {
|
||||
graph_box.texture = texture.texture;
|
||||
const label_box = self.ui.newBox(UI.Key.initNil());
|
||||
label_box.setFmtText(.text, "{d:.03}", .{marker});
|
||||
label_box.size.x = UI.Size.text(0, 1);
|
||||
label_box.size.y = UI.Size.text(0, 1);
|
||||
label_box.flags.insert(.text_left_align);
|
||||
label_box.setFixedRect(.{
|
||||
.width = y_axis_rect.width,
|
||||
.height = 1,
|
||||
.x = y_axis_rect.x,
|
||||
.y = @floatCast(remap(
|
||||
f64,
|
||||
channel_rect_opts.max_value, channel_rect_opts.min_value,
|
||||
y_axis_rect.y, y_axis_rect.y + y_axis_rect.height,
|
||||
marker
|
||||
))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.showChannelViewSlider(
|
||||
&channel_view.view_rect,
|
||||
@floatFromInt(samples.len)
|
||||
);
|
||||
{
|
||||
self.ui.pushParent(x_axis_markers);
|
||||
defer self.ui.popParent();
|
||||
|
||||
const y_axis_rect = x_axis_markers.computedRect();
|
||||
|
||||
const axis_marker_size = 100000;
|
||||
|
||||
var marker = utils.roundNearestUp(f64, @max(channel_rect_opts.from, channel_view.default_from), axis_marker_size);
|
||||
while (marker < @min(channel_rect_opts.to, channel_view.default_to)) : (marker += axis_marker_size) {
|
||||
const marker_box = self.ui.newBox(UI.Key.initNil());
|
||||
marker_box.background = rl.Color.yellow;
|
||||
marker_box.setFixedRect(.{
|
||||
.width = 1,
|
||||
.height = y_axis_rect.height/2,
|
||||
.x = @floatCast(remap(
|
||||
f64,
|
||||
channel_rect_opts.from, channel_rect_opts.to,
|
||||
y_axis_rect.x, y_axis_rect.x + y_axis_rect.width,
|
||||
marker
|
||||
)),
|
||||
.y = y_axis_rect.y,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn showChannelsWindow(self: *App) !void {
|
||||
|
@ -158,7 +158,7 @@ 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_IjStim.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_IjStim.bin");
|
||||
}
|
||||
|
23
src/ui.zig
23
src/ui.zig
@ -16,7 +16,7 @@ const clamp = std.math.clamp;
|
||||
const UI = @This();
|
||||
|
||||
const debug = false;
|
||||
const max_boxes = 512;
|
||||
const max_boxes = 5120;
|
||||
const max_events = 256;
|
||||
|
||||
const RectFormatted = struct {
|
||||
@ -176,15 +176,19 @@ pub const Event = union(enum) {
|
||||
pub const Signal = struct {
|
||||
pub const Flag = enum {
|
||||
left_pressed,
|
||||
middle_pressed,
|
||||
right_pressed,
|
||||
|
||||
left_released,
|
||||
middle_released,
|
||||
right_released,
|
||||
|
||||
left_clicked,
|
||||
middle_clicked,
|
||||
right_clicked,
|
||||
|
||||
left_dragging,
|
||||
middle_dragging,
|
||||
right_dragging,
|
||||
|
||||
scrolled
|
||||
@ -199,11 +203,11 @@ pub const Signal = struct {
|
||||
shift_modifier: bool = false,
|
||||
|
||||
pub fn clicked(self: Signal) bool {
|
||||
return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked);
|
||||
return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked) or self.flags.contains(.middle_clicked);
|
||||
}
|
||||
|
||||
pub fn dragged(self: Signal) bool {
|
||||
return self.flags.contains(.left_dragging) or self.flags.contains(.right_dragging);
|
||||
return self.flags.contains(.left_dragging) or self.flags.contains(.right_dragging) or self.flags.contains(.middle_dragging);
|
||||
}
|
||||
|
||||
pub fn scrolled(self: Signal) bool {
|
||||
@ -215,6 +219,8 @@ pub const Signal = struct {
|
||||
self.flags.insert(.left_pressed);
|
||||
} else if (mouse_button == .mouse_button_right) {
|
||||
self.flags.insert(.right_pressed);
|
||||
} else if (mouse_button == .mouse_button_middle) {
|
||||
self.flags.insert(.middle_pressed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,6 +229,8 @@ pub const Signal = struct {
|
||||
self.flags.insert(.left_released);
|
||||
} else if (mouse_button == .mouse_button_right) {
|
||||
self.flags.insert(.right_released);
|
||||
} else if (mouse_button == .mouse_button_middle) {
|
||||
self.flags.insert(.middle_released);
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,6 +239,8 @@ pub const Signal = struct {
|
||||
self.flags.insert(.left_clicked);
|
||||
} else if (mouse_button == .mouse_button_right) {
|
||||
self.flags.insert(.right_clicked);
|
||||
} else if (mouse_button == .mouse_button_middle) {
|
||||
self.flags.insert(.middle_clicked);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +249,8 @@ pub const Signal = struct {
|
||||
self.flags.insert(.left_dragging);
|
||||
} else if (mouse_button == .mouse_button_right) {
|
||||
self.flags.insert(.right_dragging);
|
||||
} else if (mouse_button == .mouse_button_middle) {
|
||||
self.flags.insert(.middle_dragging);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -856,8 +868,6 @@ fn drawBox(self: *UI, box: *Box) void {
|
||||
text_rect.y += (box_rect.height - text_size.y) / 2;
|
||||
}
|
||||
|
||||
// text_rect.y += box.persistent.active * text_rect.height*0.1;
|
||||
|
||||
const text_color = utils.shiftColorInHSV(text.color, value_shift);
|
||||
font.drawText(text.content, .{ .x = text_rect.x, .y = text_rect.y }, text_color);
|
||||
|
||||
@ -1387,7 +1397,8 @@ pub fn signalFromBox(self: *UI, box: *Box) Signal {
|
||||
}
|
||||
|
||||
if (draggable and self.mouse_delta.equals(Vec2.zero()) == 0) {
|
||||
inline for (.{ rl.MouseButton.mouse_button_left, rl.MouseButton.mouse_button_right }) |mouse_button| {
|
||||
const mouse_buttons = [_]rl.MouseButton{ .mouse_button_left, .mouse_button_right, .mouse_button_middle };
|
||||
inline for (mouse_buttons) |mouse_button| {
|
||||
const active_box = self.active_box_keys.get(mouse_button);
|
||||
|
||||
if (active_box != null and active_box.?.eql(key)) {
|
||||
|
@ -53,3 +53,11 @@ pub fn remap(comptime T: type, from_min: T, from_max: T, to_min: T, to_max: T, v
|
||||
const t = (value - from_min) / (from_max - from_min);
|
||||
return std.math.lerp(to_min, to_max, t);
|
||||
}
|
||||
|
||||
pub fn roundNearestUp(comptime T: type, value: T, multiple: T) T {
|
||||
return @ceil(value / multiple) * multiple;
|
||||
}
|
||||
|
||||
pub fn roundNearestDown(comptime T: type, value: T, multiple: T) T {
|
||||
return @floor(value / multiple) * multiple;
|
||||
}
|
Loading…
Reference in New Issue
Block a user