add labels to ruler

This commit is contained in:
Rokas Puzonas 2025-05-24 18:27:37 +03:00
parent fdf6001068
commit ecea2b513a
7 changed files with 62 additions and 74 deletions

View File

@ -854,7 +854,6 @@ pub const View = struct {
// TODO: Implement different styles of following: Look ahead, sliding, sliding window
follow: bool = false,
graph_opts: Graph.ViewOptions = .{},
sync_controls: bool = false,
marked_ranges: std.BoundedArray(MarkedRange, 32) = .{},
markers: std.BoundedArray(f64, max_markers) = .{},
transforms: BoundedTransformsArray = .{},
@ -1787,7 +1786,7 @@ fn exportProject(self: *App) !void {
{
try writer.writeAll("Pipete Solution:\n");
try writer.writeAll(self.project.pipete_solution.notes.items);
try writer.writeAll(self.project.pipete_solution.items);
try writer.writeAll("\n");
}
@ -1796,6 +1795,8 @@ fn exportProject(self: *App) !void {
try writer.writeAll(self.project.notes.items);
try writer.writeAll("\n");
}
// TODO: export channels
}
pub fn tick(self: *App) !void {

View File

@ -31,21 +31,15 @@ pub const ViewAxisPosition = struct {
}
fn get(optional_self: *?ViewAxisPosition, project: *App.Project, view_id: Id, axis: UI.Axis) ?f64 {
_ = project;
const self = optional_self.* orelse return null;
if (self.axis != axis) return null;
const view = project.views.get(view_id) orelse return null;
if (view.sync_controls) {
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;
}
@ -242,39 +236,21 @@ pub fn pushViewMove(self: *System, view_id: Id, x_range: RangeF64, y_range: Rang
}
}
var sync_controls = false;
if (self.project.views.get(view_id)) |view| {
sync_controls = view.sync_controls;
}
var view_ids: std.BoundedArray(Id, constants.max_views) = .{};
if (sync_controls) {
var iter = self.project.views.idIterator();
while (iter.next()) |id| {
if (self.project.views.get(id).?.sync_controls) {
view_ids.appendAssumeCapacity(id);
}
}
} else {
view_ids.appendAssumeCapacity(view_id);
}
for (view_ids.constSlice()) |id| {
var command: *Command = undefined;
if (frame.findCommandByView(id)) |prev_command| {
if (frame.findCommandByView(view_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;
if (self.project.views.get(view_id)) |view| {
const view_rect = &view.graph_opts;
command = frame.commands.addOneAssumeCapacity();
command.* = Command{
.move_and_zoom = .{
.view_id = id,
.view_id = view_id,
.before_x = view_rect.x_range,
.before_y = view_rect.y_range,
.x = x_range,
@ -283,7 +259,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 {

View File

@ -17,8 +17,6 @@ const Id = App.Id;
const remap = utils.remap;
const assert = std.debug.assert;
const ruler_size = UI.Sizing.initFixed(.{ .pixels = 32 });
pub const ZoomStart = UIViewRuler.ZoomStart;
pub const Context = struct {
@ -236,16 +234,6 @@ fn showToolbar(ctx: Context, view_id: Id) void {
view_name = std.fs.path.stem(file.path);
}
if (view.sync_controls) {
const btn = ui.button(ui.keyFromString("Disable sync"));
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| {
_ = ui.createBox(.{
.size_x = UI.Sizing.initGrowFull()
@ -314,14 +302,14 @@ pub fn show(ctx: Context, view_id: Id, height: UI.Sizing) !Result {
const container = ui.createBox(.{
.layout_direction = .left_to_right,
.size_x = UI.Sizing.initGrowFull(),
.size_y = ruler_size,
.size_y = UIViewRuler.ruler_size_y,
});
container.beginChildren();
defer container.endChildren();
_ = ui.createBox(.{
.size_x = ruler_size,
.size_y = ruler_size,
.size_x = UIViewRuler.ruler_size_x,
.size_y = UIViewRuler.ruler_size_y,
.background = srcery.hard_black,
});

View File

@ -6,6 +6,7 @@ const RangeF64 = @import("../range.zig").RangeF64;
const srcery = @import("../srcery.zig");
const utils = @import("../utils.zig");
const constants = @import("../constants.zig");
const Assets = @import("../assets.zig");
const ViewControlsSystem = @import("./systems/view_controls.zig");
@ -13,7 +14,8 @@ const Id = App.Id;
const remap = utils.remap;
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 {
project: *App.Project,
@ -57,11 +59,13 @@ const DrawContext = struct {
available_range: RangeF64,
axis: UI.Axis,
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 {
const view = project.views.get(view_id).?;
return DrawContext{
.project = project,
.one_unit = switch (axis) {
.X => project.getSampleRate(),
.Y => 1
@ -159,33 +163,43 @@ pub fn createBox(ctx: Context, key: UI.Key, axis: UI.Axis) *UI.Box {
});
if (axis == .X) {
ruler.size.x = UI.Sizing.initGrowFull();
ruler.size.y = ruler_size;
ruler.size.y = ruler_size_y;
} else {
ruler.size.x = ruler_size;
ruler.size.x = ruler_size_x;
ruler.size.y = UI.Sizing.initGrowFull();
}
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);
} 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));
ctx.rect = box.rect();
ctx.drawLine(ctx.available_range.lower, 1, srcery.yellow);
ctx.drawLine(ctx.available_range.upper, 1, srcery.yellow);
if (ctx.available_range.hasExclusive(0)) {
ctx.drawLine(0, 0.75, srcery.yellow);
}
// if (ctx.available_range.hasExclusive(0)) {
// 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;
}
while (ctx.render_range.size() > 50*one_unit) {
while (ctx.render_range.size() > 10*one_unit) {
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 + 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 {

View File

@ -118,9 +118,13 @@ pub fn main() !void {
if (app_config_dir.openFile("config.bin", .{})) |save_file| {
defer save_file.close();
app.loadProject(save_file) catch |e| {
log.err("Failed to load project: {}", .{e});
};
_ = try app.addView(.{
.file = try app.addFile("./samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin")
});
// app.loadProject(save_file) catch |e| {
// log.err("Failed to load project: {}", .{e});
// };
} else |e| switch (e) {
error.FileNotFound => {},
else => return e

View File

@ -525,12 +525,6 @@ fn showViewSettings(self: *MainScreen, view_id: Id) !void {
_ = ui.createBox(.{ .size_y = UI.Sizing.initFixedPixels(ui.rem(1)) });
}
_ = ui.checkbox(.{
.value = &view.sync_controls,
.label = "Sync controls"
});
switch (view.reference) {
.channel => |channel_id| {
const channel = project.channels.get(channel_id).?;

View File

@ -519,7 +519,7 @@ pub const Box = struct {
pub const Draw = struct {
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;
@ -1828,7 +1828,7 @@ fn drawBox(self: *UI, box: *Box, on_top_pass: ?bool) void {
}
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();