add labels to ruler
This commit is contained in:
parent
fdf6001068
commit
ecea2b513a
@ -854,7 +854,6 @@ pub const View = struct {
|
|||||||
// TODO: Implement different styles of following: Look ahead, sliding, sliding window
|
// TODO: Implement different styles of following: Look ahead, sliding, sliding window
|
||||||
follow: bool = false,
|
follow: bool = false,
|
||||||
graph_opts: Graph.ViewOptions = .{},
|
graph_opts: Graph.ViewOptions = .{},
|
||||||
sync_controls: bool = false,
|
|
||||||
marked_ranges: std.BoundedArray(MarkedRange, 32) = .{},
|
marked_ranges: std.BoundedArray(MarkedRange, 32) = .{},
|
||||||
markers: std.BoundedArray(f64, max_markers) = .{},
|
markers: std.BoundedArray(f64, max_markers) = .{},
|
||||||
transforms: BoundedTransformsArray = .{},
|
transforms: BoundedTransformsArray = .{},
|
||||||
@ -1787,7 +1786,7 @@ fn exportProject(self: *App) !void {
|
|||||||
|
|
||||||
{
|
{
|
||||||
try writer.writeAll("Pipete Solution:\n");
|
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");
|
try writer.writeAll("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1796,6 +1795,8 @@ fn exportProject(self: *App) !void {
|
|||||||
try writer.writeAll(self.project.notes.items);
|
try writer.writeAll(self.project.notes.items);
|
||||||
try writer.writeAll("\n");
|
try writer.writeAll("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: export channels
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(self: *App) !void {
|
pub fn tick(self: *App) !void {
|
||||||
|
@ -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;
|
||||||
@ -242,39 +236,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 +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 {
|
pub fn pushViewMoveAxis(self: *System, view_id: Id, axis: UI.Axis, view_range: RangeF64) void {
|
||||||
|
@ -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 {
|
||||||
@ -236,16 +234,6 @@ 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) {
|
|
||||||
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| {
|
if (view_name) |text| {
|
||||||
_ = ui.createBox(.{
|
_ = ui.createBox(.{
|
||||||
.size_x = UI.Sizing.initGrowFull()
|
.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(.{
|
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);
|
||||||
|
} 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 {
|
||||||
|
10
src/main.zig
10
src/main.zig
@ -118,9 +118,13 @@ 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| {
|
|
||||||
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) {
|
} else |e| switch (e) {
|
||||||
error.FileNotFound => {},
|
error.FileNotFound => {},
|
||||||
else => return e
|
else => return e
|
||||||
|
@ -525,12 +525,6 @@ fn showViewSettings(self: *MainScreen, view_id: Id) !void {
|
|||||||
_ = ui.createBox(.{ .size_y = UI.Sizing.initFixedPixels(ui.rem(1)) });
|
_ = ui.createBox(.{ .size_y = UI.Sizing.initFixedPixels(ui.rem(1)) });
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = ui.checkbox(.{
|
|
||||||
.value = &view.sync_controls,
|
|
||||||
.label = "Sync controls"
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
switch (view.reference) {
|
switch (view.reference) {
|
||||||
.channel => |channel_id| {
|
.channel => |channel_id| {
|
||||||
const channel = project.channels.get(channel_id).?;
|
const channel = project.channels.get(channel_id).?;
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user