Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions app/layout/Region.zig
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ resize: bool = false,
forget_when_empty: bool = false,
/// How this place lays its children.
dir: dvui.enums.Direction = .vertical,
/// This frame's content size, in points. A menu split halves one axis.
/// This frame's border box, in its parent's units (points, unless something above it scales):
/// the reach a split of it halves along one axis.
size: dvui.Size = .{},
/// This frame's border in physical pixels, for hit-testing a view drag.
bounds: dvui.Rect.Physical = .{},
Expand Down Expand Up @@ -580,8 +581,7 @@ pub fn init(self: *Layout, src: std.builtin.SourceLocation, init_opts: InitOptio
const box = dvui.box(src, .{ .dir = init_opts.dir }, box_opts);
if (init_opts.resize) Split.recordEdges(id, box.data(), axis);
if (init_opts.name.len > 0) {
const cr = box.data().contentRect();
self.state.setPlaceMetrics(init_opts.name, .{ .w = cr.w, .h = cr.h }, box.data().borderRectScale().r);
self.state.setPlaceMetrics(init_opts.name, box.data());
core.anchor.mark(box.data(), "region:{s}", .{init_opts.name});
}
self.containers[self.depth] = .{
Expand Down Expand Up @@ -1304,8 +1304,7 @@ fn drawTreeNode(
.forget_when_empty = true,
.dir = b.dir,
});
const cr = box.data().contentRect();
self.state.setPlaceMetrics(b.origin, .{ .w = cr.w, .h = cr.h }, box.data().borderRectScale().r);
self.state.setPlaceMetrics(b.origin, box.data());
}
self.containers[self.depth] = .{
.dir = b.dir,
Expand Down Expand Up @@ -1354,8 +1353,7 @@ pub fn fillInBox(self: *Layout, init_opts: InitOptions, box: *dvui.BoxWidget) !v
.dir = init_opts.dir,
});

const cr = box.data().contentRect();
self.state.setPlaceMetrics(init_opts.name, .{ .w = cr.w, .h = cr.h }, box.data().borderRectScale().r);
self.state.setPlaceMetrics(init_opts.name, box.data());

if (self.depth >= Layout.max_nesting) return;
self.containers[self.depth] = .{
Expand Down
10 changes: 7 additions & 3 deletions app/layout/State.zig
Original file line number Diff line number Diff line change
Expand Up @@ -791,13 +791,17 @@ fn forgetWidgetSize(id: dvui.Id) void {
dvui.dataRemove(null, id, "_chooser_press");
}

pub fn setPlaceMetrics(self: *State, name: []const u8, size: dvui.Size, bounds: dvui.Rect.Physical) void {
/// Where place `name` was drawn this frame, from the box it was drawn in: its border box, in
/// points and in physical pixels. The border box, not the content: a split's extent is the whole
/// reach of the place it opens, padding included, so a split measured from the content rect gave
/// a carded place's new half the card's padding twice over.
pub fn setPlaceMetrics(self: *State, name: []const u8, data: *const dvui.WidgetData) void {
var i = self.regions_building.items.len;
while (i > 0) {
i -= 1;
if (!std.mem.eql(u8, self.regions_building.items[i].name, name)) continue;
self.regions_building.items[i].size = size;
self.regions_building.items[i].bounds = bounds;
self.regions_building.items[i].size = data.borderRect().size();
self.regions_building.items[i].bounds = data.borderRectScale().r;
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/layout/ViewDrag.zig
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ pub const Target = struct {
/// Interned, so it outlives the frame the map was taken on.
name: []const u8,
bounds: dvui.Rect.Physical,
/// Content size in points, for the extent a landing split settles at.
/// Border-box size in points (`Region.size`), for the extent a landing split settles at.
size: dvui.Size,
/// The window it is drawn in (`Region.layer`): 0 the main window, `n` the `n`th float.
layer: u16 = 0,
Expand Down
67 changes: 67 additions & 0 deletions tests/integration.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2797,6 +2797,73 @@ test "a fizzy Main split keeps the workspace on the leftover side" {
try std.testing.expectEqual(@as(usize, 0), created.len);
}

/// fizzy's own Main: a carded place that hands its card to its panes, in a column of the window.
const ColumnCardFrame = struct {
var editor: ?*fizzy.Editor = null;

fn frame() anyerror!dvui.App.Result {
const e = editor.?;
var layout = fizzy.Editor.Layout.init(&e.app.host, &e.app.layout, e.app.gpa, dvui.currentWindow().arena());
layout.card = .{ .background = true, .padding = .all(8) };
{
var column = try layout.region(@src(), .{ .dir = .vertical }, .{ .expand = .both });
defer column.deinit();
var main = try layout.region(@src(), .{ .name = "Main", .keywords = fizzy.sdk.keywords.ide.main, .card = true, .pane_cards = true }, .{ .expand = .both });
defer main.deinit();
}
e.app.layout.publishRegions();
return .ok;
}

/// What the place takes on screen: its border box in physical pixels, measured where it was
/// drawn rather than read back from the `size` a split halves.
fn sizeOf(e: *fizzy.Editor, name: []const u8) !dvui.Size {
for (e.app.layout.regions.items) |r| {
if (std.mem.eql(u8, r.name, name)) return .{ .w = r.bounds.w, .h = r.bounds.h };
}
return error.TestExpectedEqual;
}
};

// A split's extent is the new half's whole reach, card and all. Measured from the place's content
// instead, every split of a carded place came out uneven by the card's padding, twice over.
test "a split of a carded place, and of its new half, opens even halves" {
var ctx = try shim.init(std.testing.allocator);
defer ctx.deinit(std.testing.allocator);

const editor = ctx.editor;
editor.app.gpa = std.testing.allocator;
defer editor.app.layout.regions.deinit(editor.app.gpa);
defer editor.app.layout.regions_building.deinit(editor.app.gpa);
defer editor.app.layout.deinitExtents(editor.app.gpa);
defer editor.app.layout.deinitAssignments(editor.app.gpa);
defer editor.app.layout.deinitQualified(editor.app.gpa);

ColumnCardFrame.editor = editor;
defer ColumnCardFrame.editor = null;

try dvui.testing.settle(ColumnCardFrame.frame);
{
var layout = fizzy.Editor.Layout.init(&editor.app.host, &editor.app.layout, editor.app.gpa, dvui.currentWindow().arena());
try std.testing.expectEqualStrings("Main/r1", layout.splitOn("Main", .right) orelse return error.TestExpectedEqual);
}
try dvui.testing.settle(ColumnCardFrame.frame);
const left = try ColumnCardFrame.sizeOf(editor, "Main");
const right = try ColumnCardFrame.sizeOf(editor, "Main/r1");
try std.testing.expect(left.w > 40);
try std.testing.expectApproxEqAbs(left.w, right.w, 1);

{
var layout = fizzy.Editor.Layout.init(&editor.app.host, &editor.app.layout, editor.app.gpa, dvui.currentWindow().arena());
try std.testing.expectEqualStrings("Main/r1/b1", layout.splitOn("Main/r1", .bottom) orelse return error.TestExpectedEqual);
}
try dvui.testing.settle(ColumnCardFrame.frame);
const top = try ColumnCardFrame.sizeOf(editor, "Main/r1");
const bottom = try ColumnCardFrame.sizeOf(editor, "Main/r1/b1");
try std.testing.expect(top.h > 40);
try std.testing.expectApproxEqAbs(top.h, bottom.h, 1);
}

test "a view-drag split opens on the dropped edge" {
var ctx = try shim.init(std.testing.allocator);
defer ctx.deinit(std.testing.allocator);
Expand Down
Loading