apprt/gtk-ng: write back split ratio to tree

pull/8207/head
Mitchell Hashimoto 2025-08-09 12:19:03 -07:00
parent e396d9d78d
commit 34be4de018
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 49 additions and 15 deletions

View File

@ -643,15 +643,12 @@ const SplitTreeSplit = extern struct {
// widget. We assume that this widget is always a child of a
// SplitTree, we assume that our handle is valid, and we assume
// the handle is always a split node.
const split: *Surface.Tree.Split = split: {
const split_tree = ext.getAncestor(
SplitTree,
self.as(gtk.Widget),
) orelse return 0;
const tree = split_tree.getTree() orelse return 0;
// TODO: fix this constCast
break :split @constCast(&tree.nodes[priv.handle].split);
};
const split_tree = ext.getAncestor(
SplitTree,
self.as(gtk.Widget),
) orelse return 0;
const tree = split_tree.getTree() orelse return 0;
const split: *const Surface.Tree.Split = &tree.nodes[priv.handle].split;
// Current, min, and max positions as pixels.
const pos = paned.getPosition();
@ -675,6 +672,16 @@ const SplitTreeSplit = extern struct {
);
break :max gobject.ext.Value.get(&val, c_int);
};
const pos_set: bool = max: {
var val = gobject.ext.Value.new(c_int);
defer val.unset();
gobject.Object.getProperty(
paned.as(gobject.Object),
"position-set",
&val,
);
break :max gobject.ext.Value.get(&val, c_int) != 0;
};
// We don't actually use min, but we don't expect this to ever
// be non-zero, so let's add an assert to ensure that.
@ -708,13 +715,19 @@ const SplitTreeSplit = extern struct {
// If we're out of bounds, then we need to either set the position
// to what we expect OR update our expected ratio.
const desired_pos: c_int = desired_pos: {
const max_f64: f64 = @floatFromInt(max);
break :desired_pos @intFromFloat(@round(max_f64 * desired_ratio));
};
paned.setPosition(desired_pos);
// If we've never set the position, then we set it to the desired.
if (!pos_set) {
const desired_pos: c_int = desired_pos: {
const max_f64: f64 = @floatFromInt(max);
break :desired_pos @intFromFloat(@round(max_f64 * desired_ratio));
};
paned.setPosition(desired_pos);
return 0;
}
log.warn("DESIRED={} CURRENT={}", .{ desired_ratio, current_ratio });
// If we've set the position, then this is a manual human update
// and we need to write our update back to the tree.
tree.resizeInPlace(priv.handle, @floatCast(current_ratio));
return 0;
}

View File

@ -174,6 +174,27 @@ pub fn SplitTree(comptime V: type) type {
}
};
/// Resize the given node in place. The node MUST be a split (asserted).
///
/// In general, this is an immutable data structure so this is
/// heavily discouraged. However, this is provided for convenience
/// and performance reasons where its very important for GUIs to
/// update the ratio during a live resize than to redraw the entire
/// widget tree.
pub fn resizeInPlace(
self: *Self,
at: Node.Handle,
ratio: f16,
) void {
// Let's talk about this constCast. Our member are const but
// we actually always own their memory. We don't want consumers
// who directly access the nodes to be able to modify them
// (without nasty stuff like this), but given this is internal
// usage its perfectly fine to modify the node in-place.
const s: *Split = @constCast(&self.nodes[at].split);
s.ratio = ratio;
}
/// Insert another tree into this tree at the given node in the
/// specified direction. The other tree will be inserted in the
/// new direction. For example, if the direction is "right" then