added scrollable code
This commit is contained in:
166
src/root.zig
166
src/root.zig
@@ -176,14 +176,15 @@ pub const Colour = struct {
|
||||
a: u8 = 255,
|
||||
};
|
||||
|
||||
const Dir = enum {
|
||||
x,
|
||||
y,
|
||||
};
|
||||
|
||||
pub const Scrollable = struct {
|
||||
offset: *Real,
|
||||
dir: Dir,
|
||||
offset: *Pos,
|
||||
child_size: Rect = .{},
|
||||
scroll_amount: f32 = 10.0,
|
||||
dir: enum {
|
||||
x,
|
||||
y,
|
||||
// both,
|
||||
},
|
||||
};
|
||||
|
||||
pub const MouseState = struct {
|
||||
@@ -191,6 +192,7 @@ pub const MouseState = struct {
|
||||
left: bool,
|
||||
right: bool,
|
||||
middle: bool,
|
||||
scroll_delta: Pos,
|
||||
};
|
||||
|
||||
pub fn pointinRect(point: Pos, rect_pos: Pos, rect: Rect) bool {
|
||||
@@ -238,12 +240,12 @@ pub fn Shoots(
|
||||
try printWithLevel(writer, level + 1, "pos : {any},\n", .{node.element.pos});
|
||||
try printWithLevel(writer, level + 1, "on_click : {?},\n", .{node.element.on_click});
|
||||
try printWithLevel(writer, level + 1, "rect : {any},\n", .{node.element.rect});
|
||||
try printWithLevel(writer, level + 1, "style : .{{\n", .{});
|
||||
try printWithLevel(writer, level + 1, "on_click : {any},\n", .{node.element.on_click});
|
||||
try printWithLevel(writer, level + 1, "allow_on_click_when_occluded : {any},\n", .{node.element.allow_on_click_when_occluded});
|
||||
try printWithLevel(writer, level + 1, "on_hover : {any},\n", .{node.element.on_hover});
|
||||
try printWithLevel(writer, level + 1, "allow_on_hover_when_occluded : {any},\n", .{node.element.allow_on_hover_when_occluded});
|
||||
try printWithLevel(writer, level + 1, "scrollable : {?},\n", .{node.element.scrollable});
|
||||
try printWithLevel(writer, level + 1, "style : .{{\n", .{});
|
||||
try node.element.style.printStyle(writer, level + 1);
|
||||
try printWithLevel(writer, level + 1, "children : {{\n", .{});
|
||||
for (node.element.children, 0..) |_, i| {
|
||||
@@ -301,8 +303,8 @@ pub fn Shoots(
|
||||
rect,
|
||||
text,
|
||||
texture,
|
||||
// clip_start,
|
||||
// clip_end,
|
||||
clip_start,
|
||||
clip_end,
|
||||
};
|
||||
|
||||
pub const RenderCommand = union(RenderCommandType) {
|
||||
@@ -323,13 +325,16 @@ pub fn Shoots(
|
||||
z_index: usize = 0,
|
||||
pos: Pos,
|
||||
},
|
||||
// clip_start: struct {
|
||||
// pos: Pos,
|
||||
// z_index: usize = 0,
|
||||
// rect: Rect,
|
||||
// rounding: ?Real,
|
||||
// },
|
||||
// clip_end: struct {},
|
||||
clip_start: struct {
|
||||
pos: Pos,
|
||||
z_index: usize = 0,
|
||||
rect: Rect,
|
||||
// might allow rounded rectangles for clipping,
|
||||
// hover this would require the user to implement a
|
||||
// stencil buffer and that would be annoying
|
||||
// rounding: ?Real,
|
||||
},
|
||||
clip_end: struct {},
|
||||
};
|
||||
|
||||
pub inline fn ElementWborder(
|
||||
@@ -420,14 +425,49 @@ pub fn Shoots(
|
||||
// std.debug.print("parent.element.rect.w : {}\n", .{parent.element.rect.w});
|
||||
},
|
||||
.texture => {
|
||||
std.debug.print("before {any}\n", .{parent.element.rect});
|
||||
parent.element.rect.h += node.texture.rect.h;
|
||||
parent.element.rect.w += node.texture.rect.w;
|
||||
std.debug.print("after {any}\n", .{parent.element.rect});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn computeSizes(node: *Node, parent: *Node) void {
|
||||
switch (node.*) {
|
||||
.element => {
|
||||
// std.debug.print("before {s} {}\n", .{ node.element.name, node.element.rect });
|
||||
// std.debug.print("parent name : {s}\n", .{parent.element.name});
|
||||
|
||||
const size = node.element.rect;
|
||||
|
||||
for (node.element.children, 0..) |_, i| {
|
||||
computeSizes(@constCast(&node.element.children[i]), node);
|
||||
}
|
||||
|
||||
// cheaters way to beat the fence post problem
|
||||
// TODO fix this
|
||||
switch (node.element.style.layout) {
|
||||
.right_to_left => node.element.rect.w -= node.element.style.child_gap,
|
||||
.top_to_bottom => node.element.rect.h -= node.element.style.child_gap,
|
||||
}
|
||||
if (node.element.scrollable) |scroll| {
|
||||
// have to remove the parents size
|
||||
node.element.scrollable.?.child_size = node.element.rect;
|
||||
node.element.scrollable.?.child_size.w -= size.w;
|
||||
node.element.scrollable.?.child_size.h -= size.h;
|
||||
|
||||
switch (scroll.dir) {
|
||||
// .both => node.element.rect = size, // retain size
|
||||
.x => node.element.rect.w = size.w, // scroll in the x then the hieght stays the same
|
||||
.y => node.element.rect.h = size.h, // scroll in the y then the width stays the same
|
||||
}
|
||||
}
|
||||
// std.debug.print("after {s} {}\n", .{ node.element.name, node.element.rect });
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
closeElement(node, parent);
|
||||
}
|
||||
|
||||
fn deepCloneHelper(node: Node, node_location: *Node, alloc: std.mem.Allocator) !void {
|
||||
// std.debug.print("nodeloc : {}\n", .{node_location});
|
||||
node_location.* = node;
|
||||
@@ -473,15 +513,26 @@ pub fn Shoots(
|
||||
switch (node) {
|
||||
.element => {
|
||||
// std.debug.print("parent name : {s}\n", .{parent.element.name});
|
||||
try command_list.append(alloc, .{
|
||||
.rect = .{
|
||||
.colour = node.element.style.background_colour,
|
||||
.pos = node.element.pos,
|
||||
.rect = node.element.rect,
|
||||
.rounding = node.element.style.rounded,
|
||||
.z_index = node.element.z_index,
|
||||
},
|
||||
});
|
||||
|
||||
if (node.element.scrollable) |_| {
|
||||
try command_list.append(alloc, .{
|
||||
.clip_start = .{
|
||||
.rect = node.element.rect,
|
||||
.z_index = node.element.z_index,
|
||||
.pos = node.element.pos,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
try command_list.append(alloc, .{
|
||||
.rect = .{
|
||||
.colour = node.element.style.background_colour,
|
||||
.pos = node.element.pos,
|
||||
.rect = node.element.rect,
|
||||
.rounding = node.element.style.rounded,
|
||||
.z_index = node.element.z_index,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
for (node.element.children, 0..) |_, i| {
|
||||
switch (node.element.children[i]) {
|
||||
@@ -500,6 +551,12 @@ pub fn Shoots(
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
if (node.element.scrollable) |_| {
|
||||
try command_list.append(alloc, .{
|
||||
.clip_end = .{},
|
||||
});
|
||||
}
|
||||
},
|
||||
else => return, // the commands get created above, since the text and texture need a pos
|
||||
// but they dont have the pos one the parent has it
|
||||
@@ -512,27 +569,6 @@ pub fn Shoots(
|
||||
return render_commands;
|
||||
}
|
||||
|
||||
fn computeSizes(node: *Node, parent: *Node) void {
|
||||
switch (node.*) {
|
||||
.element => {
|
||||
// std.debug.print("parent name : {s}\n", .{parent.element.name});
|
||||
|
||||
for (node.element.children, 0..) |_, i| {
|
||||
computeSizes(@constCast(&node.element.children[i]), node);
|
||||
}
|
||||
|
||||
// cheaters way to beat the fence post problem
|
||||
// TODO fix this
|
||||
switch (node.element.style.layout) {
|
||||
.right_to_left => node.element.rect.w -= node.element.style.child_gap,
|
||||
.top_to_bottom => node.element.rect.h -= node.element.style.child_gap,
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
closeElement(node, parent);
|
||||
}
|
||||
|
||||
fn filterGrowableChildren(index: *usize, node: Node) ?*Ele {
|
||||
switch (node) {
|
||||
.element => {
|
||||
@@ -758,6 +794,14 @@ pub fn Shoots(
|
||||
fn computeChildernsPostions(ele: *Ele) void {
|
||||
const layout_style = ele.style.layout;
|
||||
var children = @constCast(ele.children);
|
||||
const scroll_offset: Pos = blk: {
|
||||
if (ele.scrollable) |scroll| {
|
||||
const scroll_offset = scroll.offset.*;
|
||||
break :blk scroll_offset;
|
||||
}
|
||||
|
||||
break :blk .{};
|
||||
};
|
||||
|
||||
switch (layout_style) {
|
||||
.right_to_left => {
|
||||
@@ -767,8 +811,8 @@ pub fn Shoots(
|
||||
switch (ele.children[i]) {
|
||||
.element => {
|
||||
// off set it by the parent
|
||||
children[i].element.pos.x += ele.pos.x + ele.style.padding.left + off_set_left;
|
||||
children[i].element.pos.y += ele.pos.y + ele.style.padding.top;
|
||||
children[i].element.pos.x += ele.pos.x + ele.style.padding.left + off_set_left - scroll_offset.x;
|
||||
children[i].element.pos.y += ele.pos.y + ele.style.padding.top - scroll_offset.y;
|
||||
off_set_left += children[i].element.rect.w + child_gap;
|
||||
// add
|
||||
},
|
||||
@@ -783,8 +827,8 @@ pub fn Shoots(
|
||||
switch (ele.children[i]) {
|
||||
.element => {
|
||||
// off set it by the parent
|
||||
children[i].element.pos.x += ele.pos.x + ele.style.padding.left;
|
||||
children[i].element.pos.y += ele.pos.y + ele.style.padding.top + offset_top;
|
||||
children[i].element.pos.x += ele.pos.x + ele.style.padding.left - scroll_offset.x;
|
||||
children[i].element.pos.y += ele.pos.y + ele.style.padding.top + offset_top - scroll_offset.y;
|
||||
offset_top += children[i].element.rect.h + child_gap;
|
||||
// add
|
||||
},
|
||||
@@ -843,6 +887,22 @@ pub fn Shoots(
|
||||
.element => |e| {
|
||||
// std.debug.print("clicked : {} hovered node name : {s}\n", .{ clicked, e.name });
|
||||
|
||||
// TODO fix when another scrollable contaier occludes the other one
|
||||
if (current_node.element.scrollable) |scroll| {
|
||||
current_node.element.scrollable.?.offset.x += mouse_state.scroll_delta.x * scroll.child_size.w / current_node.element.rect.w;
|
||||
current_node.element.scrollable.?.offset.y += mouse_state.scroll_delta.y * scroll.child_size.h / current_node.element.rect.h;
|
||||
|
||||
// fixes being able to scroll past the min value
|
||||
if (scroll.offset.x < 0) current_node.element.scrollable.?.offset.x = 0;
|
||||
if (scroll.offset.y < 0) current_node.element.scrollable.?.offset.y = 0;
|
||||
|
||||
// fixes being able to scroll past the max value
|
||||
if (scroll.offset.x > scroll.child_size.w - current_node.element.rect.w)
|
||||
current_node.element.scrollable.?.offset.x = scroll.child_size.w - current_node.element.rect.w;
|
||||
if (scroll.offset.y > scroll.child_size.h - current_node.element.rect.h)
|
||||
current_node.element.scrollable.?.offset.y = scroll.child_size.h - current_node.element.rect.h;
|
||||
}
|
||||
|
||||
if (e.on_hover != null and e.allow_on_hover_when_occluded) {
|
||||
needs_redraw |= node.element.on_hover.?.func(&node.element, mouse_state, node.element.on_click.?.data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user