add breakpoints to view movement undo system
This commit is contained in:
parent
faa0a534d5
commit
12620714ed
@ -51,23 +51,23 @@ pub const ViewAxisPosition = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Command = struct {
|
pub const Command = union(enum) {
|
||||||
view_id: Id,
|
breakpoint,
|
||||||
action: union(enum) {
|
move_and_zoom: struct {
|
||||||
move_and_zoom: struct {
|
view_id: Id,
|
||||||
before_x: RangeF64,
|
before_x: RangeF64,
|
||||||
before_y: RangeF64,
|
before_y: RangeF64,
|
||||||
x: RangeF64,
|
x: RangeF64,
|
||||||
y: RangeF64
|
y: RangeF64
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
fn apply(self: *const Command, system: *System) void {
|
fn apply(self: *const Command, system: *System) void {
|
||||||
const project = system.project;
|
const project = system.project;
|
||||||
const view = project.views.get(self.view_id) orelse return;
|
|
||||||
|
|
||||||
switch (self.action) {
|
switch (self.*) {
|
||||||
|
.breakpoint => {},
|
||||||
.move_and_zoom => |move_and_zoom| {
|
.move_and_zoom => |move_and_zoom| {
|
||||||
|
const view = project.views.get(move_and_zoom.view_id) orelse return;
|
||||||
const view_rect = &view.graph_opts;
|
const view_rect = &view.graph_opts;
|
||||||
view_rect.x_range = move_and_zoom.x;
|
view_rect.x_range = move_and_zoom.x;
|
||||||
view_rect.y_range = move_and_zoom.y;
|
view_rect.y_range = move_and_zoom.y;
|
||||||
@ -78,10 +78,11 @@ pub const Command = struct {
|
|||||||
|
|
||||||
fn undo(self: *const Command, system: *System) void {
|
fn undo(self: *const Command, system: *System) void {
|
||||||
const project = system.project;
|
const project = system.project;
|
||||||
const view = project.views.get(self.view_id) orelse return;
|
|
||||||
|
|
||||||
switch (self.action) {
|
switch (self.*) {
|
||||||
|
.breakpoint => {},
|
||||||
.move_and_zoom => |move_and_zoom| {
|
.move_and_zoom => |move_and_zoom| {
|
||||||
|
const view = project.views.get(move_and_zoom.view_id) orelse return;
|
||||||
const view_rect = &view.graph_opts;
|
const view_rect = &view.graph_opts;
|
||||||
view_rect.x_range = move_and_zoom.before_x;
|
view_rect.x_range = move_and_zoom.before_x;
|
||||||
view_rect.y_range = move_and_zoom.before_y;
|
view_rect.y_range = move_and_zoom.before_y;
|
||||||
@ -95,8 +96,9 @@ pub const CommandFrame = struct {
|
|||||||
commands: std.BoundedArray(Command, constants.max_views) = .{},
|
commands: std.BoundedArray(Command, constants.max_views) = .{},
|
||||||
|
|
||||||
fn findCommandByView(self: *CommandFrame, view_id: Id) ?*Command {
|
fn findCommandByView(self: *CommandFrame, view_id: Id) ?*Command {
|
||||||
for (self.commands.slice()) |*command| {
|
const commands: []Command = self.commands.slice();
|
||||||
if (command.view_id.eql(view_id)) {
|
for (commands) |*command| {
|
||||||
|
if (command.* == .move_and_zoom and command.move_and_zoom.view_id.eql(view_id)) {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,6 +119,16 @@ pub const CommandFrame = struct {
|
|||||||
command.undo(system);
|
command.undo(system);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hasBreakpoint(self: *const CommandFrame) bool {
|
||||||
|
const commands: []const Command = self.commands.constSlice();
|
||||||
|
for (commands) |*command| {
|
||||||
|
if (command.* == .breakpoint) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CommandFrameArray = std.BoundedArray(CommandFrame, 64);
|
pub const CommandFrameArray = std.BoundedArray(CommandFrame, 64);
|
||||||
@ -146,6 +158,7 @@ fn pushCommandFrame(self: *System) *CommandFrame {
|
|||||||
|
|
||||||
var frame = self.undo_stack.addOneAssumeCapacity();
|
var frame = self.undo_stack.addOneAssumeCapacity();
|
||||||
frame.updated_at_ns = std.time.nanoTimestamp();
|
frame.updated_at_ns = std.time.nanoTimestamp();
|
||||||
|
frame.commands.len = 0;
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,9 +170,19 @@ fn lastCommandFrame(self: *System) ?*CommandFrame {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pushBreakpoint(self: *System) void {
|
||||||
|
if (self.lastCommandFrame()) |last_frame| {
|
||||||
|
// No need to have 2 break points in a row
|
||||||
|
if (last_frame.hasBreakpoint()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const frame = self.pushCommandFrame();
|
||||||
|
frame.commands.appendAssumeCapacity(.{ .breakpoint = {} });
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pushViewMove(self: *System, view_id: Id, x_range: RangeF64, y_range: RangeF64) void {
|
pub fn pushViewMove(self: *System, view_id: Id, x_range: RangeF64, y_range: RangeF64) void {
|
||||||
|
|
||||||
|
|
||||||
var frame: *CommandFrame = undefined;
|
var frame: *CommandFrame = undefined;
|
||||||
{
|
{
|
||||||
var push_new_command = true;
|
var push_new_command = true;
|
||||||
@ -204,8 +227,8 @@ pub fn pushViewMove(self: *System, view_id: Id, x_range: RangeF64, y_range: Rang
|
|||||||
if (frame.findCommandByView(id)) |prev_command| {
|
if (frame.findCommandByView(id)) |prev_command| {
|
||||||
command = prev_command;
|
command = prev_command;
|
||||||
|
|
||||||
command.action.move_and_zoom.x = x_range;
|
command.move_and_zoom.x = x_range;
|
||||||
command.action.move_and_zoom.y = y_range;
|
command.move_and_zoom.y = y_range;
|
||||||
} else {
|
} else {
|
||||||
const view = self.project.views.get(view_id) orelse continue;
|
const view = self.project.views.get(view_id) orelse continue;
|
||||||
const view_rect = &view.graph_opts;
|
const view_rect = &view.graph_opts;
|
||||||
@ -213,14 +236,12 @@ pub fn pushViewMove(self: *System, view_id: Id, x_range: RangeF64, y_range: Rang
|
|||||||
command = frame.commands.addOneAssumeCapacity();
|
command = frame.commands.addOneAssumeCapacity();
|
||||||
|
|
||||||
command.* = Command{
|
command.* = Command{
|
||||||
.view_id = id,
|
.move_and_zoom = .{
|
||||||
.action = .{
|
.view_id = id,
|
||||||
.move_and_zoom = .{
|
.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,
|
.y = y_range
|
||||||
.y = y_range
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -240,11 +261,15 @@ pub fn pushViewMoveAxis(self: *System, view_id: Id, axis: UI.Axis, view_range: R
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn undoLastMove(self: *System) void {
|
pub fn undoLastMove(self: *System) void {
|
||||||
const frame = self.undo_stack.popOrNull() orelse return;
|
while (self.undo_stack.popOrNull()) |frame| {
|
||||||
|
frame.undo(self);
|
||||||
|
|
||||||
frame.undo(self);
|
self.last_applied_command = @min(self.last_applied_command, self.undo_stack.len);
|
||||||
|
|
||||||
self.last_applied_command = @min(self.last_applied_command, self.undo_stack.len);
|
if (!frame.hasBreakpoint()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn applyCommands(self: *System) void {
|
pub fn applyCommands(self: *System) void {
|
||||||
|
@ -100,6 +100,10 @@ fn showGraph(ctx: Context, view_id: Id) *UI.Box {
|
|||||||
ctx.view_controls.pushViewMove(view_id, view.available_x_range, view.available_y_range);
|
ctx.view_controls.pushViewMove(view_id, view.available_x_range, view.available_y_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (signal.flags.contains(.left_released)) {
|
||||||
|
ctx.view_controls.pushBreakpoint();
|
||||||
|
}
|
||||||
|
|
||||||
view.graph_cache.min_max_cache = app.getViewMinMaxCache(view_id);
|
view.graph_cache.min_max_cache = app.getViewMinMaxCache(view_id);
|
||||||
|
|
||||||
Graph.drawCached(&view.graph_cache, graph_box.persistent.size, view_opts.*, samples);
|
Graph.drawCached(&view.graph_cache, graph_box.persistent.size, view_opts.*, samples);
|
||||||
|
Loading…
Reference in New Issue
Block a user