Compare commits
10 Commits
fdf6001068
...
be0d0f6bb1
Author | SHA1 | Date | |
---|---|---|---|
be0d0f6bb1 | |||
aa63dab79a | |||
d49dc387fb | |||
0c237eb053 | |||
6adf0b9423 | |||
0edeaefbf0 | |||
eafafbab89 | |||
1428d3d9bf | |||
7de55bde54 | |||
ecea2b513a |
@ -19,6 +19,10 @@
|
|||||||
.url = "git+https://github.com/lassade/profiler.zig.git#d066d066c36c4eebd494babf15c1cdbd2d512b12",
|
.url = "git+https://github.com/lassade/profiler.zig.git#d066d066c36c4eebd494babf15c1cdbd2d512b12",
|
||||||
.hash = "122097461acc2064f5f89b85d76d2a02232579864b17604617a333789c892f2d262f",
|
.hash = "122097461acc2064f5f89b85d76d2a02232579864b17604617a333789c892f2d262f",
|
||||||
},
|
},
|
||||||
|
.@"zig-datetime" = .{
|
||||||
|
.url = "git+https://github.com/frmdstryr/zig-datetime.git#70aebf28fb3e137cd84123a9349d157a74708721",
|
||||||
|
.hash = "122077215ce36e125a490e59ec1748ffd4f6ba00d4d14f7308978e5360711d72d77f",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
.paths = .{
|
.paths = .{
|
||||||
|
868
src/app.zig
868
src/app.zig
File diff suppressed because it is too large
Load Diff
@ -31,20 +31,14 @@ pub const ViewAxisPosition = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get(optional_self: *?ViewAxisPosition, project: *App.Project, view_id: Id, axis: UI.Axis) ?f64 {
|
fn get(optional_self: *?ViewAxisPosition, project: *App.Project, view_id: Id, axis: UI.Axis) ?f64 {
|
||||||
|
_ = project;
|
||||||
|
|
||||||
const self = optional_self.* orelse return null;
|
const self = optional_self.* orelse return null;
|
||||||
|
|
||||||
if (self.axis != axis) return null;
|
if (self.axis != axis) return null;
|
||||||
|
|
||||||
const view = project.views.get(view_id) orelse return null;
|
if (!self.view_id.eql(view_id)) {
|
||||||
if (view.sync_controls) {
|
return null;
|
||||||
const owner_view = project.views.get(self.view_id).?;
|
|
||||||
if (!owner_view.sync_controls) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!self.view_id.eql(view_id)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.position;
|
return self.position;
|
||||||
@ -159,6 +153,7 @@ const MarkedRangeIterator = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
app: *App,
|
||||||
project: *App.Project,
|
project: *App.Project,
|
||||||
|
|
||||||
// TODO: Redo
|
// TODO: Redo
|
||||||
@ -166,21 +161,13 @@ undo_stack: CommandFrameArray = .{},
|
|||||||
last_applied_command: usize = 0,
|
last_applied_command: usize = 0,
|
||||||
zoom_start: ?ViewAxisPosition = null,
|
zoom_start: ?ViewAxisPosition = null,
|
||||||
cursor: ?ViewAxisPosition = null,
|
cursor: ?ViewAxisPosition = null,
|
||||||
view_settings: ?Id = null, // View id
|
// view_protocol_modal: ?Id = null, // View id
|
||||||
view_protocol_modal: ?Id = null, // View id
|
// selected_tool: enum { move, select, marker } = .move,
|
||||||
selected_tool: enum { move, select, marker } = .move,
|
|
||||||
show_marked_range: ?struct {
|
|
||||||
view_id: Id,
|
|
||||||
index: usize,
|
|
||||||
} = null,
|
|
||||||
show_marker: ?struct {
|
|
||||||
view_id: Id,
|
|
||||||
index: usize
|
|
||||||
} = null,
|
|
||||||
|
|
||||||
pub fn init(project: *App.Project) System {
|
pub fn init(app: *App) System {
|
||||||
return System{
|
return System{
|
||||||
.project = project
|
.app = app,
|
||||||
|
.project = &app.project
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,39 +229,21 @@ pub fn pushViewMove(self: *System, view_id: Id, x_range: RangeF64, y_range: Rang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var sync_controls = false;
|
var command: *Command = undefined;
|
||||||
if (self.project.views.get(view_id)) |view| {
|
if (frame.findCommandByView(view_id)) |prev_command| {
|
||||||
sync_controls = view.sync_controls;
|
command = prev_command;
|
||||||
}
|
|
||||||
|
|
||||||
var view_ids: std.BoundedArray(Id, constants.max_views) = .{};
|
command.move_and_zoom.x = x_range;
|
||||||
if (sync_controls) {
|
command.move_and_zoom.y = y_range;
|
||||||
var iter = self.project.views.idIterator();
|
|
||||||
while (iter.next()) |id| {
|
|
||||||
if (self.project.views.get(id).?.sync_controls) {
|
|
||||||
view_ids.appendAssumeCapacity(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
view_ids.appendAssumeCapacity(view_id);
|
if (self.project.views.get(view_id)) |view| {
|
||||||
}
|
|
||||||
|
|
||||||
for (view_ids.constSlice()) |id| {
|
|
||||||
var command: *Command = undefined;
|
|
||||||
if (frame.findCommandByView(id)) |prev_command| {
|
|
||||||
command = prev_command;
|
|
||||||
|
|
||||||
command.move_and_zoom.x = x_range;
|
|
||||||
command.move_and_zoom.y = y_range;
|
|
||||||
} else {
|
|
||||||
const view = self.project.views.get(view_id) orelse continue;
|
|
||||||
const view_rect = &view.graph_opts;
|
const view_rect = &view.graph_opts;
|
||||||
|
|
||||||
command = frame.commands.addOneAssumeCapacity();
|
command = frame.commands.addOneAssumeCapacity();
|
||||||
|
|
||||||
command.* = Command{
|
command.* = Command{
|
||||||
.move_and_zoom = .{
|
.move_and_zoom = .{
|
||||||
.view_id = id,
|
.view_id = view_id,
|
||||||
.before_x = view_rect.x_range,
|
.before_x = view_rect.x_range,
|
||||||
.before_y = view_rect.y_range,
|
.before_y = view_rect.y_range,
|
||||||
.x = x_range,
|
.x = x_range,
|
||||||
@ -283,7 +252,6 @@ pub fn pushViewMove(self: *System, view_id: Id, x_range: RangeF64, y_range: Rang
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pushViewMoveAxis(self: *System, view_id: Id, axis: UI.Axis, view_range: RangeF64) void {
|
pub fn pushViewMoveAxis(self: *System, view_id: Id, axis: UI.Axis, view_range: RangeF64) void {
|
||||||
@ -318,14 +286,15 @@ pub fn applyCommands(self: *System) void {
|
|||||||
|
|
||||||
pub fn toggleViewSettings(self: *System, view_id: Id) void {
|
pub fn toggleViewSettings(self: *System, view_id: Id) void {
|
||||||
if (self.isViewSettingsOpen(view_id)) {
|
if (self.isViewSettingsOpen(view_id)) {
|
||||||
self.view_settings = null;
|
self.app.main_screen.side_panel = .project;
|
||||||
} else {
|
} else {
|
||||||
self.view_settings = view_id;
|
self.app.main_screen.side_panel = .{ .view_settings = view_id };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isViewSettingsOpen(self: *System, view_id: Id) bool {
|
pub fn isViewSettingsOpen(self: *System, view_id: Id) bool {
|
||||||
return self.view_settings != null and self.view_settings.?.eql(view_id);
|
const side_panel = self.app.main_screen.side_panel;
|
||||||
|
return side_panel == .view_settings and side_panel.view_settings.eql(view_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setCursor(self: *System, view_id: Id, axis: UI.Axis, position: ?f64) void {
|
pub fn setCursor(self: *System, view_id: Id, axis: UI.Axis, position: ?f64) void {
|
||||||
@ -345,29 +314,36 @@ pub fn getCursorHoldStart(self: *System, view_id: Id, axis: UI.Axis) ?f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggleShownMarkedRange(self: *System, view_id: Id, index: usize) void {
|
pub fn toggleShownMarkedRange(self: *System, view_id: Id, index: usize) void {
|
||||||
if (self.show_marked_range) |show_marked_range| {
|
const side_panel = &self.app.main_screen.side_panel;
|
||||||
|
|
||||||
|
if (side_panel.* == .marked_range) {
|
||||||
|
const show_marked_range = side_panel.marked_range;
|
||||||
if (show_marked_range.view_id.eql(view_id) and show_marked_range.index == index) {
|
if (show_marked_range.view_id.eql(view_id) and show_marked_range.index == index) {
|
||||||
self.show_marked_range = null;
|
side_panel.* = .project;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.show_marked_range = .{
|
side_panel.* = .{
|
||||||
.view_id = view_id,
|
.marked_range = .{ .index = index, .view_id = view_id }
|
||||||
.index = index,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggleShownMarker(self: *System, view_id: Id, index: usize) void {
|
pub fn toggleShownMarker(self: *System, view_id: Id, index: usize) void {
|
||||||
if (self.show_marker) |show_marker| {
|
const side_panel = &self.app.main_screen.side_panel;
|
||||||
|
|
||||||
|
if (side_panel.* == .marker) {
|
||||||
|
const show_marker = side_panel.marker;
|
||||||
if (show_marker.view_id.eql(view_id) and show_marker.index == index) {
|
if (show_marker.view_id.eql(view_id) and show_marker.index == index) {
|
||||||
self.show_marker = null;
|
side_panel.* = .project;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.show_marker = .{
|
side_panel.* = .{
|
||||||
.view_id = view_id,
|
.marker = .{
|
||||||
.index = index,
|
.view_id = view_id,
|
||||||
|
.index = index,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -17,8 +17,6 @@ const Id = App.Id;
|
|||||||
const remap = utils.remap;
|
const remap = utils.remap;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const ruler_size = UI.Sizing.initFixed(.{ .pixels = 32 });
|
|
||||||
|
|
||||||
pub const ZoomStart = UIViewRuler.ZoomStart;
|
pub const ZoomStart = UIViewRuler.ZoomStart;
|
||||||
|
|
||||||
pub const Context = struct {
|
pub const Context = struct {
|
||||||
@ -75,7 +73,7 @@ fn showGraph(ctx: Context, graph_box: *UI.Box, view_id: Id) void {
|
|||||||
sample_value_under_mouse = mouse_y_range.remapTo(view_opts.y_range, signal.relative_mouse.y);
|
sample_value_under_mouse = mouse_y_range.remapTo(view_opts.y_range, signal.relative_mouse.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.view_controls.selected_tool == .move) {
|
// if (ctx.view_controls.selected_tool == .move) {
|
||||||
if (signal.dragged()) {
|
if (signal.dragged()) {
|
||||||
const x_offset = mouse_x_range.remapTo(RangeF64.init(0, view_opts.x_range.size()), signal.drag.x);
|
const x_offset = mouse_x_range.remapTo(RangeF64.init(0, view_opts.x_range.size()), signal.drag.x);
|
||||||
const y_offset = mouse_y_range.remapTo(RangeF64.init(0, view_opts.y_range.size()), signal.drag.y);
|
const y_offset = mouse_y_range.remapTo(RangeF64.init(0, view_opts.y_range.size()), signal.drag.y);
|
||||||
@ -109,21 +107,16 @@ fn showGraph(ctx: Context, graph_box: *UI.Box, view_id: Id) void {
|
|||||||
if (signal.flags.contains(.left_released)) {
|
if (signal.flags.contains(.left_released)) {
|
||||||
ctx.view_controls.pushBreakpoint();
|
ctx.view_controls.pushBreakpoint();
|
||||||
}
|
}
|
||||||
} else if (ctx.view_controls.selected_tool == .select) {
|
// } else if (ctx.view_controls.selected_tool == .select) {
|
||||||
// TODO:
|
// // TODO:
|
||||||
|
|
||||||
} else if (ctx.view_controls.selected_tool == .marker) {
|
// } else if (ctx.view_controls.selected_tool == .marker) {
|
||||||
// TODO:
|
// // TODO:
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
{ // Render graph
|
{ // Render graph
|
||||||
var sample_list_id = app.project.getViewSampleListId(view_id);
|
const sample_list = app.project.sample_lists.get(view.transformed_samples).?;
|
||||||
if (view.transformed_samples) |transformed_samples_id| {
|
|
||||||
sample_list_id = transformed_samples_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sample_list = app.project.sample_lists.get(sample_list_id).?;
|
|
||||||
Graph.drawCached(&view.graph_cache, graph_box.persistent.size, view_opts.*, sample_list);
|
Graph.drawCached(&view.graph_cache, graph_box.persistent.size, view_opts.*, sample_list);
|
||||||
if (view.graph_cache.texture) |texture| {
|
if (view.graph_cache.texture) |texture| {
|
||||||
graph_box.texture = texture.texture;
|
graph_box.texture = texture.texture;
|
||||||
@ -170,19 +163,11 @@ fn showToolbar(ctx: Context, view_id: Id) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
const btn = ui.textButton("Reset view");
|
|
||||||
btn.background = srcery.hard_black;
|
|
||||||
if (ui.signal(btn).clicked()) {
|
|
||||||
ctx.view_controls.pushViewMove(view_id, view.available_x_range, view.available_y_range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view.reference == .channel) {
|
if (view.reference == .channel) {
|
||||||
const channel_id = view.reference.channel;
|
const channel_id = view.reference.channel;
|
||||||
const channel = ctx.app.getChannel(channel_id).?;
|
const channel = ctx.app.getChannel(channel_id).?;
|
||||||
const channel_name = utils.getBoundedStringZ(&channel.name);
|
const channel_name = utils.getBoundedStringZ(&channel.name);
|
||||||
const channel_type = NIDaq.getChannelType(channel_name).?;
|
// const channel_type = NIDaq.getChannelType(channel_name).?;
|
||||||
|
|
||||||
{
|
{
|
||||||
const follow = ui.textButton("Follow");
|
const follow = ui.textButton("Follow");
|
||||||
@ -198,35 +183,35 @@ fn showToolbar(ctx: Context, view_id: Id) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel_type == .analog_output) {
|
// if (channel_type == .analog_output) {
|
||||||
const button = ui.button(ui.keyFromString("Output generation"));
|
// const button = ui.button(ui.keyFromString("Output generation"));
|
||||||
button.texture = Assets.output_generation;
|
// button.texture = Assets.output_generation;
|
||||||
button.size.y = UI.Sizing.initGrowFull();
|
// button.size.y = UI.Sizing.initGrowFull();
|
||||||
|
|
||||||
const signal = ui.signal(button);
|
// const signal = ui.signal(button);
|
||||||
if (signal.clicked()) {
|
// if (signal.clicked()) {
|
||||||
if (ctx.app.isChannelOutputing(channel_id)) {
|
// if (ctx.app.isChannelOutputing(channel_id)) {
|
||||||
ctx.app.pushCommand(.{
|
// ctx.app.pushCommand(.{
|
||||||
.stop_output = channel_id
|
// .stop_output = channel_id
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
ctx.view_controls.view_protocol_modal = view_id;
|
// ctx.view_controls.view_protocol_modal = view_id;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
var color = rl.Color.white;
|
// var color = rl.Color.white;
|
||||||
if (ctx.app.isChannelOutputing(channel_id)) {
|
// if (ctx.app.isChannelOutputing(channel_id)) {
|
||||||
color = srcery.red;
|
// color = srcery.red;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (signal.active) {
|
// if (signal.active) {
|
||||||
button.texture_color = color.alpha(0.6);
|
// button.texture_color = color.alpha(0.6);
|
||||||
} else if (signal.hot) {
|
// } else if (signal.hot) {
|
||||||
button.texture_color = color.alpha(0.8);
|
// button.texture_color = color.alpha(0.8);
|
||||||
} else {
|
// } else {
|
||||||
button.texture_color = color;
|
// button.texture_color = color;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
view_name = channel_name;
|
view_name = channel_name;
|
||||||
} else if (view.reference == .file) {
|
} else if (view.reference == .file) {
|
||||||
@ -236,14 +221,8 @@ fn showToolbar(ctx: Context, view_id: Id) void {
|
|||||||
view_name = std.fs.path.stem(file.path);
|
view_name = std.fs.path.stem(file.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.sync_controls) {
|
if (view.name.len > 0) {
|
||||||
const btn = ui.button(ui.keyFromString("Disable sync"));
|
view_name = view.name.constSlice();
|
||||||
btn.texture = Assets.cross;
|
|
||||||
btn.size.y = UI.Sizing.initGrowFull();
|
|
||||||
btn.tooltip = "Disable sync controls";
|
|
||||||
if (ui.signal(btn).clicked()) {
|
|
||||||
view.sync_controls = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view_name) |text| {
|
if (view_name) |text| {
|
||||||
@ -314,14 +293,14 @@ pub fn show(ctx: Context, view_id: Id, height: UI.Sizing) !Result {
|
|||||||
const container = ui.createBox(.{
|
const container = ui.createBox(.{
|
||||||
.layout_direction = .left_to_right,
|
.layout_direction = .left_to_right,
|
||||||
.size_x = UI.Sizing.initGrowFull(),
|
.size_x = UI.Sizing.initGrowFull(),
|
||||||
.size_y = ruler_size,
|
.size_y = UIViewRuler.ruler_size_y,
|
||||||
});
|
});
|
||||||
container.beginChildren();
|
container.beginChildren();
|
||||||
defer container.endChildren();
|
defer container.endChildren();
|
||||||
|
|
||||||
_ = ui.createBox(.{
|
_ = ui.createBox(.{
|
||||||
.size_x = ruler_size,
|
.size_x = UIViewRuler.ruler_size_x,
|
||||||
.size_y = ruler_size,
|
.size_y = UIViewRuler.ruler_size_y,
|
||||||
.background = srcery.hard_black,
|
.background = srcery.hard_black,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ const RangeF64 = @import("../range.zig").RangeF64;
|
|||||||
const srcery = @import("../srcery.zig");
|
const srcery = @import("../srcery.zig");
|
||||||
const utils = @import("../utils.zig");
|
const utils = @import("../utils.zig");
|
||||||
const constants = @import("../constants.zig");
|
const constants = @import("../constants.zig");
|
||||||
|
const Assets = @import("../assets.zig");
|
||||||
|
|
||||||
const ViewControlsSystem = @import("./systems/view_controls.zig");
|
const ViewControlsSystem = @import("./systems/view_controls.zig");
|
||||||
|
|
||||||
@ -13,7 +14,8 @@ const Id = App.Id;
|
|||||||
const remap = utils.remap;
|
const remap = utils.remap;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const ruler_size = UI.Sizing.initFixed(.{ .pixels = 32 });
|
pub const ruler_size_x = UI.Sizing.initFixed(.{ .pixels = 32*3 });
|
||||||
|
pub const ruler_size_y = UI.Sizing.initFixed(.{ .pixels = 32 });
|
||||||
|
|
||||||
const Ruler = struct {
|
const Ruler = struct {
|
||||||
project: *App.Project,
|
project: *App.Project,
|
||||||
@ -57,11 +59,13 @@ const DrawContext = struct {
|
|||||||
available_range: RangeF64,
|
available_range: RangeF64,
|
||||||
axis: UI.Axis,
|
axis: UI.Axis,
|
||||||
rect: rl.Rectangle = .{ .x = 0, .y = 0, .width = 0, .height = 0 },
|
rect: rl.Rectangle = .{ .x = 0, .y = 0, .width = 0, .height = 0 },
|
||||||
|
project: *App.Project,
|
||||||
|
|
||||||
fn init(axis: UI.Axis, project: *App.Project, view_id: Id) DrawContext {
|
fn init(axis: UI.Axis, project: *App.Project, view_id: Id) DrawContext {
|
||||||
const view = project.views.get(view_id).?;
|
const view = project.views.get(view_id).?;
|
||||||
|
|
||||||
return DrawContext{
|
return DrawContext{
|
||||||
|
.project = project,
|
||||||
.one_unit = switch (axis) {
|
.one_unit = switch (axis) {
|
||||||
.X => project.getSampleRate(),
|
.X => project.getSampleRate(),
|
||||||
.Y => 1
|
.Y => 1
|
||||||
@ -159,33 +163,43 @@ pub fn createBox(ctx: Context, key: UI.Key, axis: UI.Axis) *UI.Box {
|
|||||||
});
|
});
|
||||||
if (axis == .X) {
|
if (axis == .X) {
|
||||||
ruler.size.x = UI.Sizing.initGrowFull();
|
ruler.size.x = UI.Sizing.initGrowFull();
|
||||||
ruler.size.y = ruler_size;
|
ruler.size.y = ruler_size_y;
|
||||||
} else {
|
} else {
|
||||||
ruler.size.x = ruler_size;
|
ruler.size.x = ruler_size_x;
|
||||||
ruler.size.y = UI.Sizing.initGrowFull();
|
ruler.size.y = UI.Sizing.initGrowFull();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruler;
|
return ruler;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drawRulerTicks(_ctx: ?*anyopaque, box: *UI.Box) void {
|
fn formatAxisLabel(allocator: std.mem.Allocator, project: *App.Project, axis: UI.Axis, position: f64) ![]u8 {
|
||||||
|
const sample_rate = project.sample_rate;
|
||||||
|
if (axis == .X and sample_rate != null) {
|
||||||
|
const seconds = position / sample_rate.?;
|
||||||
|
return try utils.formatDuration(allocator, seconds, false);
|
||||||
|
} else {
|
||||||
|
return try std.fmt.allocPrint(allocator, "{d:.3}", .{ position });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drawRulerTicks(_ctx: ?*anyopaque, ui: *UI, box: *UI.Box) void {
|
||||||
const ctx: *DrawContext = @ptrCast(@alignCast(_ctx));
|
const ctx: *DrawContext = @ptrCast(@alignCast(_ctx));
|
||||||
ctx.rect = box.rect();
|
ctx.rect = box.rect();
|
||||||
|
|
||||||
ctx.drawLine(ctx.available_range.lower, 1, srcery.yellow);
|
ctx.drawLine(ctx.available_range.lower, 1, srcery.yellow);
|
||||||
ctx.drawLine(ctx.available_range.upper, 1, srcery.yellow);
|
ctx.drawLine(ctx.available_range.upper, 1, srcery.yellow);
|
||||||
|
|
||||||
if (ctx.available_range.hasExclusive(0)) {
|
// if (ctx.available_range.hasExclusive(0)) {
|
||||||
ctx.drawLine(0, 0.75, srcery.yellow);
|
// ctx.drawLine(0, 0.75, srcery.yellow);
|
||||||
}
|
// }
|
||||||
|
|
||||||
var one_unit = ctx.one_unit orelse return;
|
var one_unit = ctx.one_unit orelse 5000;
|
||||||
|
|
||||||
while (ctx.render_range.size() < 5*one_unit) {
|
while (ctx.render_range.size() < 2*one_unit) {
|
||||||
one_unit /= 2;
|
one_unit /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ctx.render_range.size() > 50*one_unit) {
|
while (ctx.render_range.size() > 10*one_unit) {
|
||||||
one_unit *= 2;
|
one_unit *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +208,18 @@ fn drawRulerTicks(_ctx: ?*anyopaque, box: *UI.Box) void {
|
|||||||
|
|
||||||
ctx.drawTicks(ticks_range.lower, ticks_range.upper, one_unit, 0.5, srcery.yellow);
|
ctx.drawTicks(ticks_range.lower, ticks_range.upper, one_unit, 0.5, srcery.yellow);
|
||||||
ctx.drawTicks(ticks_range.lower + one_unit/2, ticks_range.upper, one_unit, 0.25, srcery.yellow);
|
ctx.drawTicks(ticks_range.lower + one_unit/2, ticks_range.upper, one_unit, 0.25, srcery.yellow);
|
||||||
|
|
||||||
|
const font = Assets.font(box.font);
|
||||||
|
|
||||||
|
const allocator = ui.frameAllocator();
|
||||||
|
|
||||||
|
{
|
||||||
|
var position = ticks_range.lower + one_unit;
|
||||||
|
while (position < ticks_range.upper - one_unit) : (position += one_unit) {
|
||||||
|
const text = formatAxisLabel(allocator, ctx.project, ctx.axis, position) catch continue;
|
||||||
|
font.drawTextCenter(text, ctx.getPoint(position, 0.8), srcery.bright_white);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn showMouseTooltip(ctx: Context, axis: UI.Axis, view_id: Id, position: f64) void {
|
fn showMouseTooltip(ctx: Context, axis: UI.Axis, view_id: Id, position: f64) void {
|
||||||
@ -214,7 +240,7 @@ fn showMouseTooltip(ctx: Context, axis: UI.Axis, view_id: Id, position: f64) voi
|
|||||||
} else if (axis == .X and sample_rate != null) {
|
} else if (axis == .X and sample_rate != null) {
|
||||||
const seconds = position / sample_rate.?;
|
const seconds = position / sample_rate.?;
|
||||||
const frame_allocator = ui.frameAllocator();
|
const frame_allocator = ui.frameAllocator();
|
||||||
_ = ui.label("{s}", .{ utils.formatDuration(frame_allocator, seconds) catch "-" });
|
_ = ui.label("{s}", .{ utils.formatDuration(frame_allocator, seconds, true) catch "-" });
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_ = ui.label("{d:.3}", .{position});
|
_ = ui.label("{d:.3}", .{position});
|
||||||
@ -303,54 +329,87 @@ pub fn show(ctx: Context, box: *UI.Box, graph_box: *UI.Box, view_id: Id, axis: U
|
|||||||
_ = showMarkerRect(ui, ruler, RangeF64.init(hold_start.?, cursor.?), marker_color.alpha(0.5), null);
|
_ = showMarkerRect(ui, ruler, RangeF64.init(hold_start.?, cursor.?), marker_color.alpha(0.5), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// {
|
||||||
var selected_range_iter = view.iterMarkedRanges(axis);
|
// var selected_range_iter = view.iterMarkedRanges(axis);
|
||||||
while (selected_range_iter.next()) |selected_range| {
|
// while (selected_range_iter.next()) |selected_range| {
|
||||||
var color = srcery.blue;
|
// var color = srcery.blue;
|
||||||
const index = selected_range_iter.index;
|
// const index = selected_range_iter.index;
|
||||||
|
|
||||||
if (ctx.view_controls.show_marked_range) |show_marked_range| {
|
// const side_panel = ctx.view_controls.app.main_screen.side_panel;
|
||||||
if (show_marked_range.view_id.eql(view_id) and show_marked_range.index == index) {
|
// if (side_panel == .marked_range) {
|
||||||
if (@mod(rl.getTime(), 0.5) < 0.25) {
|
// const show_marked_range = side_panel.marked_range;
|
||||||
color = utils.shiftColorInHSV(color, 0.8);
|
// if (show_marked_range.view_id.eql(view_id) and show_marked_range.index == index) {
|
||||||
}
|
// if (@mod(rl.getTime(), 0.5) < 0.25) {
|
||||||
}
|
// color = utils.shiftColorInHSV(color, 0.8);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
showMarkerLine(ui, ruler, selected_range.lower, color);
|
// showMarkerLine(ui, ruler, selected_range.lower, color);
|
||||||
showMarkerLine(ui, ruler, selected_range.upper, color);
|
// showMarkerLine(ui, ruler, selected_range.upper, color);
|
||||||
|
|
||||||
var hasher = UI.Key.CombineHasher.init();
|
// var hasher = UI.Key.CombineHasher.init();
|
||||||
hasher.update(std.mem.asBytes("Marked ranges"));
|
// hasher.update(std.mem.asBytes("Marked ranges"));
|
||||||
hasher.update(std.mem.asBytes(&view_id));
|
// hasher.update(std.mem.asBytes(&view_id));
|
||||||
hasher.update(std.mem.asBytes(&axis));
|
// hasher.update(std.mem.asBytes(&axis));
|
||||||
hasher.update(std.mem.asBytes(&index));
|
// hasher.update(std.mem.asBytes(&index));
|
||||||
const range_box_key = UI.Key.init(hasher.final());
|
// const range_box_key = UI.Key.init(hasher.final());
|
||||||
|
|
||||||
var range_box = showMarkerRect(ui, ruler, selected_range, color.alpha(0.5), range_box_key);
|
// var range_box = showMarkerRect(ui, ruler, selected_range, color.alpha(0.5), range_box_key);
|
||||||
range_box.flags.insert(.clickable);
|
// range_box.flags.insert(.clickable);
|
||||||
range_box.flags.insert(.draw_hot);
|
// range_box.flags.insert(.draw_hot);
|
||||||
range_box.flags.insert(.draw_active);
|
// range_box.flags.insert(.draw_active);
|
||||||
|
|
||||||
range_box.hot_cursor = .mouse_cursor_pointing_hand;
|
// range_box.hot_cursor = .mouse_cursor_pointing_hand;
|
||||||
if (ctx.view_controls.selected_tool == .select) {
|
// if (ctx.view_controls.selected_tool == .select) {
|
||||||
const signal = ui.signal(range_box);
|
// const signal = ui.signal(range_box);
|
||||||
if (signal.clicked()) {
|
// if (signal.clicked()) {
|
||||||
ctx.view_controls.toggleShownMarkedRange(view_id, index);
|
// ctx.view_controls.toggleShownMarkedRange(view_id, index);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (axis == .X) {
|
if (axis == .X) {
|
||||||
for (0.., view.markers.constSlice()) |i, marker| {
|
// for (0.., view.markers.constSlice()) |i, marker| {
|
||||||
const color = srcery.cyan;
|
// const color = srcery.cyan;
|
||||||
|
|
||||||
showMarkerLine(ui, ruler, marker, color);
|
// showMarkerLine(ui, ruler, marker, color);
|
||||||
showMarkerLine(ui, ruler, marker, color);
|
// showMarkerLine(ui, ruler, marker, color);
|
||||||
|
|
||||||
|
// var hasher = UI.Key.CombineHasher.init();
|
||||||
|
// hasher.update(std.mem.asBytes("Markers"));
|
||||||
|
// hasher.update(std.mem.asBytes(&view_id));
|
||||||
|
// hasher.update(std.mem.asBytes(&axis));
|
||||||
|
// hasher.update(std.mem.asBytes(&i));
|
||||||
|
|
||||||
|
// const view_size = view.graph_opts.x_range.size();
|
||||||
|
// const clickable_width = view_size * 0.01;
|
||||||
|
|
||||||
|
// const clickable = ui.createBox(.{
|
||||||
|
// .key = UI.Key.init(hasher.final()),
|
||||||
|
// .float_rect = ruler.getGraphDrawContext().getRect(marker - clickable_width/2, clickable_width, 0, 1),
|
||||||
|
// .float_relative_to = ruler.graph_box,
|
||||||
|
// .parent = ruler.graph_box,
|
||||||
|
// .flags = &.{ .draw_hot, .draw_active, .clickable },
|
||||||
|
// .hot_cursor = .mouse_cursor_pointing_hand,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (ui.signal(clickable).clicked()) {
|
||||||
|
// ctx.view_controls.toggleShownMarker(view_id, i);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (0.., project.gain_changes.slice()) |i, *gain_change| {
|
||||||
|
const color = srcery.bright_orange;
|
||||||
|
|
||||||
|
const sample = gain_change.sample;
|
||||||
|
|
||||||
|
showMarkerLine(ui, ruler, sample, color);
|
||||||
|
showMarkerLine(ui, ruler, sample, color);
|
||||||
|
|
||||||
var hasher = UI.Key.CombineHasher.init();
|
var hasher = UI.Key.CombineHasher.init();
|
||||||
hasher.update(std.mem.asBytes("Markers"));
|
hasher.update(std.mem.asBytes("Gain change"));
|
||||||
hasher.update(std.mem.asBytes(&view_id));
|
hasher.update(std.mem.asBytes(&view_id));
|
||||||
hasher.update(std.mem.asBytes(&axis));
|
hasher.update(std.mem.asBytes(&axis));
|
||||||
hasher.update(std.mem.asBytes(&i));
|
hasher.update(std.mem.asBytes(&i));
|
||||||
@ -360,21 +419,77 @@ pub fn show(ctx: Context, box: *UI.Box, graph_box: *UI.Box, view_id: Id, axis: U
|
|||||||
|
|
||||||
const clickable = ui.createBox(.{
|
const clickable = ui.createBox(.{
|
||||||
.key = UI.Key.init(hasher.final()),
|
.key = UI.Key.init(hasher.final()),
|
||||||
.float_rect = ruler.getGraphDrawContext().getRect(marker - clickable_width/2, clickable_width, 0, 1),
|
.float_rect = ruler.getGraphDrawContext().getRect(sample - clickable_width/2, clickable_width, 0, 1),
|
||||||
|
.float_relative_to = ruler.graph_box,
|
||||||
|
.parent = ruler.graph_box,
|
||||||
|
.flags = &.{ .draw_hot, .draw_active, .clickable, .draggable },
|
||||||
|
.hot_cursor = .mouse_cursor_pointing_hand,
|
||||||
|
});
|
||||||
|
|
||||||
|
const signal = ui.signal(clickable);
|
||||||
|
if (signal.hot) {
|
||||||
|
const mouse_tooltip = ui.mouseTooltip();
|
||||||
|
mouse_tooltip.beginChildren();
|
||||||
|
defer mouse_tooltip.endChildren();
|
||||||
|
|
||||||
|
_ = ui.label("Gain: {d:.3}", .{ gain_change.gain });
|
||||||
|
}
|
||||||
|
|
||||||
|
const view_range = view.getGraphView(axis);
|
||||||
|
const mouse_range = switch (axis) {
|
||||||
|
.X => RangeF64.init(0, ruler.graph_box.persistent.size.x),
|
||||||
|
.Y => RangeF64.init(0, ruler.graph_box.persistent.size.y)
|
||||||
|
};
|
||||||
|
const mouse_position = switch (axis) {
|
||||||
|
.X => signal.mouse.x - ruler.graph_box.persistent.position.x,
|
||||||
|
.Y => signal.mouse.y - ruler.graph_box.persistent.position.y
|
||||||
|
};
|
||||||
|
|
||||||
|
if (signal.dragged() and i != 0) {
|
||||||
|
project.updateGainChange(i, mouse_range.remapTo(view_range.*, mouse_position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (0.., project.statistic_points.items) |i, statistic_point| {
|
||||||
|
const color = srcery.bright_blue;
|
||||||
|
|
||||||
|
const sample: f64 = @floatFromInt(statistic_point);
|
||||||
|
|
||||||
|
showMarkerLine(ui, ruler, sample, color);
|
||||||
|
showMarkerLine(ui, ruler, sample, color);
|
||||||
|
|
||||||
|
var hasher = UI.Key.CombineHasher.init();
|
||||||
|
hasher.update(std.mem.asBytes("Statistic point"));
|
||||||
|
hasher.update(std.mem.asBytes(&view_id));
|
||||||
|
hasher.update(std.mem.asBytes(&axis));
|
||||||
|
hasher.update(std.mem.asBytes(&i));
|
||||||
|
|
||||||
|
const view_size = view.graph_opts.x_range.size();
|
||||||
|
const clickable_width = view_size * 0.01;
|
||||||
|
|
||||||
|
const clickable = ui.createBox(.{
|
||||||
|
.key = UI.Key.init(hasher.final()),
|
||||||
|
.float_rect = ruler.getGraphDrawContext().getRect(sample - clickable_width/2, clickable_width, 0, 1),
|
||||||
.float_relative_to = ruler.graph_box,
|
.float_relative_to = ruler.graph_box,
|
||||||
.parent = ruler.graph_box,
|
.parent = ruler.graph_box,
|
||||||
.flags = &.{ .draw_hot, .draw_active, .clickable },
|
.flags = &.{ .draw_hot, .draw_active, .clickable },
|
||||||
.hot_cursor = .mouse_cursor_pointing_hand,
|
.hot_cursor = .mouse_cursor_pointing_hand,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ui.signal(clickable).clicked()) {
|
const signal = ui.signal(clickable);
|
||||||
ctx.view_controls.toggleShownMarker(view_id, i);
|
if (signal.hot) {
|
||||||
|
const mouse_tooltip = ui.mouseTooltip();
|
||||||
|
mouse_tooltip.beginChildren();
|
||||||
|
defer mouse_tooltip.endChildren();
|
||||||
|
|
||||||
|
_ = ui.label("Statistic point", .{ });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const signal = ui.signal(box);
|
const signal = ui.signal(box);
|
||||||
|
const view_range = view.getGraphView(axis);
|
||||||
const mouse_position = switch (axis) {
|
const mouse_position = switch (axis) {
|
||||||
.X => signal.relative_mouse.x,
|
.X => signal.relative_mouse.x,
|
||||||
.Y => signal.relative_mouse.y
|
.Y => signal.relative_mouse.y
|
||||||
@ -383,7 +498,6 @@ pub fn show(ctx: Context, box: *UI.Box, graph_box: *UI.Box, view_id: Id, axis: U
|
|||||||
.X => RangeF64.init(0, box.persistent.size.x),
|
.X => RangeF64.init(0, box.persistent.size.x),
|
||||||
.Y => RangeF64.init(0, box.persistent.size.y)
|
.Y => RangeF64.init(0, box.persistent.size.y)
|
||||||
};
|
};
|
||||||
const view_range = view.getGraphView(axis);
|
|
||||||
|
|
||||||
if (signal.hot and view_range.size() > 0) {
|
if (signal.hot and view_range.size() > 0) {
|
||||||
const mouse_position_on_graph = mouse_range.remapTo(view_range.*, mouse_position);
|
const mouse_position_on_graph = mouse_range.remapTo(view_range.*, mouse_position);
|
||||||
@ -401,7 +515,7 @@ pub fn show(ctx: Context, box: *UI.Box, graph_box: *UI.Box, view_id: Id, axis: U
|
|||||||
ctx.view_controls.setCursorHoldStart(view_id, axis, cursor);
|
ctx.view_controls.setCursorHoldStart(view_id, axis, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.view_controls.selected_tool == .move) {
|
// if (ctx.view_controls.selected_tool == .move) {
|
||||||
if (signal.scrolled() and cursor != null) {
|
if (signal.scrolled() and cursor != null) {
|
||||||
var scale_factor: f64 = 1;
|
var scale_factor: f64 = 1;
|
||||||
if (signal.scroll.y > 0) {
|
if (signal.scroll.y > 0) {
|
||||||
@ -436,27 +550,27 @@ pub fn show(ctx: Context, box: *UI.Box, graph_box: *UI.Box, view_id: Id, axis: U
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ctx.view_controls.selected_tool == .select) {
|
// } else if (ctx.view_controls.selected_tool == .select) {
|
||||||
|
|
||||||
if (cursor != null) {
|
// if (cursor != null) {
|
||||||
if (ctx.view_controls.getCursorHoldStart(view_id, axis)) |hold_start| {
|
// if (ctx.view_controls.getCursorHoldStart(view_id, axis)) |hold_start| {
|
||||||
const range = RangeF64.init(
|
// const range = RangeF64.init(
|
||||||
@min(hold_start, cursor.?),
|
// @min(hold_start, cursor.?),
|
||||||
@max(hold_start, cursor.?),
|
// @max(hold_start, cursor.?),
|
||||||
);
|
// );
|
||||||
const hold_start_mouse = view_range.remapTo(mouse_range, range.lower);
|
// const hold_start_mouse = view_range.remapTo(mouse_range, range.lower);
|
||||||
const hold_end_mouse = view_range.remapTo(mouse_range, range.upper);
|
// const hold_end_mouse = view_range.remapTo(mouse_range, range.upper);
|
||||||
const mouse_move_distance = @abs(hold_end_mouse - hold_start_mouse);
|
// const mouse_move_distance = @abs(hold_end_mouse - hold_start_mouse);
|
||||||
if (signal.flags.contains(.left_released) and mouse_move_distance > 5) {
|
// if (signal.flags.contains(.left_released) and mouse_move_distance > 5) {
|
||||||
_ = ctx.project.appendMarkedRange(view_id, axis, range);
|
// _ = ctx.project.appendMarkedRange(view_id, axis, range);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} else if (ctx.view_controls.selected_tool == .marker) {
|
// } else if (ctx.view_controls.selected_tool == .marker) {
|
||||||
if (cursor != null and signal.flags.contains(.left_released) and axis == .X) {
|
// if (cursor != null and signal.flags.contains(.left_released) and axis == .X) {
|
||||||
view.markers.append(cursor.?) catch {};
|
// view.markers.append(cursor.?) catch {};
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (signal.flags.contains(.left_released)) {
|
if (signal.flags.contains(.left_released)) {
|
||||||
ctx.view_controls.setCursorHoldStart(view_id, axis, null);
|
ctx.view_controls.setCursorHoldStart(view_id, axis, null);
|
||||||
|
@ -30,7 +30,7 @@ pub const ViewOptions = struct {
|
|||||||
pub const RenderCache = struct {
|
pub const RenderCache = struct {
|
||||||
const Key = struct {
|
const Key = struct {
|
||||||
options: ViewOptions,
|
options: ViewOptions,
|
||||||
drawn_x_range: RangeF64
|
drawn_x_range: RangeF64,
|
||||||
};
|
};
|
||||||
|
|
||||||
texture: ?rl.RenderTexture2D = null,
|
texture: ?rl.RenderTexture2D = null,
|
||||||
@ -48,6 +48,14 @@ pub const RenderCache = struct {
|
|||||||
self.key = null;
|
self.key = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn invalidateRange(self: *RenderCache, x_range: RangeF64) void {
|
||||||
|
if (self.key) |key| {
|
||||||
|
if (key.drawn_x_range.intersectPositive(x_range).isPositive()) {
|
||||||
|
self.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw(self: RenderCache, rect: rl.Rectangle) void {
|
pub fn draw(self: RenderCache, rect: rl.Rectangle) void {
|
||||||
if (self.texture) |texture| {
|
if (self.texture) |texture| {
|
||||||
const source = rl.Rectangle{
|
const source = rl.Rectangle{
|
||||||
@ -323,7 +331,7 @@ pub fn drawCached(cache: *RenderCache, render_size: Vec2, options: ViewOptions,
|
|||||||
|
|
||||||
const cache_key = RenderCache.Key{
|
const cache_key = RenderCache.Key{
|
||||||
.options = options,
|
.options = options,
|
||||||
.drawn_x_range = RangeF64.init(0, @max(@as(f64, @floatFromInt(sample_list.getLength())) - 1, 0)).intersectPositive(options.x_range)
|
.drawn_x_range = RangeF64.init(0, @max(@as(f64, @floatFromInt(sample_list.getLength())) - 1, 0)).intersectPositive(options.x_range),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cache.key != null and std.meta.eql(cache.key.?, cache_key)) {
|
if (cache.key != null and std.meta.eql(cache.key.?, cache_key)) {
|
||||||
|
11
src/main.zig
11
src/main.zig
@ -118,8 +118,12 @@ pub fn main() !void {
|
|||||||
|
|
||||||
if (app_config_dir.openFile("config.bin", .{})) |save_file| {
|
if (app_config_dir.openFile("config.bin", .{})) |save_file| {
|
||||||
defer save_file.close();
|
defer save_file.close();
|
||||||
|
|
||||||
app.loadProject(save_file) catch |e| {
|
app.loadProject(save_file) catch |e| {
|
||||||
log.err("Failed to load project: {}", .{e});
|
log.err("Failed to load project: {}", .{e});
|
||||||
|
if (@errorReturnTrace()) |stack_trace| {
|
||||||
|
std.debug.dumpStackTrace(stack_trace.*);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else |e| switch (e) {
|
} else |e| switch (e) {
|
||||||
error.FileNotFound => {},
|
error.FileNotFound => {},
|
||||||
@ -174,6 +178,13 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
if (app.isCollectionInProgress()) {
|
||||||
|
app.stopCollection();
|
||||||
|
}
|
||||||
|
if (app.isOutputingInProgress()) {
|
||||||
|
app.stopAllOutput();
|
||||||
|
}
|
||||||
|
|
||||||
const save_file = try app_config_dir.createFile("config.bin", .{});
|
const save_file = try app_config_dir.createFile("config.bin", .{});
|
||||||
defer save_file.close();
|
defer save_file.close();
|
||||||
try app.saveProject(save_file);
|
try app.saveProject(save_file);
|
||||||
|
@ -97,12 +97,12 @@ pub fn tick(self: *Screen) !void {
|
|||||||
ai_voltage_physical_channels = try ni_daq.listDeviceAIPhysicalChannels(device);
|
ai_voltage_physical_channels = try ni_daq.listDeviceAIPhysicalChannels(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ao_physical_channels: []const [:0]const u8 = &.{};
|
// var ao_physical_channels: []const [:0]const u8 = &.{};
|
||||||
if (try ni_daq.checkDeviceAOOutputType(device, .Voltage)) {
|
// if (try ni_daq.checkDeviceAOOutputType(device, .Voltage)) {
|
||||||
ao_physical_channels = try ni_daq.listDeviceAOPhysicalChannels(device);
|
// ao_physical_channels = try ni_daq.listDeviceAOPhysicalChannels(device);
|
||||||
}
|
// }
|
||||||
|
|
||||||
inline for (.{ ai_voltage_physical_channels, ao_physical_channels }) |channels| {
|
inline for (.{ ai_voltage_physical_channels }) |channels| {
|
||||||
for (channels) |channel| {
|
for (channels) |channel| {
|
||||||
const channel_button = ui.textButton(channel);
|
const channel_button = ui.textButton(channel);
|
||||||
channel_button.background = srcery.black;
|
channel_button.background = srcery.black;
|
||||||
|
File diff suppressed because it is too large
Load Diff
24
src/ui.zig
24
src/ui.zig
@ -519,7 +519,7 @@ pub const Box = struct {
|
|||||||
|
|
||||||
pub const Draw = struct {
|
pub const Draw = struct {
|
||||||
ctx: ?*anyopaque = null,
|
ctx: ?*anyopaque = null,
|
||||||
do: *const fn(ctx: ?*anyopaque, box: *Box) void
|
do: *const fn(ctx: ?*anyopaque, ui: *UI, box: *Box) void
|
||||||
};
|
};
|
||||||
|
|
||||||
const max_wrapped_lines = 64;
|
const max_wrapped_lines = 64;
|
||||||
@ -1828,7 +1828,7 @@ fn drawBox(self: *UI, box: *Box, on_top_pass: ?bool) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (box.draw) |box_draw| {
|
if (box.draw) |box_draw| {
|
||||||
box_draw.do(box_draw.ctx, box);
|
box_draw.do(box_draw.ctx, self, box);
|
||||||
}
|
}
|
||||||
|
|
||||||
const alignment_x_coeff = box.alignment.x.getCoefficient();
|
const alignment_x_coeff = box.alignment.x.getCoefficient();
|
||||||
@ -2502,7 +2502,8 @@ pub const FileInputOptions = struct {
|
|||||||
file_picker: *?Platform.FilePickerId,
|
file_picker: *?Platform.FilePickerId,
|
||||||
open_dialog: bool = true,
|
open_dialog: bool = true,
|
||||||
folder: bool = false,
|
folder: bool = false,
|
||||||
path: ?[]const u8 = null
|
path: ?[]const u8 = null,
|
||||||
|
size_x: ?Sizing = null
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn mouseTooltip(self: *UI) *Box {
|
pub fn mouseTooltip(self: *UI) *Box {
|
||||||
@ -2649,7 +2650,7 @@ pub fn textInput(self: *UI, opts: TextInputOptions) !void {
|
|||||||
const storage_text = &storage.buffer;
|
const storage_text = &storage.buffer;
|
||||||
|
|
||||||
if (opts.initial != null and container.created) {
|
if (opts.initial != null and container.created) {
|
||||||
storage_text.clearAndFree();
|
storage.clear();
|
||||||
try storage_text.appendSlice(opts.initial.?);
|
try storage_text.appendSlice(opts.initial.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2778,8 +2779,9 @@ pub fn textInput(self: *UI, opts: TextInputOptions) !void {
|
|||||||
storage.editing = true;
|
storage.editing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stop_editing = false;
|
||||||
if (self.isKeyActiveAny() and !container_signal.active) {
|
if (self.isKeyActiveAny() and !container_signal.active) {
|
||||||
storage.editing = false;
|
stop_editing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text input controls
|
// Text input controls
|
||||||
@ -2951,7 +2953,7 @@ pub fn textInput(self: *UI, opts: TextInputOptions) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (self.isKeyboardPressed(.key_escape)) {
|
if (self.isKeyboardPressed(.key_escape)) {
|
||||||
storage.editing = false;
|
stop_editing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.isKeyboardPressed(.key_enter)) {
|
if (self.isKeyboardPressed(.key_enter)) {
|
||||||
@ -2974,9 +2976,15 @@ pub fn textInput(self: *UI, opts: TextInputOptions) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!opts.editable) {
|
if (!opts.editable) {
|
||||||
storage.editing = false;
|
stop_editing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stop_editing) {
|
||||||
|
storage.editing = false;
|
||||||
|
storage.cursor_start = 0;
|
||||||
|
storage.cursor_stop = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn numberInput(self: *UI, T: type, opts: NumberInputOptions) !?T {
|
pub fn numberInput(self: *UI, T: type, opts: NumberInputOptions) !?T {
|
||||||
@ -3071,7 +3079,7 @@ pub fn fileInput(self: *UI, opts: FileInputOptions) ?[]u8 {
|
|||||||
|
|
||||||
const container = self.createBox(.{
|
const container = self.createBox(.{
|
||||||
.key = opts.key,
|
.key = opts.key,
|
||||||
.size_x = Sizing.initGrowUpTo(.{ .pixels = 200 }),
|
.size_x = opts.size_x orelse Sizing.initGrowUpTo(.{ .pixels = 200 }),
|
||||||
.size_y = Sizing.initFixed(Unit.initPixels(self.rem(1))),
|
.size_y = Sizing.initFixed(Unit.initPixels(self.rem(1))),
|
||||||
.flags = &.{ .clickable, .clip_view, .draw_hot, .draw_active },
|
.flags = &.{ .clickable, .clip_view, .draw_hot, .draw_active },
|
||||||
.background = srcery.bright_white,
|
.background = srcery.bright_white,
|
||||||
|
@ -86,8 +86,12 @@ pub inline fn dumpErrorTrace() void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn formatDuration(allocator: std.mem.Allocator, total_seconds: f64) ![]u8 {
|
pub fn formatDuration(allocator: std.mem.Allocator, total_seconds: f64, high_accuracy: bool) ![]u8 {
|
||||||
const seconds = @mod(total_seconds, @as(f64, @floatFromInt(std.time.s_per_min)));
|
const seconds = @mod(total_seconds, @as(f64, @floatFromInt(std.time.s_per_min)));
|
||||||
const minutes = @divFloor(total_seconds, std.time.s_per_min);
|
const minutes = @divFloor(total_seconds, std.time.s_per_min);
|
||||||
return try std.fmt.allocPrint(allocator, "{d:.0}m {d:.3}s", .{ minutes, seconds });
|
if (high_accuracy) {
|
||||||
|
return try std.fmt.allocPrint(allocator, "{d:.0}m {d:.5}s", .{ minutes, seconds });
|
||||||
|
} else {
|
||||||
|
return try std.fmt.allocPrint(allocator, "{d:.0}m {d:.3}s", .{ minutes, seconds });
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user