diff --git a/README.md b/README.md index 78b4b14..187719e 100644 --- a/README.md +++ b/README.md @@ -37,15 +37,15 @@ pub fn main() !void { var window = try capy.Window.init(); try window.set( - capy.Column(.{ .spacing = 10 }, .{ // have 10px spacing between each column's element - capy.Row(.{ .spacing = 5 }, .{ // have 5px spacing between each row's element - capy.Button(.{ .label = "Save", .onclick = buttonClicked }), - capy.Button(.{ .label = "Run", .onclick = buttonClicked }) + capy.column(.{ .spacing = 10 }, .{ // have 10px spacing between each column's element + capy.row(.{ .spacing = 5 }, .{ // have 5px spacing between each row's element + capy.button(.{ .label = "Save", .onclick = &buttonClicked }), + capy.button(.{ .label = "Run", .onclick = &buttonClicked }) }), // Expanded means the widget will take all the space it can // in the parent container - capy.Expanded( - capy.TextArea(.{ .text = "Hello World!" }) + capy.expanded( + capy.textArea(.{ .text = "Hello World!" }) ) }) ); @@ -55,7 +55,7 @@ pub fn main() !void { capy.runEventLoop(); } -fn buttonClicked(button: *capy.Button_Impl) !void { +fn buttonClicked(button: *capy.Button) !void { std.log.info("You clicked button with text {s}", .{button.getLabel()}); } ``` diff --git a/examples/300-buttons.zig b/examples/300-buttons.zig index 7bfed67..19b70e4 100644 --- a/examples/300-buttons.zig +++ b/examples/300-buttons.zig @@ -17,11 +17,11 @@ pub fn main() !void { defer labelArena.deinit(); const labelAllocator = labelArena.child_allocator; - var row = try capy.Row(.{ .wrapping = true }, .{}); + var row = try capy.row(.{ .wrapping = true }, .{}); var i: usize = 0; while (i < NUM_BUTTONS) : (i += 1) { const buttonLabel = try std.fmt.allocPrintZ(labelAllocator, "Button #{d}", .{i}); - try row.add(capy.Button(.{ .label = buttonLabel })); + try row.add(capy.button(.{ .label = buttonLabel })); } try window.set(row); diff --git a/examples/7gui/counter.zig b/examples/7gui/counter.zig index baaf5f7..e182310 100644 --- a/examples/7gui/counter.zig +++ b/examples/7gui/counter.zig @@ -34,12 +34,12 @@ pub fn main() !void { var format = try capy.FormattedAtom(capy.internal.lasting_allocator, "{d}", .{&count}); defer format.deinit(); - try window.set(capy.Align( + try window.set(capy.alignment( .{}, - capy.Row(.{ .spacing = 5 }, .{ - capy.TextField(.{ .readOnly = true, .name = "text-field" }) + capy.row(.{ .spacing = 5 }, .{ + capy.textField(.{ .readOnly = true, .name = "text-field" }) .bind("text", format), - capy.Button(.{ .label = "Count", .onclick = increment }), + capy.button(.{ .label = "Count", .onclick = increment }), }), )); diff --git a/examples/7gui/flight-booker.zig b/examples/7gui/flight-booker.zig index c196006..3c56862 100644 --- a/examples/7gui/flight-booker.zig +++ b/examples/7gui/flight-booker.zig @@ -2,63 +2,63 @@ const std = @import("std"); const capy = @import("capy"); pub usingnamespace capy.cross_platform; -var selectedIndex: capy.Atom(usize) = capy.Atom(usize).of(0); +var selected_index: capy.Atom(usize) = capy.Atom(usize).of(0); pub fn main() !void { try capy.backend.init(); var window = try capy.Window.init(); - try window.set(capy.Column(.{}, .{ - capy.Button(.{ .label = "one-way flight", .onclick = oneWay }), - capy.Button(.{ .label = "return flight", .onclick = returnFlight }), - capy.TextField(.{ .name = "start-date", .text = "27.03.2014" }), - capy.TextField(.{ .name = "return-date", .text = "27.03.2014" }), - capy.Button(.{ .name = "book-button", .label = "Book", .onclick = bookFlight }), + try window.set(capy.column(.{}, .{ + capy.button(.{ .label = "one-way flight", .onclick = oneWay }), + capy.button(.{ .label = "return flight", .onclick = returnFlight }), + capy.textField(.{ .name = "start-date", .text = "27.03.2014" }), + capy.textField(.{ .name = "return-date", .text = "27.03.2014" }), + capy.button(.{ .name = "book-button", .label = "Book", .onclick = bookFlight }), })); window.setTitle("Book Flight"); window.show(); - const root = window.getChild().?.as(capy.Container_Impl); - const start_field = root.getChildAs(capy.TextField_Impl, "start-date").?; - const return_field = root.getChildAs(capy.TextField_Impl, "return-date").?; - const book_button = root.getChildAs(capy.Button_Impl, "book-button").?; + const root = window.getChild().?.as(capy.Container); + const start_field = root.getChildAs(capy.TextField, "start-date").?; + const return_field = root.getChildAs(capy.TextField, "return-date").?; + const book_button = root.getChildAs(capy.Button, "book-button").?; - try return_field.readOnly.dependOn(.{&selectedIndex}, &(struct { + try return_field.readOnly.dependOn(.{&selected_index}, &(struct { fn a(index: usize) bool { return index != 1; // only enabled for return flight } }.a)); // Quite literally, the 'enabled' property of button depends on start field's text and return field's text - try book_button.enabled.dependOn(.{ &start_field.text, &return_field.text }, &(struct { - fn a(start_text: []const u8, return_text: []const u8) bool { + try book_button.enabled.dependOn(.{ &start_field.text, &return_field.text, &selected_index }, &(struct { + fn a(start_text: []const u8, return_text: []const u8, index: usize) bool { const start_date = parseDate(start_text) catch return false; const return_date = parseDate(return_text) catch return false; // return date must be after departure date - return return_date > start_date; + return return_date > start_date or index == 0; } }.a)); capy.runEventLoop(); } -// TODO: switch back to *capy.Button_Impl when ziglang/zig#12325 is fixed +// TODO: switch back to *capy.Button when ziglang/zig#12325 is fixed fn oneWay(_: *anyopaque) !void { - selectedIndex.set(0); + selected_index.set(0); } -// TODO: switch back to *capy.Button_Impl when ziglang/zig#12325 is fixed +// TODO: switch back to *capy.Button when ziglang/zig#12325 is fixed fn returnFlight(_: *anyopaque) !void { - selectedIndex.set(1); + selected_index.set(1); } -// TODO: switch back to *capy.Button_Impl when ziglang/zig#12325 is fixed +// TODO: switch back to *capy.Button when ziglang/zig#12325 is fixed fn bookFlight(button_: *anyopaque) !void { - const button = @as(*capy.Button_Impl, @ptrCast(@alignCast(button_))); + const button = @as(*capy.Button, @ptrCast(@alignCast(button_))); - const root = button.getRoot().?.as(capy.Container_Impl); + const root = button.getRoot().?.as(capy.Container); _ = root; } diff --git a/examples/7gui/temperature-converter.zig b/examples/7gui/temperature-converter.zig index a1156c1..a2caf7d 100644 --- a/examples/7gui/temperature-converter.zig +++ b/examples/7gui/temperature-converter.zig @@ -14,15 +14,15 @@ pub fn main() !void { var window = try capy.Window.init(); - try window.set(capy.Align( + try window.set(capy.alignment( .{}, - capy.Row(.{ .spacing = 5 }, .{ - capy.TextField(.{}) + capy.row(.{ .spacing = 5 }, .{ + capy.textField(.{}) .bind("text", &celsius), - capy.Label(.{ .text = "Celsius =" }), - capy.TextField(.{}) + capy.label(.{ .text = "Celsius =" }), + capy.textField(.{}) .bind("text", &fahrenheit), - capy.Label(.{ .text = "Fahrenheit" }), + capy.label(.{ .text = "Fahrenheit" }), }), )); diff --git a/examples/balls.zig b/examples/balls.zig index cbfc747..11da93f 100644 --- a/examples/balls.zig +++ b/examples/balls.zig @@ -39,7 +39,7 @@ pub fn main() !void { }); } - var canvas = capy.Canvas(.{ + var canvas = capy.canvas(.{ .preferredSize = capy.Size.init(500, 500), .ondraw = @as(*const fn (*anyopaque, *capy.DrawContext) anyerror!void, @ptrCast(&onDraw)), .name = "ball-canvas", @@ -51,11 +51,11 @@ pub fn main() !void { defer totalEnergyFormat.deinit(); var window = try capy.Window.init(); - try window.set(capy.Column(.{}, .{ - capy.Label(.{ .text = "Balls with attraction and friction" }), - capy.Label(.{}) + try window.set(capy.column(.{}, .{ + capy.label(.{ .text = "Balls with attraction and friction" }), + capy.label(.{}) .bind("text", totalEnergyFormat), - capy.Align(.{}, &canvas), + capy.alignment(.{}, &canvas), })); window.setTitle("Balls"); @@ -68,7 +68,7 @@ pub fn main() !void { capy.runEventLoop(); } -fn onMouseButton(widget: *capy.Canvas_Impl, button: capy.MouseButton, pressed: bool, x: i32, y: i32) !void { +fn onMouseButton(widget: *capy.Canvas, button: capy.MouseButton, pressed: bool, x: i32, y: i32) !void { mouseX = x; mouseY = y; if (button == .Left) { @@ -90,7 +90,7 @@ fn onMouseButton(widget: *capy.Canvas_Impl, button: capy.MouseButton, pressed: b } } -fn onMouseMotion(widget: *capy.Canvas_Impl, x: i32, y: i32) !void { +fn onMouseMotion(widget: *capy.Canvas, x: i32, y: i32) !void { if (selected_ball_index != null) { mouseX = x; mouseY = y; @@ -98,7 +98,7 @@ fn onMouseMotion(widget: *capy.Canvas_Impl, x: i32, y: i32) !void { } } -fn onDraw(widget: *capy.Canvas_Impl, ctx: *capy.DrawContext) !void { +fn onDraw(widget: *capy.Canvas, ctx: *capy.DrawContext) !void { const width = widget.getWidth(); const height = widget.getHeight(); @@ -126,8 +126,8 @@ fn onDraw(widget: *capy.Canvas_Impl, ctx: *capy.DrawContext) !void { } fn simulationThread(window: *capy.Window) !void { - const root = window.getChild().?.as(capy.Container_Impl); - const canvas = root.getChild("ball-canvas").?.as(capy.Canvas_Impl); + const root = window.getChild().?.as(capy.Container); + const canvas = root.getChild("ball-canvas").?.as(capy.Canvas); while (true) { const delta = 1.0 / 60.0; diff --git a/examples/border-layout.zig b/examples/border-layout.zig index 43152bf..df17684 100644 --- a/examples/border-layout.zig +++ b/examples/border-layout.zig @@ -6,18 +6,18 @@ pub fn main() !void { try capy.backend.init(); var window = try capy.Window.init(); - try window.set(capy.Column(.{}, .{ - capy.Label(.{ .text = "Top" }), - capy.Expanded( - capy.Row(.{}, .{ - capy.Label(.{ .text = "Left" }), - capy.Expanded( - capy.Label(.{ .text = "Center" }), + try window.set(capy.column(.{}, .{ + capy.label(.{ .text = "Top", .alignment = .Center }), + capy.expanded( + capy.row(.{}, .{ + capy.label(.{ .text = "Left", .alignment = .Center }), + capy.expanded( + capy.label(.{ .text = "Center", .alignment = .Center }), ), - capy.Label(.{ .text = "Right" }), + capy.label(.{ .text = "Right", .alignment = .Center }), }), ), - capy.Label(.{ .text = "Bottom " }), + capy.label(.{ .text = "Bottom ", .alignment = .Center }), })); window.setTitle("Hello"); diff --git a/examples/calculator.zig b/examples/calculator.zig index 15e6bd7..213ac04 100644 --- a/examples/calculator.zig +++ b/examples/calculator.zig @@ -3,19 +3,14 @@ const capy = @import("capy"); pub usingnamespace capy.cross_platform; // Short names to avoid writing 'capy.' each time -const Button = capy.Button; -const Margin = capy.Margin; -const Expanded = capy.Expanded; -const Row = capy.Row; - const Allocator = std.mem.Allocator; -var computationLabel: capy.Label_Impl = undefined; +var computationLabel: capy.Label = undefined; var allocator: Allocator = undefined; -// TODO: switch back to *capy.Button_Impl when ziglang/zig#12325 is fixed +// TODO: switch back to *capy.button_Impl when ziglang/zig#12325 is fixed pub fn pressedKey(button_: *anyopaque) !void { - const button = @as(*capy.Button_Impl, @ptrCast(@alignCast(button_))); + const button = @as(*capy.Button, @ptrCast(@alignCast(button_))); const buttonLabel = button.getLabel(); const labelText = computationLabel.getText(); @@ -29,7 +24,7 @@ pub fn pressedKey(button_: *anyopaque) !void { allocator.free(labelText); } -// TODO: switch back to *capy.Button_Impl when ziglang/zig#12325 is fixed +// TODO: switch back to *capy.button_Impl when ziglang/zig#12325 is fixed pub fn erase(_: *anyopaque) !void { allocator.free(computationLabel.getText()); computationLabel.setText(""); @@ -39,7 +34,7 @@ fn findOperator(computation: []const u8, pos: usize) ?usize { return std.mem.indexOfScalarPos(u8, computation, pos, '+') orelse std.mem.indexOfScalarPos(u8, computation, pos, '-') orelse std.mem.indexOfScalarPos(u8, computation, pos, '*') orelse std.mem.indexOfScalarPos(u8, computation, pos, '/'); } -// TODO: switch back to *capy.Button_Impl when ziglang/zig#12325 is fixed +// TODO: switch back to *capy.button_Impl when ziglang/zig#12325 is fixed pub fn compute(_: *anyopaque) !void { const rawText = computationLabel.getText(); const computation = rawText; @@ -96,35 +91,37 @@ pub fn main() !void { } var window = try capy.Window.init(); - computationLabel = capy.Label(.{ .text = "", .alignment = .Left }); + computationLabel = capy.label(.{ .text = "", .alignment = .Left }); defer allocator.free(computationLabel.getText()); - try window.set(capy.Column(.{ .expand = .Fill, .spacing = 10 }, .{ + try window.set(capy.column(.{ .expand = .Fill, .spacing = 10 }, .{ &computationLabel, - Expanded(Row(.{ .expand = .Fill, .spacing = 10 }, .{ - Button(.{ .label = "7", .onclick = pressedKey }), - Button(.{ .label = "8", .onclick = pressedKey }), - Button(.{ .label = "9", .onclick = pressedKey }), - Button(.{ .label = "+", .onclick = pressedKey }), + capy.expanded(capy.row(.{ .expand = .Fill, .spacing = 10 }, .{ + capy.button(.{ .label = "7", .onclick = pressedKey }), + capy.button(.{ .label = "8", .onclick = pressedKey }), + capy.button(.{ .label = "9", .onclick = pressedKey }), + capy.button(.{ .label = "+", .onclick = pressedKey }), })), - Expanded(Row(.{ .expand = .Fill, .spacing = 10 }, .{ - Button(.{ .label = "4", .onclick = pressedKey }), - Button(.{ .label = "5", .onclick = pressedKey }), - Button(.{ .label = "6", .onclick = pressedKey }), - Button(.{ .label = "-", .onclick = pressedKey }), + capy.expanded(capy.row(.{ .expand = .Fill, .spacing = 10 }, .{ + capy.button(.{ .label = "4", .onclick = pressedKey }), + capy.button(.{ .label = "5", .onclick = pressedKey }), + capy.button(.{ .label = "6", .onclick = pressedKey }), + capy.button(.{ .label = "-", .onclick = pressedKey }), })), - Expanded(Row(.{ .expand = .Fill, .spacing = 10 }, .{ - Button(.{ .label = "1", .onclick = pressedKey }), - Button(.{ .label = "2", .onclick = pressedKey }), - Button(.{ .label = "3", .onclick = pressedKey }), - Button(.{ .label = "*", .onclick = pressedKey }), + capy.expanded(capy.row(.{ .expand = .Fill, .spacing = 10 }, .{ + capy.button(.{ .label = "1", .onclick = pressedKey }), + capy.button(.{ .label = "2", .onclick = pressedKey }), + capy.button(.{ .label = "3", .onclick = pressedKey }), + capy.button(.{ .label = "*", .onclick = pressedKey }), })), - Expanded(Row(.{ .expand = .Fill, .spacing = 10 }, .{ - Button(.{ .label = "/", .onclick = pressedKey }), - Button(.{ .label = "0", .onclick = pressedKey }), - Button(.{ .label = "CE", .onclick = erase }), - Button(.{ .label = ".", .onclick = pressedKey }), + capy.expanded(capy.row(.{ .expand = .Fill, .spacing = 10 }, .{ + capy.button(.{ .label = "/", .onclick = pressedKey }), + capy.button(.{ .label = "0", .onclick = pressedKey }), + capy.button(.{ .label = "CE", .onclick = erase }), + capy.button(.{ .label = ".", .onclick = pressedKey }), })), - Expanded(Button(.{ .label = "=", .onclick = compute })), + capy.expanded( + capy.button(.{ .label = "=", .onclick = compute }), + ), })); window.setPreferredSize(400, 500); window.setTitle("Calculator"); diff --git a/examples/colors.zig b/examples/colors.zig index d8ebc97..431600a 100644 --- a/examples/colors.zig +++ b/examples/colors.zig @@ -7,10 +7,10 @@ var random = prng.random(); pub fn animateRandomColor(button_: *anyopaque) !void { // This part is a workaround to ziglang/zig#12325 - const button: *capy.Button_Impl = @ptrCast(@alignCast(button_)); + const button: *capy.Button = @ptrCast(@alignCast(button_)); - const root = button.getRoot().?.as(capy.Container_Impl); - const rect = root.getChild("background-rectangle").?.as(capy.Rect_Impl); + const root = button.getRoot().?.as(capy.Container); + const rect = root.getChild("background-rectangle").?.as(capy.Rect); const randomColor = capy.Color{ .red = random.int(u8), .green = random.int(u8), .blue = random.int(u8) }; rect.color.animate(capy.Easings.InOut, randomColor, 1000); } @@ -21,10 +21,10 @@ pub fn main() !void { prng = std.rand.DefaultPrng.init(@as(u64, @bitCast(std.time.milliTimestamp()))); window.setPreferredSize(800, 600); - try window.set(capy.Stack(.{ - capy.Rect(.{ .name = "background-rectangle", .color = capy.Color.transparent }), - capy.Column(.{}, .{ - capy.Align(.{}, capy.Button(.{ .label = "Random color", .onclick = animateRandomColor })), + try window.set(capy.stack(.{ + capy.rect(.{ .name = "background-rectangle", .color = capy.Color.transparent }), + capy.column(.{}, .{ + capy.alignment(.{}, capy.button(.{ .label = "Random color", .onclick = animateRandomColor })), }), })); window.show(); diff --git a/examples/demo.zig b/examples/demo.zig index cecefe1..47ffa04 100644 --- a/examples/demo.zig +++ b/examples/demo.zig @@ -20,46 +20,46 @@ pub fn main() !void { var window = try capy.Window.init(); defer window.deinit(); - var someSliderValue = capy.Atom(f32).of(0); - var someSliderText = try capy.FormattedAtom(capy.internal.lasting_allocator, "{d:.1}", .{&someSliderValue}); - - try window.set(capy.Row(.{ .spacing = 0 }, .{ - capy.NavigationSidebar(.{}), - capy.Tabs(.{ - capy.Tab(.{ .label = "Border Layout" }, BorderLayoutExample()), - capy.Tab(.{ .label = "Buttons" }, capy.Column(.{}, .{ + var somesliderValue = capy.Atom(f32).of(0); + var somesliderText = try capy.FormattedAtom(capy.internal.lasting_allocator, "{d:.1}", .{&somesliderValue}); + + try window.set(capy.row(.{ .spacing = 0 }, .{ + capy.navigationSidebar(.{}), + capy.tabs(.{ + capy.tab(.{ .label = "Border Layout" }, BorderLayoutExample()), + capy.tab(.{ .label = "Buttons" }, capy.column(.{}, .{ // alignX = 0 means buttons should be aligned to the left // TODO: use constraint layout (when it's added) to make all buttons same width - capy.Align(.{ .x = 0 }, capy.Button(.{ .label = "Button", .onclick = moveButton })), - capy.Button(.{ .label = "Button (disabled)", .enabled = false }), - capy.CheckBox(.{ .label = "Checked", .checked = true }), // TODO: dynamic label based on checked - capy.CheckBox(.{ .label = "Disabled", .enabled = false }), - capy.Row(.{}, .{ - capy.Expanded(capy.Slider(.{ .min = -10, .max = 10, .step = 0.1 }) - .bind("value", &someSliderValue)), - capy.Label(.{}) - .bind("text", someSliderText), + capy.alignment(.{ .x = 0 }, capy.button(.{ .label = "Button", .onclick = moveButton })), + capy.button(.{ .label = "Button (disabled)", .enabled = false }), + capy.checkBox(.{ .label = "Checked", .checked = true }), // TODO: dynamic label based on checked + capy.checkBox(.{ .label = "Disabled", .enabled = false }), + capy.row(.{}, .{ + capy.expanded(capy.slider(.{ .min = -10, .max = 10, .step = 0.1 }) + .bind("value", &somesliderValue)), + capy.label(.{}) + .bind("text", somesliderText), }), })), - capy.Tab(.{ .label = "Rounded Rectangle" }, capy.Column(.{}, .{ - capy.Align( + capy.tab(.{ .label = "Rounded Rectangle" }, capy.column(.{}, .{ + capy.alignment( .{}, - capy.Canvas(.{ .preferredSize = capy.Size.init(100, 100), .ondraw = drawRounded }), + capy.canvas(.{ .preferredSize = capy.Size.init(100, 100), .ondraw = drawRounded }), ), - capy.Row(.{}, .{ - capy.Expanded(capy.Slider(.{ .min = 0, .max = 100, .step = 0.1 }) + capy.row(.{}, .{ + capy.expanded(capy.slider(.{ .min = 0, .max = 100, .step = 0.1 }) .bind("value", &corner_1)), - capy.Expanded(capy.Slider(.{ .min = 0, .max = 100, .step = 0.1 }) + capy.expanded(capy.slider(.{ .min = 0, .max = 100, .step = 0.1 }) .bind("value", &corner_2)), }), - capy.Row(.{}, .{ - capy.Expanded(capy.Slider(.{ .min = 0, .max = 100, .step = 0.1 }) + capy.row(.{}, .{ + capy.expanded(capy.slider(.{ .min = 0, .max = 100, .step = 0.1 }) .bind("value", &corner_3)), - capy.Expanded(capy.Slider(.{ .min = 0, .max = 100, .step = 0.1 }) + capy.expanded(capy.slider(.{ .min = 0, .max = 100, .step = 0.1 }) .bind("value", &corner_4)), }), })), - //capy.Tab(.{ .label = "Drawing" }, capy.Expanded(Drawer(.{}))), + //capy.tab(.{ .label = "Drawing" }, capy.expanded(drawer(.{}))), }), })); @@ -69,7 +69,7 @@ pub fn main() !void { } fn drawRounded(cnv: *anyopaque, ctx: *capy.DrawContext) !void { - const canvas = @as(*capy.Canvas_Impl, @ptrCast(@alignCast(cnv))); + const canvas = @as(*capy.Canvas, @ptrCast(@alignCast(cnv))); ctx.setColor(0.7, 0.9, 0.3); ctx.setLinearGradient(.{ .x0 = 80, .y0 = 0, .x1 = 100, .y1 = 100, .stops = &.{ @@ -86,27 +86,27 @@ fn drawRounded(cnv: *anyopaque, ctx: *capy.DrawContext) !void { ctx.fill(); } -pub const Drawer_Impl = struct { - pub usingnamespace capy.internal.All(Drawer_Impl); +pub const Drawer = struct { + pub usingnamespace capy.internal.All(Drawer); peer: ?capy.backend.Canvas = null, - handlers: Drawer_Impl.Handlers = undefined, - dataWrappers: Drawer_Impl.Atoms = .{}, + handlers: Drawer.Handlers = undefined, + dataWrappers: Drawer.Atoms = .{}, image: capy.ImageData, - pub fn init() !Drawer_Impl { - return Drawer_Impl.init_events(Drawer_Impl{ + pub fn init() !Drawer { + return Drawer.init_events(Drawer{ .image = try capy.ImageData.new(1, 1, .RGB), // start with a 1x1 image }); } - pub fn onDraw(self: *Drawer_Impl, ctx: *capy.DrawContext) !void { + pub fn onDraw(self: *Drawer, ctx: *capy.DrawContext) !void { const width = self.getWidth(); const height = self.getHeight(); ctx.image(0, 0, width, height, self.image); } - pub fn onResize(self: *Drawer_Impl, size: capy.Size) !void { + pub fn onResize(self: *Drawer, size: capy.Size) !void { if (size.width > self.image.width or size.height > self.image.height) { self.image.deinit(); // delete old image self.image = try capy.ImageData.new(size.width, size.height, .RGB); @@ -114,46 +114,46 @@ pub const Drawer_Impl = struct { } } - pub fn show(self: *Drawer_Impl) !void { + pub fn show(self: *Drawer) !void { if (self.peer == null) { - self.peer = try capy.backend.Canvas.create(); + self.peer = try capy.backend.canvas.create(); try self.show_events(); } } - pub fn getPreferredSize(self: *Drawer_Impl, _: capy.Size) capy.Size { + pub fn getPreferredSize(self: *Drawer, _: capy.Size) capy.Size { return .{ .width = self.image.width, .height = self.image.height }; } }; -pub fn Drawer(config: Drawer_Impl.Config) !Drawer_Impl { +pub fn drawer(config: Drawer.Config) !Drawer { _ = config; - var lineGraph = try Drawer_Impl.init(); - try lineGraph.addDrawHandler(&Drawer_Impl.onDraw); - try lineGraph.addResizeHandler(&Drawer_Impl.onResize); + var lineGraph = try Drawer.init(); + try lineGraph.addDrawHandler(&Drawer.onDraw); + try lineGraph.addResizeHandler(&Drawer.onResize); return lineGraph; } -// You can simulate a border layout using only Column, Row and Expanded -fn BorderLayoutExample() anyerror!capy.Container_Impl { - return capy.Column(.{}, .{ - capy.Label(.{ .text = "Top" }), - capy.Expanded( - capy.Row(.{}, .{ - capy.Label(.{ .text = "Left" }), - capy.Expanded( - capy.Label(.{ .text = "Center" }), +// You can simulate a border layout using only column, row and expanded +fn BorderLayoutExample() anyerror!capy.Container { + return capy.column(.{}, .{ + capy.label(.{ .text = "Top", .alignment = .Center }), + capy.expanded( + capy.row(.{}, .{ + capy.label(.{ .text = "Left", .alignment = .Center }), + capy.expanded( + capy.label(.{ .text = "Center", .alignment = .Center }), ), - capy.Label(.{ .text = "Right" }), + capy.label(.{ .text = "Right", .alignment = .Center }), }), ), - capy.Label(.{ .text = "Bottom " }), + capy.label(.{ .text = "Bottom", .alignment = .Center }), }); } fn moveButton(button_: *anyopaque) !void { - const button = @as(*capy.Button_Impl, @ptrCast(@alignCast(button_))); - const parent = button.getParent().?.as(capy.Align_Impl); + const button = @as(*capy.Button, @ptrCast(@alignCast(button_))); + const parent = button.getParent().?.as(capy.Alignment); const alignX = &parent.x; // Ensure the current animation is done before starting another diff --git a/examples/dev-tools.zig b/examples/dev-tools.zig index 88ff78a..b9716ac 100644 --- a/examples/dev-tools.zig +++ b/examples/dev-tools.zig @@ -14,37 +14,37 @@ pub fn main() !void { app_window = try capy.Window.init(); try app_window.set( - capy.Navigation(.{ .routeName = "Connect" }, .{ - .Connect = capy.Align(.{}, capy.Column(.{}, .{ - capy.Label(.{ .text = "Address" }), - capy.TextField(.{ .name = "server-address", .text = "localhost" }), - capy.Label(.{ .text = "Port" }), - capy.TextField(.{ .name = "server-port", .text = "42671" }), - capy.Align(.{ .x = 1 }, capy.Button(.{ .label = "Connect", .onclick = onConnect })), + capy.navigation(.{ .routeName = "Connect" }, .{ + .Connect = capy.alignment(.{}, capy.column(.{}, .{ + capy.label(.{ .text = "Address" }), + capy.textField(.{ .name = "server-address", .text = "localhost" }), + capy.label(.{ .text = "Port" }), + capy.textField(.{ .name = "server-port", .text = "42671" }), + capy.alignment(.{ .x = 1 }, capy.button(.{ .label = "Connect", .onclick = onConnect })), })), - .@"Dev Tools" = capy.Column(.{}, .{ - capy.Label(.{ .text = "Dev Tools", .alignment = .Center }), - capy.Expanded(capy.Tabs(.{ - capy.Tab( + .@"Dev Tools" = capy.column(.{}, .{ + capy.label(.{ .text = "Dev Tools", .alignment = .Center }), + capy.expanded(capy.tabs(.{ + capy.tab( .{ .label = "Inspector" }, - capy.Row(.{}, .{ - capy.Expanded( + capy.row(.{}, .{ + capy.expanded( // TODO: widget tree - capy.Label(.{ .text = "test" }), + capy.label(.{ .text = "test" }), ), - capy.Expanded(capy.Tabs(.{ - capy.Tab(.{ .label = "Properties" }, capy.Column(.{}, .{ - capy.Label(.{ .text = "Hello" }), + capy.expanded(capy.tabs(.{ + capy.tab(.{ .label = "Properties" }, capy.column(.{}, .{ + capy.label(.{ .text = "Hello" }), })), - capy.Tab(.{ .label = "Source Code" }, capy.Column(.{}, .{ - capy.TextArea(.{ .text = "capy.Row(.{}, .{})" }), + capy.tab(.{ .label = "Source Code" }, capy.column(.{}, .{ + capy.textArea(.{ .text = "capy.row(.{}, .{})" }), })), })), }), ), - capy.Tab( - .{ .label = "Tab 2" }, - capy.Button(.{ .label = "Test 2" }), + capy.tab( + .{ .label = "tab 2" }, + capy.button(.{ .label = "Test 2" }), ), })), }), @@ -59,12 +59,12 @@ pub fn main() !void { } fn onConnect(widget: *anyopaque) !void { - const button = @as(*capy.Button_Impl, @ptrCast(@alignCast(widget))); - const parent = button.getParent().?.getParent().?.as(capy.Container_Impl); - const root = button.getRoot().?.as(capy.Navigation_Impl); + const button = @as(*capy.Button, @ptrCast(@alignCast(widget))); + const parent = button.getParent().?.getParent().?.as(capy.Container); + const root = button.getRoot().?.as(capy.Navigation); - const serverAddress = parent.getChildAs(capy.TextField_Impl, "server-address").?; - const serverPort = parent.getChildAs(capy.TextField_Impl, "server-port").?; + const serverAddress = parent.getChildAs(capy.TextField, "server-address").?; + const serverPort = parent.getChildAs(capy.TextField, "server-port").?; const port = try std.fmt.parseUnsigned(u16, serverPort.get("text"), 10); const addressList = try std.net.getAddressList(app_allocator, serverAddress.get("text"), port); diff --git a/examples/dummy-installer.zig b/examples/dummy-installer.zig index f1391b0..c7896b9 100644 --- a/examples/dummy-installer.zig +++ b/examples/dummy-installer.zig @@ -7,15 +7,15 @@ pub fn main() !void { var window = try capy.Window.init(); try window.set( - capy.Margin(capy.Rectangle.init(10, 10, 10, 10), capy.Column(.{}, .{ - capy.Label(.{ .text = "Hello, World", .alignment = .Left }), // TODO: capy.Heading (= label with bold + big font) - capy.Label(.{ .text = + capy.margin(capy.Rectangle.init(10, 10, 10, 10), capy.column(.{}, .{ + capy.label(.{ .text = "Hello, World", .alignment = .Left }), // TODO: capy.Heading (= label with bold + big font) + capy.label(.{ .text = \\ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. }), - capy.Spacing(), - capy.Align(.{ .x = 1.0 }, capy.Row(.{}, .{ - capy.Button(.{ .label = "Previous", .enabled = false }), - capy.Button(.{ .label = "Next" }), + capy.spacing(), + capy.alignment(.{ .x = 1.0 }, capy.row(.{}, .{ + capy.button(.{ .label = "Previous", .enabled = false }), + capy.button(.{ .label = "Next" }), })), })), ); diff --git a/examples/entry.zig b/examples/entry.zig index 27d7702..ab0fd87 100644 --- a/examples/entry.zig +++ b/examples/entry.zig @@ -6,7 +6,7 @@ pub usingnamespace capy.cross_platform; var gpa = std.heap.GeneralPurposeAllocator(.{}){}; pub const capy_allocator = gpa.allocator(); -fn draw(widget: *capy.Canvas_Impl, ctx: *capy.DrawContext) !void { +fn draw(widget: *capy.Canvas, ctx: *capy.DrawContext) !void { _ = widget; std.log.info("drawing widget", .{}); ctx.setColor(0, 0, 0); @@ -22,7 +22,7 @@ fn draw(widget: *capy.Canvas_Impl, ctx: *capy.DrawContext) !void { ctx.fill(); } -fn scroll(widget: *capy.Canvas_Impl, dx: f32, dy: f32) !void { +fn scroll(widget: *capy.Canvas, dx: f32, dy: f32) !void { std.log.info("Scroll by {d}, {d}", .{ dx, dy }); try widget.requestDraw(); } @@ -34,17 +34,17 @@ pub fn main() !void { var window = try capy.Window.init(); defer window.deinit(); - var canvas = capy.Canvas(.{}); + var canvas = capy.canvas(.{}); try canvas.addDrawHandler(&draw); try canvas.addScrollHandler(&scroll); - try window.set(capy.Column(.{}, .{ - capy.Row(.{}, .{ - capy.Expanded(capy.TextField(.{ .text = "gemini://gemini.circumlunar.space/" })), - capy.Button(.{ .label = "Go!" }), + try window.set(capy.column(.{}, .{ + capy.row(.{}, .{ + capy.expanded(capy.textField(.{ .text = "gemini://gemini.circumlunar.space/" })), + capy.button(.{ .label = "Go!" }), }), - capy.TextField(.{ .text = "other text" }), - capy.Expanded(&canvas), + capy.textField(.{ .text = "other text" }), + capy.expanded(&canvas), })); window.setPreferredSize(800, 600); diff --git a/examples/fade.zig b/examples/fade.zig index 72d8b96..cc7295f 100644 --- a/examples/fade.zig +++ b/examples/fade.zig @@ -6,7 +6,7 @@ var opacity = capy.Atom(f32).of(1.0); // TODO: switch back to *capy.Button_Impl when ziglang/zig#12325 is fixed fn startAnimation(button_: *anyopaque) !void { - const button = @as(*capy.Button_Impl, @ptrCast(@alignCast(button_))); + const button = @as(*capy.Button, @ptrCast(@alignCast(button_))); // Ensure the current animation is done before starting another if (!opacity.hasAnimation()) { @@ -29,15 +29,15 @@ pub fn main() !void { // const imageData = try capy.ImageData.fromBuffer(capy.internal.lasting_allocator, @embedFile("ziglogo.png")); try window.set( - capy.Row(.{}, .{ - capy.Expanded((try capy.Row(.{}, .{ - capy.Label(.{ .text = "Hello Zig" }), - capy.Expanded( - capy.Image(.{ .url = "asset:///ziglogo.png", .scaling = .Fit }), + capy.row(.{}, .{ + capy.expanded((try capy.row(.{}, .{ + capy.label(.{ .text = "Hello Zig" }), + capy.expanded( + capy.image(.{ .url = "asset:///ziglogo.png", .scaling = .Fit }), ), })) .bind("opacity", &opacity)), - capy.Button(.{ .label = "Hide", .onclick = startAnimation }), + capy.button(.{ .label = "Hide", .onclick = startAnimation }), }), ); diff --git a/examples/foo_app.zig b/examples/foo_app.zig index 7f72754..de85d7b 100644 --- a/examples/foo_app.zig +++ b/examples/foo_app.zig @@ -7,20 +7,20 @@ pub fn main() !void { var window = try capy.Window.init(); - var column = try capy.Column(.{}, .{}); + var column = try capy.column(.{}, .{}); var i: usize = 0; while (i < 4) : (i += 1) { - var row = try capy.Row(.{}, .{}); + var row = try capy.row(.{}, .{}); var j: usize = 0; while (j < 20) : (j += 1) { - try row.add(try capy.Column(.{}, .{capy.Label(.{ .text = "Sample Item" })})); + try row.add(try capy.column(.{}, .{capy.label(.{ .text = "Sample Item" })})); } - try column.add(capy.Label(.{ .text = "Row" })); - try column.add(try capy.Scrollable(row)); + try column.add(capy.label(.{ .text = "Row" })); + try column.add(try capy.scrollable(row)); } - try window.set(capy.Scrollable(&column)); + try window.set(capy.scrollable(&column)); window.setPreferredSize(800, 600); window.show(); capy.runEventLoop(); diff --git a/examples/graph.zig b/examples/graph.zig index 0992c67..3d8ad27 100644 --- a/examples/graph.zig +++ b/examples/graph.zig @@ -4,20 +4,20 @@ const std = @import("std"); // Small block needed for correct WebAssembly support pub usingnamespace capy.cross_platform; -var graph: LineGraph_Impl = undefined; +var graph: LineGraph = undefined; -pub const LineGraph_Impl = struct { - pub usingnamespace capy.internal.All(LineGraph_Impl); +pub const LineGraph = struct { + pub usingnamespace capy.internal.All(LineGraph); peer: ?capy.backend.Canvas = null, - widget_data: LineGraph_Impl.WidgetData = .{}, + widget_data: LineGraph.WidgetData = .{}, dataFn: *const fn (x: f32) f32, - pub fn init(dataFn: *const fn (x: f32) f32) LineGraph_Impl { - return LineGraph_Impl.init_events(LineGraph_Impl{ .dataFn = dataFn }); + pub fn init(dataFn: *const fn (x: f32) f32) LineGraph { + return LineGraph.init_events(LineGraph{ .dataFn = dataFn }); } - pub fn draw(self: *LineGraph_Impl, ctx: *capy.DrawContext) !void { + pub fn draw(self: *LineGraph, ctx: *capy.DrawContext) !void { const width = self.getWidth(); const height = self.getHeight(); ctx.setColor(1, 1, 1); @@ -72,24 +72,24 @@ pub const LineGraph_Impl = struct { } } - pub fn show(self: *LineGraph_Impl) !void { + pub fn show(self: *LineGraph) !void { if (self.peer == null) { self.peer = try capy.backend.Canvas.create(); try self.show_events(); } } - pub fn getPreferredSize(self: *LineGraph_Impl, available: capy.Size) capy.Size { + pub fn getPreferredSize(self: *LineGraph, available: capy.Size) capy.Size { _ = self; _ = available; return capy.Size{ .width = 500.0, .height = 200.0 }; } }; -pub fn LineGraph(config: struct { dataFn: *const fn (x: f32) f32 }) !LineGraph_Impl { - var lineGraph = LineGraph_Impl.init(config.dataFn); - try lineGraph.addDrawHandler(&LineGraph_Impl.draw); - return lineGraph; +pub fn lineGraph(config: struct { dataFn: *const fn (x: f32) f32 }) !LineGraph { + var line_graph = LineGraph.init(config.dataFn); + try line_graph.addDrawHandler(&LineGraph.draw); + return line_graph; } const smoothData = true; @@ -154,7 +154,7 @@ fn SetEasing(comptime Easing: fn (x: f64) f64) fn (*anyopaque) anyerror!void { } // TODO: switch back to *capy.Canvas_Impl when ziglang/zig#12325 is fixed -fn drawRectangle(_: *anyopaque, ctx: *capy.Canvas_Impl.DrawContext) !void { +fn drawRectangle(_: *anyopaque, ctx: *capy.Canvas.DrawContext) !void { ctx.setColor(0, 0, 0); ctx.rectangle(0, 0, 100, 100); ctx.fill(); @@ -166,25 +166,25 @@ pub fn main() !void { try capy.backend.init(); var window = try capy.Window.init(); - graph = try LineGraph(.{ .dataFn = easing }); + graph = try lineGraph(.{ .dataFn = easing }); - var rectangle = (try capy.Align( + var rectangle = (try capy.alignment( .{}, - capy.Canvas(.{ + capy.canvas(.{ .preferredSize = capy.Size{ .width = 100, .height = 100 }, .ondraw = drawRectangle, }), )) .bind("x", &rectangleX); - try window.set(capy.Column(.{}, .{ - capy.Align(.{}, capy.Row(.{ .spacing = 10 }, .{ - capy.Button(.{ .label = "Linear", .onclick = SetEasing(capy.Easings.Linear) }), - capy.Button(.{ .label = "In", .onclick = SetEasing(capy.Easings.In) }), - capy.Button(.{ .label = "Out", .onclick = SetEasing(capy.Easings.Out) }), - capy.Button(.{ .label = "In Out", .onclick = SetEasing(capy.Easings.InOut) }), + try window.set(capy.column(.{}, .{ + capy.alignment(.{}, capy.row(.{ .spacing = 10 }, .{ + capy.button(.{ .label = "Linear", .onclick = SetEasing(capy.Easings.Linear) }), + capy.button(.{ .label = "In", .onclick = SetEasing(capy.Easings.In) }), + capy.button(.{ .label = "Out", .onclick = SetEasing(capy.Easings.Out) }), + capy.button(.{ .label = "In Out", .onclick = SetEasing(capy.Easings.InOut) }), })), - capy.Expanded(&graph), + capy.expanded(&graph), &rectangle, })); diff --git a/examples/hacker-news.zig b/examples/hacker-news.zig index 5f6b144..0f9822f 100644 --- a/examples/hacker-news.zig +++ b/examples/hacker-news.zig @@ -7,8 +7,8 @@ const ListModel = struct { size: capy.Atom(usize) = capy.Atom(usize).of(10), arena: std.heap.ArenaAllocator = std.heap.ArenaAllocator.init(capy.internal.lasting_allocator), - pub fn getComponent(self: *ListModel, index: usize) capy.Label_Impl { - return capy.Label(.{ + pub fn getComponent(self: *ListModel, index: usize) capy.Label { + return capy.label(.{ .text = std.fmt.allocPrintZ(self.arena.allocator(), "Label #{d}", .{index + 1}) catch unreachable, }); } @@ -21,17 +21,17 @@ pub fn main() !void { var window = try capy.Window.init(); try window.set( - capy.Stack(.{ - capy.Rect(.{ .color = capy.Color.comptimeFromString("#f6f6ef") }), - capy.Column(.{}, .{ - capy.Stack(.{ - capy.Rect(.{ + capy.stack(.{ + capy.rect(.{ .color = capy.Color.comptimeFromString("#f6f6ef") }), + capy.column(.{}, .{ + capy.stack(.{ + capy.rect(.{ .color = capy.Color.comptimeFromString("#ff6600"), .cornerRadius = .{ 0.0, 0.0, 5.0, 5.0 }, }), - capy.Label(.{ .text = "Hacker News", .alignment = .Center }), + capy.label(.{ .text = "Hacker News", .alignment = .Center }), }), - capy.ColumnList(.{}, &hn_list_model), + capy.columnList(.{}, &hn_list_model), }), }), ); diff --git a/examples/media-player.zig b/examples/media-player.zig index 22b7a53..6250988 100644 --- a/examples/media-player.zig +++ b/examples/media-player.zig @@ -16,9 +16,9 @@ pub fn main() !void { defer window.deinit(); try window.set( - capy.Align(.{}, capy.Column(.{}, .{ - RotatingDisc(), // TODO - capy.Label(.{ .text = "Audio Name", .alignment = .Center }), + capy.alignment(.{}, capy.column(.{}, .{ + rotatingDisc(), // TODO + capy.label(.{ .text = "Audio Name", .alignment = .Center }), })), ); @@ -27,15 +27,15 @@ pub fn main() !void { } /// A spinning CD disc with the thumbnail of the audio or none if there isn't any -fn RotatingDisc() !capy.Canvas_Impl { - var canvas = capy.Canvas(.{ +fn rotatingDisc() !capy.Canvas { + var canvas = capy.canvas(.{ .preferredSize = capy.Size.init(256, 256), }); - try canvas.addDrawHandler(&drawRotatingDisk); + try canvas.addDrawHandler(&drawRotatingDisc); return canvas; } -fn drawRotatingDisk(self: *capy.Canvas_Impl, ctx: *capy.DrawContext) anyerror!void { +fn drawRotatingDisc(self: *capy.Canvas, ctx: *capy.DrawContext) anyerror!void { const width = self.getWidth(); const height = self.getHeight(); diff --git a/examples/notepad.zig b/examples/notepad.zig index 60a18ee..172dda7 100644 --- a/examples/notepad.zig +++ b/examples/notepad.zig @@ -20,34 +20,34 @@ pub fn main() !void { var label_text = try capy.FormattedAtom(capy.internal.lasting_allocator, "Text length: {d}", .{text_length}); defer label_text.deinit(); - try window.set(capy.Column(.{ .spacing = 0 }, .{ - capy.Expanded(capy.TextArea(.{}) + try window.set(capy.column(.{ .spacing = 0 }, .{ + capy.expanded(capy.textArea(.{}) .bind("monospace", &monospace) .bind("text", &text)), - capy.Label(.{ .text = "TODO: cursor info" }) + capy.label(.{ .text = "TODO: cursor info" }) .bind("text", label_text), // TODO: move into menu - capy.CheckBox(.{ .label = "Monospaced" }) + capy.checkBox(.{ .label = "Monospaced" }) .bind("checked", &monospace), })); // TODO: hotkeys for actions (Ctrl+S, Ctrl+C) plus corresponding Cmd+C on macOS - window.setMenuBar(capy.MenuBar(.{ - capy.Menu(.{ .label = "File" }, .{ - capy.MenuItem(.{ .label = "New File" }), - capy.MenuItem(.{ .label = "Open File.." }), - capy.MenuItem(.{ .label = "Save" }), - // TODO: capy.MenuSeperator ? - capy.MenuItem(.{ .label = "Quit" }), + window.setMenuBar(capy.menuBar(.{ + capy.menu(.{ .label = "File" }, .{ + capy.menuItem(.{ .label = "New File" }), + capy.menuItem(.{ .label = "Open File.." }), + capy.menuItem(.{ .label = "Save" }), + // TODO: capy.menuSeperator ? + capy.menuItem(.{ .label = "Quit" }), }), - capy.Menu(.{ .label = "Edit" }, .{ - capy.MenuItem(.{ .label = "Find" }), - capy.MenuItem(.{ .label = "Copy" }), - capy.MenuItem(.{ .label = "Paste" }), + capy.menu(.{ .label = "Edit" }, .{ + capy.menuItem(.{ .label = "Find" }), + capy.menuItem(.{ .label = "Copy" }), + capy.menuItem(.{ .label = "Paste" }), }), - capy.Menu(.{ .label = "View" }, .{ + capy.menu(.{ .label = "View" }, .{ // TODO: togglemenuitem ? - capy.MenuItem(.{ .label = "Monospace" }), + capy.menuItem(.{ .label = "Monospace" }), }), })); diff --git a/examples/osm-viewer.zig b/examples/osm-viewer.zig index b24477d..a454797 100644 --- a/examples/osm-viewer.zig +++ b/examples/osm-viewer.zig @@ -9,8 +9,8 @@ fn deg2rad(theta: f32) f32 { return theta / 180.0 * std.math.pi; } -pub const MapViewer_Impl = struct { - pub usingnamespace capy.internal.All(MapViewer_Impl); +pub const MapViewer = struct { + pub usingnamespace capy.internal.All(MapViewer); // Required fields for all components. @@ -19,8 +19,8 @@ pub const MapViewer_Impl = struct { // a GtkDrawingBox on GTK+, a custom canvas on win32, a element on // the web, etc. peer: ?capy.backend.Canvas = null, - // .Handlers and .Atoms are implemented by `capy.internal.All(MapViewer_Impl)` - widget_data: MapViewer_Impl.WidgetData = .{}, + // .Handlers and .Atoms are implemented by `capy.internal.All(MapViewer)` + widget_data: MapViewer.WidgetData = .{}, // Our own component state. tileCache: std.AutoHashMap(TilePosition, Tile), @@ -51,8 +51,8 @@ pub const MapViewer_Impl = struct { const Tile = struct { data: capy.ImageData }; - pub fn init(config: MapViewer_Impl.Config) MapViewer_Impl { - var viewer = MapViewer_Impl.init_events(MapViewer_Impl{ + pub fn init(config: MapViewer.Config) MapViewer { + var viewer = MapViewer.init_events(MapViewer{ .tileCache = std.AutoHashMap(TilePosition, Tile).init(config.allocator), .pendingRequests = std.AutoHashMap(TilePosition, capy.http.HttpResponse).init(config.allocator), .allocator = Atom(std.mem.Allocator).of(config.allocator), @@ -63,7 +63,7 @@ pub const MapViewer_Impl = struct { } // Implementation Methods - pub fn getTile(self: *MapViewer_Impl, pos: TilePosition) ?Tile { + pub fn getTile(self: *MapViewer, pos: TilePosition) ?Tile { const modTileXY = std.math.powi(i32, 2, pos.zoom) catch unreachable; const actual_pos = TilePosition{ .zoom = pos.zoom, @@ -84,7 +84,7 @@ pub const MapViewer_Impl = struct { } } - pub fn centerTo(self: *MapViewer_Impl, lon: f32, lat: f32) void { + pub fn centerTo(self: *MapViewer, lon: f32, lat: f32) void { const n = std.math.pow(f32, 2, @as(f32, @floatFromInt(self.camZoom))); const x = n * ((lon + 180) / 360); const lat_rad = deg2rad(lat); @@ -93,7 +93,7 @@ pub const MapViewer_Impl = struct { self.centerY = y * 256; } - pub fn search(self: *MapViewer_Impl, query: []const u8) !void { + pub fn search(self: *MapViewer, query: []const u8) !void { var buf: [2048]u8 = undefined; const encoded_query = try std.Uri.escapeQuery(capy.internal.scratch_allocator, query); defer capy.internal.scratch_allocator.free(encoded_query); @@ -104,7 +104,7 @@ pub const MapViewer_Impl = struct { self.pendingSearchRequest = response; } - pub fn checkRequests(self: *MapViewer_Impl) !void { + pub fn checkRequests(self: *MapViewer) !void { if (self.pendingSearchRequest) |*response| { if (response.isReady()) { try response.checkError(); @@ -155,8 +155,8 @@ pub const MapViewer_Impl = struct { // Component Methods (drawing, showing, ...) // Here we'll draw ourselves the content of the map - // It works because in MapViewer() function, we do addDrawHandler(MapViewer.draw) - pub fn draw(self: *MapViewer_Impl, ctx: *capy.DrawContext) !void { + // It works because in mapViewer() function, we do addDrawHandler(mapViewer.draw) + pub fn draw(self: *MapViewer, ctx: *capy.DrawContext) !void { const width = self.getWidth(); const height = self.getHeight(); ctx.clear(0, 0, width, height); @@ -172,7 +172,7 @@ pub const MapViewer_Impl = struct { } } - fn drawTile(self: *MapViewer_Impl, ctx: *capy.DrawContext, pos: TilePosition, camX: i32, camY: i32) void { + fn drawTile(self: *MapViewer, ctx: *capy.DrawContext, pos: TilePosition, camX: i32, camY: i32) void { const x = -camX + pos.x * 256; const y = -camY + pos.y * 256; if (self.getTile(pos)) |tile| { @@ -185,7 +185,7 @@ pub const MapViewer_Impl = struct { } } - fn mouseButton(self: *MapViewer_Impl, button: capy.MouseButton, pressed: bool, x: i32, y: i32) !void { + fn mouseButton(self: *MapViewer, button: capy.MouseButton, pressed: bool, x: i32, y: i32) !void { if (button == .Left) { self.isDragging = pressed; self.lastMouseX = x; @@ -193,7 +193,7 @@ pub const MapViewer_Impl = struct { } } - fn mouseMoved(self: *MapViewer_Impl, x: i32, y: i32) !void { + fn mouseMoved(self: *MapViewer, x: i32, y: i32) !void { if (self.isDragging) { // TODO: smooth move self.centerX -= @as(f32, @floatFromInt(x - self.lastMouseX)); @@ -205,7 +205,7 @@ pub const MapViewer_Impl = struct { } } - fn mouseScroll(self: *MapViewer_Impl, dx: f32, dy: f32) !void { + fn mouseScroll(self: *MapViewer, dx: f32, dy: f32) !void { _ = dx; if (dy > 0 and self.camZoom > 0) { self.camZoom -|= 2 * @as(u5, @intFromFloat(dy)); @@ -225,26 +225,26 @@ pub const MapViewer_Impl = struct { // All components have this method, which is automatically called // when Capy needs to create the native peers of your widget. - pub fn show(self: *MapViewer_Impl) !void { + pub fn show(self: *MapViewer) !void { if (self.peer == null) { self.peer = try capy.backend.Canvas.create(); try self.show_events(); } } - pub fn getPreferredSize(self: *MapViewer_Impl, available: capy.Size) capy.Size { + pub fn getPreferredSize(self: *MapViewer, available: capy.Size) capy.Size { _ = self; _ = available; return capy.Size{ .width = 500.0, .height = 200.0 }; } }; -pub fn MapViewer(config: MapViewer_Impl.Config) !MapViewer_Impl { - var map_viewer = MapViewer_Impl.init(config); - _ = try map_viewer.addDrawHandler(&MapViewer_Impl.draw); - _ = try map_viewer.addMouseButtonHandler(&MapViewer_Impl.mouseButton); - _ = try map_viewer.addMouseMotionHandler(&MapViewer_Impl.mouseMoved); - _ = try map_viewer.addScrollHandler(&MapViewer_Impl.mouseScroll); +pub fn mapViewer(config: MapViewer.Config) !MapViewer { + var map_viewer = MapViewer.init(config); + _ = try map_viewer.addDrawHandler(&MapViewer.draw); + _ = try map_viewer.addMouseButtonHandler(&MapViewer.mouseButton); + _ = try map_viewer.addMouseMotionHandler(&MapViewer.mouseMoved); + _ = try map_viewer.addScrollHandler(&MapViewer.mouseScroll); return map_viewer; } @@ -253,28 +253,28 @@ pub fn main() !void { var window = try capy.Window.init(); try window.set( - capy.Column(.{}, .{ - capy.Row(.{}, .{ - capy.Expanded(capy.TextField(.{ .name = "location-input" })), - capy.Button(.{ .label = "Go!", .onclick = onGo }), + capy.column(.{}, .{ + capy.row(.{}, .{ + capy.expanded(capy.textField(.{ .name = "location-input" })), + capy.button(.{ .label = "Go!", .onclick = onGo }), }), - capy.Expanded(MapViewer(.{ .name = "map-viewer" })), + capy.expanded(mapViewer(.{ .name = "map-viewer" })), }), ); window.setTitle("OpenStreetMap Viewer"); window.show(); while (capy.stepEventLoop(.Asynchronous)) { - const root = window.getChild().?.as(capy.Container_Impl); - const viewer = root.getChildAs(MapViewer_Impl, "map-viewer").?; + const root = window.getChild().?.as(capy.Container); + const viewer = root.getChildAs(MapViewer, "map-viewer").?; try viewer.checkRequests(); } } fn onGo(self_ptr: *anyopaque) !void { - const self = @as(*capy.Button_Impl, @ptrCast(@alignCast(self_ptr))); // due to ZIG BUG - const root = self.getRoot().?.as(capy.Container_Impl); - const viewer = root.getChildAs(MapViewer_Impl, "map-viewer").?; - const input = root.getChildAs(capy.TextField_Impl, "location-input").?; + const self = @as(*capy.Button, @ptrCast(@alignCast(self_ptr))); // due to ZIG BUG + const root = self.getRoot().?.as(capy.Container); + const viewer = root.getChildAs(MapViewer, "map-viewer").?; + const input = root.getChildAs(capy.TextField, "location-input").?; try viewer.search(input.get("text")); } diff --git a/examples/slide-viewer.zig b/examples/slide-viewer.zig index 0110493..e3feb8c 100644 --- a/examples/slide-viewer.zig +++ b/examples/slide-viewer.zig @@ -6,16 +6,16 @@ pub fn main() !void { try capy.backend.init(); var window = try capy.Window.init(); - try window.set(capy.Stack(.{ - capy.Rect(.{ .color = capy.Color.comptimeFromString("#2D2D2D") }), - capy.Image(.{ .url = "asset:///ziglogo.png" }), - capy.Column(.{}, .{ - capy.Spacing(), - capy.Row(.{}, .{ - capy.Button(.{ .label = "Previous", .enabled = false }), // TODO: capy Icon left arrow / previous + tooltip - capy.Button(.{ .label = "Next", .enabled = false }), // TODO: capy Icon right arrow / next + tooltip - capy.Expanded(capy.Label(.{ .text = "TODO: slider" })), - capy.Button(.{ .label = "Fullscreen" }), // TODO: capy Icon fullscreen + tooltip + try window.set(capy.stack(.{ + capy.rect(.{ .color = capy.Color.comptimeFromString("#2D2D2D") }), + capy.image(.{ .url = "asset:///ziglogo.png" }), + capy.column(.{}, .{ + capy.spacing(), + capy.row(.{}, .{ + capy.button(.{ .label = "Previous", .enabled = false }), // TODO: capy Icon left arrow / previous + tooltip + capy.button(.{ .label = "Next", .enabled = false }), // TODO: capy Icon right arrow / next + tooltip + capy.expanded(capy.label(.{ .text = "TODO: slider" })), + capy.button(.{ .label = "Fullscreen" }), // TODO: capy Icon fullscreen + tooltip }), }), })); diff --git a/examples/tabs.zig b/examples/tabs.zig index 31eb227..874e276 100644 --- a/examples/tabs.zig +++ b/examples/tabs.zig @@ -5,11 +5,11 @@ pub fn main() !void { try capy.backend.init(); var window = try capy.Window.init(); - try window.set(capy.Tabs(.{ - capy.Tab(.{ .label = "Tab 1" }, capy.Column(.{}, .{ - capy.Button(.{ .label = "Test" }), + try window.set(capy.tabs(.{ + capy.tab(.{ .label = "Tab 1" }, capy.column(.{}, .{ + capy.button(.{ .label = "Test" }), })), - capy.Tab(.{ .label = "Tab 2" }, capy.Button(.{ .label = "Test 2" })), + capy.tab(.{ .label = "Tab 2" }, capy.button(.{ .label = "Test 2" })), })); window.show(); diff --git a/examples/test-backend.zig b/examples/test-backend.zig index 12cd6c2..46d7240 100644 --- a/examples/test-backend.zig +++ b/examples/test-backend.zig @@ -7,12 +7,12 @@ pub fn main() !void { var window = try capy.Window.init(); try window.set( - capy.Row(.{}, .{}), + capy.row(.{}, .{}), ); - var row = capy.Label(.{ .text = "test" }); + var row = capy.label(.{ .text = "test" }); _ = row; - //window.resize(800, 450); + // window.resize(800, 450); window.show(); capy.runEventLoop(); } diff --git a/examples/time-feed.zig b/examples/time-feed.zig index 4e851a6..14d3bde 100644 --- a/examples/time-feed.zig +++ b/examples/time-feed.zig @@ -19,15 +19,15 @@ const ListModel = struct { self.size.set(self.size.get() + 1); } - pub fn getComponent(self: *ListModel, index: usize) capy.Container_Impl { + pub fn getComponent(self: *ListModel, index: usize) capy.Container { const activity = self.data.items[index]; const start_epoch = std.time.epoch.EpochSeconds{ .secs = activity.start }; const start_day = start_epoch.getDaySeconds(); const end_epoch = std.time.epoch.EpochSeconds{ .secs = activity.end }; const end_day = end_epoch.getDaySeconds(); - return Card(capy.Column(.{}, .{ - capy.Label(.{ + return Card(capy.column(.{}, .{ + capy.label(.{ .text = std.fmt.allocPrintZ(self.arena.allocator(), "{d:0>2}:{d:0>2} - {d:0>2}:{d:0>2}", .{ start_day.getHoursIntoDay(), start_day.getMinutesIntoHour(), @@ -35,16 +35,16 @@ const ListModel = struct { end_day.getMinutesIntoHour(), }) catch unreachable, }), - capy.Label(.{ .text = activity.description }), - capy.Align(.{ .x = 1 }, capy.Button(.{ .label = "Edit" })), + capy.label(.{ .text = activity.description }), + capy.alignment(.{ .x = 1 }, capy.button(.{ .label = "Edit" })), })) catch unreachable; } }; -pub fn Card(child: anytype) anyerror!capy.Container_Impl { - return try capy.Stack(.{ - capy.Rect(.{ .color = capy.Color.comptimeFromString("#ffffff") }), - capy.Margin(capy.Rectangle.init(10, 10, 10, 10), try child), +pub fn Card(child: anytype) anyerror!capy.Container { + return try capy.stack(.{ + capy.rect(.{ .color = capy.Color.comptimeFromString("#ffffff") }), + capy.margin(capy.Rectangle.init(10, 10, 10, 10), try child), }); } @@ -63,22 +63,22 @@ fn onSubmit(_: *anyopaque) !void { submitDesc.set(""); } -pub fn InsertCard() anyerror!capy.Container_Impl { +pub fn InsertCard() anyerror!capy.Container { submitEnabled.dependOn(.{&submitDesc}, &(struct { fn callback(description: []const u8) bool { return description.len > 0; } }.callback)) catch unreachable; - return try capy.Column(.{}, .{ + return try capy.column(.{}, .{ // TODO: TextArea when it supports data wrappers - capy.TextField(.{ .name = "description" }) + capy.textField(.{ .name = "description" }) .bind("text", &submitDesc), // placeholder = "Task description..." - capy.Label(.{ .text = "Going on since.. 00:00:20" }), - capy.Align(.{ .x = 1 }, capy.Row(.{}, .{ - capy.Button(.{ .label = "Submit", .onclick = onSubmit }) + capy.label(.{ .text = "Going on since.. 00:00:20" }), + capy.alignment(.{ .x = 1 }, capy.row(.{}, .{ + capy.button(.{ .label = "Submit", .onclick = onSubmit }) .bind("enabled", &submitEnabled), - capy.Button(.{ .label = "Delete" }), // TODO: icon + capy.button(.{ .label = "Delete" }), // TODO: icon })), }); } @@ -90,11 +90,11 @@ pub fn main() !void { .data = std.ArrayList(TimeActivity).init(capy.internal.lasting_allocator), }; var window = try capy.Window.init(); - try window.set(capy.Column(.{}, .{ - capy.Label(.{ .text = "Feed" }), // TODO: capy.Heading ? + try window.set(capy.column(.{}, .{ + capy.label(.{ .text = "Feed" }), // TODO: capy.Heading ? InsertCard(), // TODO: days labels / list categories - capy.ColumnList(.{}, &list_model), + capy.columnList(.{}, &list_model), })); window.setTitle("Time Feed"); diff --git a/src/backends/gtk/backend.zig b/src/backends/gtk/backend.zig index 5b60fd2..1c7ab33 100644 --- a/src/backends/gtk/backend.zig +++ b/src/backends/gtk/backend.zig @@ -154,7 +154,7 @@ pub const Window = struct { wbin_set_child(@ptrCast(self.wbin), peer); } - pub fn setMenuBar(self: *Window, bar: lib.MenuBar_Impl) void { + pub fn setMenuBar(self: *Window, bar: lib.MenuBar) void { const menuBar = c.gtk_popover_menu_bar_new_from_model(null).?; const menuModel = c.g_menu_new().?; initMenu(menuModel, bar.menus); @@ -172,7 +172,7 @@ pub const Window = struct { self.scale = resolution / @as(f32, @floatFromInt(dpi)); } - fn initMenu(menu: *c.GMenu, items: []const lib.MenuItem_Impl) void { + fn initMenu(menu: *c.GMenu, items: []const lib.MenuItem) void { for (items) |item| { if (item.items.len > 0) { // The menu associated to the menu item @@ -269,6 +269,18 @@ pub fn Events(comptime T: type) type { _ = c.g_signal_connect_data(event_controller_key, "key-pressed", @as(c.GCallback, @ptrCast(>kKeyPress)), null, null, c.G_CONNECT_AFTER); c.gtk_widget_add_controller(widget, event_controller_key); + const event_controller_motion = c.gtk_event_controller_motion_new(); + _ = c.g_signal_connect_data(event_controller_motion, "motion", @as(c.GCallback, @ptrCast(>kMouseMotion)), null, null, c.G_CONNECT_AFTER); + c.gtk_widget_add_controller(widget, event_controller_motion); + + const event_controller_scroll = c.gtk_event_controller_scroll_new(c.GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES | c.GTK_EVENT_CONTROLLER_SCROLL_DISCRETE); + _ = c.g_signal_connect_data(event_controller_scroll, "scroll", @as(c.GCallback, @ptrCast(>kMouseScroll)), null, null, c.G_CONNECT_AFTER); + c.gtk_widget_add_controller(widget, event_controller_scroll); + + const event_controller_legacy = c.gtk_event_controller_legacy_new(); + _ = c.g_signal_connect_data(event_controller_legacy, "event", @as(c.GCallback, @ptrCast(>kButtonPress)), null, null, c.G_CONNECT_AFTER); + c.gtk_widget_add_controller(widget, event_controller_legacy); + var data = try lib.internal.lasting_allocator.create(EventUserData); data.* = EventUserData{ .peer = widget }; // ensure that it uses default values c.g_object_set_data(@as(*c.GObject, @ptrCast(widget)), "eventUserData", data); @@ -333,9 +345,23 @@ pub fn Events(comptime T: type) type { return 0; } - fn gtkButtonPress(peer: *c.GtkWidget, event: *c.GdkEvent, _: usize) callconv(.C) c.gboolean { + fn getWindow(peer: *c.GtkWidget) *c.GtkWidget { + var window = peer; + while (c.gtk_widget_get_parent(window)) |parent| { + window = parent; + } + return window; + } + + fn gtkButtonPress(controller: *c.GtkEventControllerLegacy, event: *c.GdkEvent, _: usize) callconv(.C) c.gboolean { + const event_type = c.gdk_event_get_event_type(event); + if (event_type != c.GDK_BUTTON_PRESS and event_type != c.GDK_BUTTON_RELEASE) + return 0; + + const peer = c.gtk_event_controller_get_widget(@ptrCast(controller)); + const window = getWindow(peer); const data = getEventUserData(peer); - const pressed = switch (c.gdk_event_get_event_type(event)) { + const pressed = switch (event_type) { c.GDK_BUTTON_PRESS => true, c.GDK_BUTTON_RELEASE => false, // don't send released button in case of GDK_2BUTTON_PRESS, GDK_3BUTTON_PRESS, ... @@ -343,9 +369,13 @@ pub fn Events(comptime T: type) type { }; var x: f64 = undefined; - std.debug.assert(c.gdk_event_get_axis(event, c.GDK_AXIS_X, &x)); + std.debug.assert(c.gdk_event_get_axis(event, c.GDK_AXIS_X, &x) != 0); var y: f64 = undefined; - std.debug.assert(c.gdk_event_get_axis(event, c.GDK_AXIS_Y, &y)); + std.debug.assert(c.gdk_event_get_axis(event, c.GDK_AXIS_Y, &y) != 0); + + const point: c.graphene_point_t = .{ .x = @floatCast(x), .y = @floatCast(y) }; + var out_point: c.graphene_point_t = undefined; + _ = c.gtk_widget_compute_point(window, peer, &point, &out_point); if (x < 0 or y < 0) return 0; @@ -353,28 +383,29 @@ pub fn Events(comptime T: type) type { 1 => MouseButton.Left, 2 => MouseButton.Middle, 3 => MouseButton.Right, - else => @as(MouseButton, @enumFromInt(event.button)), + else => @as(MouseButton, @enumFromInt(c.gdk_button_event_get_button(event))), }; - const mx = @as(i32, @intFromFloat(@floor(x))); - const my = @as(i32, @intFromFloat(@floor(y))); + const mx = @as(i32, @intFromFloat(@floor(out_point.x))); + const my = @as(i32, @intFromFloat(@floor(out_point.y))); if (data.class.mouseButtonHandler) |handler| { handler(button, pressed, mx, my, @intFromPtr(data)); } if (data.user.mouseButtonHandler) |handler| { if (data.focusOnClick) { - c.gtk_widget_grab_focus(peer); + _ = c.gtk_widget_grab_focus(peer); } handler(button, pressed, mx, my, data.userdata); } return 0; } - fn gtkMouseMotion(peer: *c.GtkWidget, event: *c.GdkEvent, _: usize) callconv(.C) c.gboolean { + fn gtkMouseMotion(controller: *c.GtkEventControllerMotion, x: f64, y: f64, _: usize) callconv(.C) c.gboolean { + const peer = c.gtk_event_controller_get_widget(@ptrCast(controller)); const data = getEventUserData(peer); - const mx = @as(i32, @intFromFloat(@floor(event.x))); - const my = @as(i32, @intFromFloat(@floor(event.y))); + const mx = @as(i32, @intFromFloat(@floor(x))); + const my = @as(i32, @intFromFloat(@floor(y))); if (data.class.mouseMotionHandler) |handler| { handler(mx, my, @intFromPtr(data)); if (data.user.mouseMotionHandler == null) return 1; @@ -386,21 +417,11 @@ pub fn Events(comptime T: type) type { return 0; } - /// Temporary hack until translate-c can translate this struct - const GdkEventScroll = extern struct { type: c.GdkEventType, window: *c.GdkWindow, send_event: c.gint8, time: c.guint32, x: c.gdouble, y: c.gdouble, state: c.guint, direction: c.GdkScrollDirection, device: *c.GdkDevice, x_root: c.gdouble, y_root: c.gdouble, delta_x: c.gdouble, delta_y: c.gdouble, is_stop: c.guint }; - - fn gtkMouseScroll(peer: *c.GtkWidget, event: *c.GdkEvent, _: usize) callconv(.C) void { + fn gtkMouseScroll(controller: *c.GtkEventControllerScroll, delta_x: f64, delta_y: f64, _: usize) callconv(.C) void { + const peer = c.gtk_event_controller_get_widget(@ptrCast(controller)); const data = getEventUserData(peer); - const dx: f32 = switch (event.direction) { - c.GDK_SCROLL_LEFT => -1, - c.GDK_SCROLL_RIGHT => 1, - else => @as(f32, @floatCast(event.delta_x)), - }; - const dy: f32 = switch (event.direction) { - c.GDK_SCROLL_UP => -1, - c.GDK_SCROLL_DOWN => 1, - else => @as(f32, @floatCast(event.delta_y)), - }; + const dx: f32 = @floatCast(delta_x); + const dy: f32 = @floatCast(delta_y); if (data.class.scrollHandler) |handler| handler(dx, dy, @intFromPtr(data)); diff --git a/src/c_api.zig b/src/c_api.zig index dc7677c..0def082 100644 --- a/src/c_api.zig +++ b/src/c_api.zig @@ -68,8 +68,8 @@ export fn capy_window_get_child(window: CapyWindow) ?CapyWidget { // Button // /// Returns null on error export fn capy_button_new() ?CapyWidget { - const button = allocator.create(capy.Button_Impl) catch return null; - button.* = capy.Button(.{}); + const button = allocator.create(capy.Button) catch return null; + button.* = capy.button(.{}); const widget = allocator.create(capy.Widget) catch return null; widget.* = capy.internal.genericWidgetFrom(button) catch unreachable; // it can't error as the component doesn't have a widget and no allocation is necessary @@ -78,7 +78,7 @@ export fn capy_button_new() ?CapyWidget { } export fn capy_button_set_label(widget: CapyWidget, label: [*:0]const u8) void { - const button = widget.as(capy.Button_Impl); + const button = widget.as(capy.Button); button.label.set(std.mem.span(label)); } diff --git a/src/components/Align.zig b/src/components/Alignment.zig similarity index 76% rename from src/components/Align.zig rename to src/components/Alignment.zig index 26c0f80..ee6dfa6 100644 --- a/src/components/Align.zig +++ b/src/components/Alignment.zig @@ -5,19 +5,19 @@ const Size = @import("../data.zig").Size; const Atom = @import("../data.zig").Atom; const Widget = @import("../widget.zig").Widget; -pub const Align_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Align_Impl); +pub const Alignment = struct { + pub usingnamespace @import("../internal.zig").All(Alignment); peer: ?backend.Container = null, - widget_data: Align_Impl.WidgetData = .{}, + widget_data: Alignment.WidgetData = .{}, child: Widget, relayouting: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false), x: Atom(f32) = Atom(f32).of(0.5), y: Atom(f32) = Atom(f32).of(0.5), - pub fn init(config: Align_Impl.Config, widget: Widget) !Align_Impl { - var component = Align_Impl.init_events(Align_Impl{ .child = widget }); + pub fn init(config: Alignment.Config, widget: Widget) !Alignment { + var component = Alignment.init_events(Alignment{ .child = widget }); component.x.set(config.x); component.y.set(config.y); try component.addResizeHandler(&onResize); @@ -25,16 +25,16 @@ pub const Align_Impl = struct { return component; } - pub fn _pointerMoved(self: *Align_Impl) void { + pub fn _pointerMoved(self: *Alignment) void { self.x.updateBinders(); self.y.updateBinders(); } - pub fn onResize(self: *Align_Impl, _: Size) !void { + pub fn onResize(self: *Alignment, _: Size) !void { self.relayout(); } - pub fn getChild(self: *Align_Impl, name: []const u8) ?*Widget { + pub fn getChild(self: *Alignment, name: []const u8) ?*Widget { if (self.child.name.*.get()) |child_name| { if (std.mem.eql(u8, child_name, name)) { return &self.child; @@ -45,16 +45,16 @@ pub const Align_Impl = struct { /// When alignX or alignY is changed, this will trigger a parent relayout fn alignChanged(_: f32, userdata: usize) void { - const self = @as(*Align_Impl, @ptrFromInt(userdata)); + const self = @as(*Alignment, @ptrFromInt(userdata)); self.relayout(); } - pub fn _showWidget(widget: *Widget, self: *Align_Impl) !void { + pub fn _showWidget(widget: *Widget, self: *Alignment) !void { self.child.parent = widget; self.child.class.setWidgetFn(&self.child); } - pub fn show(self: *Align_Impl) !void { + pub fn show(self: *Alignment) !void { if (self.peer == null) { var peer = try backend.Container.create(); self.peer = peer; @@ -70,7 +70,7 @@ pub const Align_Impl = struct { } } - pub fn relayout(self: *Align_Impl) void { + pub fn relayout(self: *Alignment) void { if (self.relayouting.load(.SeqCst) == true) return; if (self.peer) |peer| { self.relayouting.store(true, .SeqCst); @@ -94,16 +94,16 @@ pub const Align_Impl = struct { } } - pub fn getPreferredSize(self: *Align_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Alignment, available: Size) Size { return self.child.getPreferredSize(available); } - pub fn _deinit(self: *Align_Impl) void { + pub fn _deinit(self: *Alignment) void { self.child.deinit(); } }; -pub fn Align(opts: Align_Impl.Config, child: anytype) anyerror!Align_Impl { +pub fn alignment(opts: Alignment.Config, child: anytype) anyerror!Alignment { const element = if (comptime internal.isErrorUnion(@TypeOf(child))) try child @@ -111,5 +111,5 @@ pub fn Align(opts: Align_Impl.Config, child: anytype) anyerror!Align_Impl { child; const widget = try internal.genericWidgetFrom(element); - return try Align_Impl.init(opts, widget); + return try Alignment.init(opts, widget); } diff --git a/src/components/Button.zig b/src/components/Button.zig index 06e4c18..bdce4a7 100644 --- a/src/components/Button.zig +++ b/src/components/Button.zig @@ -5,19 +5,19 @@ const Atom = @import("../data.zig").Atom; const Container_Impl = @import("../containers.zig").Container_Impl; /// A button component. Instantiated using `Button(.{ })` -pub const Button_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Button_Impl); +pub const Button = struct { + pub usingnamespace @import("../internal.zig").All(Button); peer: ?backend.Button = null, - widget_data: Button_Impl.WidgetData = .{}, + widget_data: Button.WidgetData = .{}, label: Atom([:0]const u8) = Atom([:0]const u8).of(""), enabled: Atom(bool) = Atom(bool).of(true), - pub fn init() Button_Impl { - return Button_Impl.init_events(Button_Impl{}); + pub fn init() Button { + return Button.init_events(Button{}); } - pub fn _pointerMoved(self: *Button_Impl) void { + pub fn _pointerMoved(self: *Button) void { self.enabled.updateBinders(); self.label.updateBinders(); } @@ -32,7 +32,7 @@ pub const Button_Impl = struct { peer.*.?.setLabel(newValue); } - pub fn show(self: *Button_Impl) !void { + pub fn show(self: *Button) !void { if (self.peer == null) { self.peer = try backend.Button.create(); self.peer.?.setEnabled(self.enabled.get()); @@ -44,7 +44,7 @@ pub const Button_Impl = struct { } } - pub fn getPreferredSize(self: *Button_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Button, available: Size) Size { _ = available; if (self.peer) |peer| { return peer.getPreferredSize(); @@ -53,22 +53,22 @@ pub const Button_Impl = struct { } } - pub fn setLabel(self: *Button_Impl, label: [:0]const u8) void { + pub fn setLabel(self: *Button, label: [:0]const u8) void { self.label.set(label); } - pub fn getLabel(self: *Button_Impl) [:0]const u8 { + pub fn getLabel(self: *Button) [:0]const u8 { return self.label.get(); } - pub fn _deinit(self: *Button_Impl) void { + pub fn _deinit(self: *Button) void { self.enabled.deinit(); self.label.deinit(); } }; -pub fn Button(config: Button_Impl.Config) Button_Impl { - var btn = Button_Impl.init(); +pub fn button(config: Button.Config) Button { + var btn = Button.init(); btn.label.set(config.label); btn.enabled.set(config.enabled); btn.widget_data.atoms.name.set(config.name); @@ -78,20 +78,20 @@ pub fn Button(config: Button_Impl.Config) Button_Impl { return btn; } -test "Button" { - var button = Button(.{ .label = "Test Label" }); - try std.testing.expectEqualStrings("Test Label", button.getLabel()); +test "button" { + var btn = button(.{ .label = "Test Label" }); + try std.testing.expectEqualStrings("Test Label", btn.getLabel()); - button.setLabel("New Label"); - try std.testing.expectEqualStrings("New Label", button.getLabel()); + btn.setLabel("New Label"); + try std.testing.expectEqualStrings("New Label", btn.getLabel()); try backend.init(); - try button.show(); - defer button.deinit(); + try btn.show(); + defer btn.deinit(); - button.enabled.set(true); + btn.enabled.set(true); - try std.testing.expectEqualStrings("New Label", button.getLabel()); - button.setLabel("One more time"); - try std.testing.expectEqualStrings("One more time", button.getLabel()); + try std.testing.expectEqualStrings("New Label", btn.getLabel()); + btn.setLabel("One more time"); + try std.testing.expectEqualStrings("One more time", btn.getLabel()); } diff --git a/src/components/Canvas.zig b/src/components/Canvas.zig index 02a32cd..9ffc30b 100644 --- a/src/components/Canvas.zig +++ b/src/components/Canvas.zig @@ -6,30 +6,30 @@ const Atom = @import("../data.zig").Atom; pub const DrawContext = backend.Canvas.DrawContext; -pub const Canvas_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Canvas_Impl); +pub const Canvas = struct { + pub usingnamespace @import("../internal.zig").All(Canvas); peer: ?backend.Canvas = null, - widget_data: Canvas_Impl.WidgetData = .{}, + widget_data: Canvas.WidgetData = .{}, preferredSize: Atom(?Size) = Atom(?Size).of(null), pub const DrawContext = backend.Canvas.DrawContext; - pub fn init() Canvas_Impl { - return Canvas_Impl.init_events(Canvas_Impl{}); + pub fn init() Canvas { + return Canvas.init_events(Canvas{}); } - pub fn getPreferredSize(self: *Canvas_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Canvas, available: Size) Size { // As it's a canvas, by default it should take the available space return self.preferredSize.get() orelse available; } - pub fn setPreferredSize(self: *Canvas_Impl, preferred: Size) Canvas_Impl { + pub fn setPreferredSize(self: *Canvas, preferred: Size) Canvas { self.preferredSize.set(preferred); return self.*; } - pub fn show(self: *Canvas_Impl) !void { + pub fn show(self: *Canvas) !void { if (self.peer == null) { self.peer = try backend.Canvas.create(); try self.show_events(); @@ -37,45 +37,45 @@ pub const Canvas_Impl = struct { } }; -pub fn Canvas(config: Canvas_Impl.Config) Canvas_Impl { - var btn = Canvas_Impl.init(); - btn.preferredSize = Atom(?Size).of(config.preferredSize); - btn.widget_data.atoms.name.set(config.name); +pub fn canvas(config: Canvas.Config) Canvas { + var cnv = Canvas.init(); + cnv.preferredSize = Atom(?Size).of(config.preferredSize); + cnv.widget_data.atoms.name.set(config.name); if (config.onclick) |onclick| { - btn.addClickHandler(onclick) catch unreachable; // TODO: improve + cnv.addClickHandler(onclick) catch unreachable; // TODO: improve } if (config.ondraw) |ondraw| { - btn.addDrawHandler(ondraw) catch unreachable; // TODO: improve + cnv.addDrawHandler(ondraw) catch unreachable; // TODO: improve } - return btn; + return cnv; } const Color = @import("../color.zig").Color; -pub const Rect_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Rect_Impl); +pub const Rect = struct { + pub usingnamespace @import("../internal.zig").All(Rect); peer: ?backend.Canvas = null, - widget_data: Rect_Impl.WidgetData = .{}, + widget_data: Rect.WidgetData = .{}, preferredSize: Atom(?Size) = Atom(?Size).of(null), color: Atom(Color) = Atom(Color).of(Color.black), cornerRadius: Atom([4]f32) = Atom([4]f32).of(.{0.0} ** 4), - pub fn init() Rect_Impl { - return Rect_Impl.init_events(Rect_Impl{}); + pub fn init() Rect { + return Rect.init_events(Rect{}); } - pub fn getPreferredSize(self: *Rect_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Rect, available: Size) Size { return self.preferredSize.get() orelse available.intersect(Size.init(0, 0)); } - pub fn setPreferredSize(self: *Rect_Impl, preferred: Size) Rect_Impl { + pub fn setPreferredSize(self: *Rect, preferred: Size) Rect { self.preferredSize.set(preferred); return self.*; } - pub fn draw(self: *Rect_Impl, ctx: *Canvas_Impl.DrawContext) !void { + pub fn draw(self: *Rect, ctx: *Canvas.DrawContext) !void { ctx.setColorByte(self.color.get()); if (builtin.os.tag == .windows) { ctx.rectangle(0, 0, self.getWidth(), self.getHeight()); @@ -85,7 +85,7 @@ pub const Rect_Impl = struct { ctx.fill(); } - pub fn show(self: *Rect_Impl) !void { + pub fn show(self: *Rect) !void { if (self.peer == null) { self.peer = try backend.Canvas.create(); _ = try self.color.addChangeListener(.{ .function = struct { @@ -105,29 +105,29 @@ pub const Rect_Impl = struct { } }; -pub fn Rect(config: Rect_Impl.Config) Rect_Impl { - var rect = Rect_Impl.init(); - rect.addDrawHandler(&Rect_Impl.draw) catch unreachable; - rect.preferredSize = Atom(?Size).of(config.preferredSize); - rect.color = Atom(Color).of(config.color); - rect.cornerRadius = Atom([4]f32).of(config.cornerRadius); - rect.widget_data.atoms.name.set(config.name); - return rect; +pub fn rect(config: Rect.Config) Rect { + var r = Rect.init(); + r.addDrawHandler(&Rect.draw) catch unreachable; + r.preferredSize = Atom(?Size).of(config.preferredSize); + r.color = Atom(Color).of(config.color); + r.cornerRadius = Atom([4]f32).of(config.cornerRadius); + r.widget_data.atoms.name.set(config.name); + return r; } const fuzz = @import("../fuzz.zig"); test "instantiate Canvas" { - var canvas = Canvas(.{}); - defer canvas.deinit(); + var cnv = canvas(.{}); + defer cnv.deinit(); } test "instantiate Rect" { - var rect = Rect(.{ .color = Color.blue }); - defer rect.deinit(); - try std.testing.expectEqual(Color.blue, rect.color.get()); + var rect1 = rect(.{ .color = Color.blue }); + defer rect1.deinit(); + try std.testing.expectEqual(Color.blue, rect1.color.get()); - var rect2 = Rect(.{ .color = Color.yellow }); + var rect2 = rect(.{ .color = Color.yellow }); defer rect2.deinit(); try std.testing.expectEqual(Color.yellow, rect2.color.get()); } diff --git a/src/components/CheckBox.zig b/src/components/CheckBox.zig index 52d2993..a72914a 100644 --- a/src/components/CheckBox.zig +++ b/src/components/CheckBox.zig @@ -4,20 +4,20 @@ const Size = @import("../data.zig").Size; const Atom = @import("../data.zig").Atom; const Container_Impl = @import("../containers.zig").Container_Impl; -pub const CheckBox_Impl = struct { - pub usingnamespace @import("../internal.zig").All(CheckBox_Impl); +pub const CheckBox = struct { + pub usingnamespace @import("../internal.zig").All(CheckBox); peer: ?backend.CheckBox = null, - widget_data: CheckBox_Impl.WidgetData = .{}, + widget_data: CheckBox.WidgetData = .{}, checked: Atom(bool) = Atom(bool).of(false), label: Atom([:0]const u8) = Atom([:0]const u8).of(""), enabled: Atom(bool) = Atom(bool).of(true), - pub fn init() CheckBox_Impl { - return CheckBox_Impl.init_events(CheckBox_Impl{}); + pub fn init() CheckBox { + return CheckBox.init_events(CheckBox{}); } - pub fn _pointerMoved(self: *CheckBox_Impl) void { + pub fn _pointerMoved(self: *CheckBox) void { self.enabled.updateBinders(); self.checked.updateBinders(); } @@ -37,11 +37,11 @@ pub const CheckBox_Impl = struct { peer.*.?.setLabel(newValue); } - fn onClick(self: *CheckBox_Impl) !void { + fn onClick(self: *CheckBox) !void { self.checked.set(self.peer.?.isChecked()); } - pub fn show(self: *CheckBox_Impl) !void { + pub fn show(self: *CheckBox) !void { if (self.peer == null) { self.peer = try backend.CheckBox.create(); self.peer.?.setChecked(self.checked.get()); @@ -57,7 +57,7 @@ pub const CheckBox_Impl = struct { } } - pub fn getPreferredSize(self: *CheckBox_Impl, available: Size) Size { + pub fn getPreferredSize(self: *CheckBox, available: Size) Size { _ = available; if (self.peer) |peer| { return peer.getPreferredSize(); @@ -66,21 +66,21 @@ pub const CheckBox_Impl = struct { } } - pub fn setLabel(self: *CheckBox_Impl, label: [:0]const u8) void { + pub fn setLabel(self: *CheckBox, label: [:0]const u8) void { self.label.set(label); } - pub fn getLabel(self: *CheckBox_Impl) [:0]const u8 { + pub fn getLabel(self: *CheckBox) [:0]const u8 { return self.label.get(); } - pub fn _deinit(self: *CheckBox_Impl) void { + pub fn _deinit(self: *CheckBox) void { self.enabled.deinit(); } }; -pub fn CheckBox(config: CheckBox_Impl.Config) CheckBox_Impl { - var btn = CheckBox_Impl.init(); +pub fn checkBox(config: CheckBox.Config) CheckBox { + var btn = CheckBox.init(); btn.checked.set(config.checked); btn.label.set(config.label); btn.enabled.set(config.enabled); diff --git a/src/components/Image.zig b/src/components/Image.zig index bf52eb0..ec7dfce 100644 --- a/src/components/Image.zig +++ b/src/components/Image.zig @@ -14,11 +14,11 @@ const ScalableVectorData = @import("../image.zig").ScalableVectorData; // TODO: convert to using a flat component so a backend may provide an Image backend /// Component used to show an image. -pub const Image_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Image_Impl); +pub const Image = struct { + pub usingnamespace @import("../internal.zig").All(Image); peer: ?backend.Canvas = null, - widget_data: Image_Impl.WidgetData = .{}, + widget_data: Image.WidgetData = .{}, url: Atom([]const u8), data: Atom(?ImageData) = Atom(?ImageData).of(null), scaling: Atom(Scaling) = Atom(Scaling).of(.Fit), @@ -40,17 +40,17 @@ pub const Image_Impl = struct { pub const DrawContext = backend.Canvas.DrawContext; // TODO: just directly accept an URL or file path if there's no data - pub fn init(config: Image_Impl.Config) Image_Impl { - var image = Image_Impl.init_events(Image_Impl{ + pub fn init(config: Image.Config) Image { + var self = Image.init_events(Image{ .url = Atom([]const u8).of(config.url), .data = Atom(?ImageData).of(config.data), .scaling = Atom(Scaling).of(config.scaling), }); - image.addDrawHandler(&Image_Impl.draw) catch unreachable; - return image; + self.addDrawHandler(&Image.draw) catch unreachable; + return self; } - pub fn getPreferredSize(self: *Image_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Image, available: Size) Size { if (self.data.get()) |data| { return Size.init(data.width, data.height); } else { @@ -58,7 +58,7 @@ pub const Image_Impl = struct { } } - fn loadImage(self: *Image_Impl) !void { + fn loadImage(self: *Image) !void { // TODO: asynchronous loading var handle = try assets.get(self.url.get()); defer handle.deinit(); @@ -72,7 +72,7 @@ pub const Image_Impl = struct { self.data.set(data); } - pub fn draw(self: *Image_Impl, ctx: *DrawContext) !void { + pub fn draw(self: *Image, ctx: *DrawContext) !void { const width = self.getWidth(); const height = self.getHeight(); @@ -88,57 +88,57 @@ pub const Image_Impl = struct { return; } - const image = self.data.get().?; + const img = self.data.get().?; switch (self.scaling.get()) { .None => { - const imageX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(image.width / 2)); - const imageY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(image.height / 2)); + const imgX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(img.width / 2)); + const imgY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(img.height / 2)); ctx.image( - imageX, - imageY, - image.width, - image.height, - image, + imgX, + imgY, + img.width, + img.height, + img, ); }, .Fit => { - // The aspect ratio of the image - const ratio = @as(f32, @floatFromInt(image.width)) / @as(f32, @floatFromInt(image.height)); - var imageW: u32 = undefined; - var imageH: u32 = undefined; + // The aspect ratio of the img + const ratio = @as(f32, @floatFromInt(img.width)) / @as(f32, @floatFromInt(img.height)); + var imgW: u32 = undefined; + var imgH: u32 = undefined; if (@as(f32, @floatFromInt(width)) / ratio < @as(f32, @floatFromInt(height))) { - imageW = width; - imageH = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imageW)) / ratio)); + imgW = width; + imgH = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imgW)) / ratio)); } else { - imageH = height; - imageW = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imageH)) * ratio)); + imgH = height; + imgW = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imgH)) * ratio)); } - const imageX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(imageW / 2)); - const imageY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(imageH / 2)); + const imgX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(imgW / 2)); + const imgY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(imgH / 2)); ctx.image( - imageX, - imageY, - imageW, - imageH, - image, + imgX, + imgY, + imgW, + imgH, + img, ); }, .Stretch => { ctx.image( 0, 0, - image.width, - image.height, - image, + img.width, + img.height, + img, ); }, } } - pub fn show(self: *Image_Impl) !void { + pub fn show(self: *Image) !void { if (self.peer == null) { self.peer = try backend.Canvas.create(); try self.show_events(); @@ -146,7 +146,7 @@ pub const Image_Impl = struct { } }; -pub fn Image(config: Image_Impl.Config) Image_Impl { - var image = Image_Impl.init(config); - return image; +pub fn image(config: Image.Config) Image { + var img = Image.init(config); + return img; } diff --git a/src/components/Label.zig b/src/components/Label.zig index a59b0c9..91542e1 100644 --- a/src/components/Label.zig +++ b/src/components/Label.zig @@ -3,32 +3,32 @@ const backend = @import("../backend.zig"); const Size = @import("../data.zig").Size; const Atom = @import("../data.zig").Atom; -pub const Label_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Label_Impl); +pub const Label = struct { + pub usingnamespace @import("../internal.zig").All(Label); peer: ?backend.Label = null, - widget_data: Label_Impl.WidgetData = .{}, + widget_data: Label.WidgetData = .{}, text: Atom([]const u8) = Atom([]const u8).of(""), alignment: Atom(TextAlignment) = Atom(TextAlignment).of(.Left), - pub fn init(config: Label_Impl.Config) Label_Impl { - return Label_Impl.init_events(Label_Impl{ + pub fn init(config: Label.Config) Label { + return Label.init_events(Label{ .text = Atom([]const u8).of(config.text), .alignment = Atom(TextAlignment).of(config.alignment), }); } - pub fn _pointerMoved(self: *Label_Impl) void { + pub fn _pointerMoved(self: *Label) void { self.text.updateBinders(); self.alignment.updateBinders(); } fn wrapperTextChanged(newValue: []const u8, userdata: usize) void { - const self = @as(*Label_Impl, @ptrFromInt(userdata)); + const self = @as(*Label, @ptrFromInt(userdata)); self.peer.?.setText(newValue); } - pub fn show(self: *Label_Impl) !void { + pub fn show(self: *Label) !void { if (self.peer == null) { var peer = try backend.Label.create(); peer.setText(self.text.get()); @@ -43,7 +43,7 @@ pub const Label_Impl = struct { } } - pub fn getPreferredSize(self: *Label_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Label, available: Size) Size { _ = available; if (self.peer) |peer| { return peer.getPreferredSize(); @@ -53,23 +53,23 @@ pub const Label_Impl = struct { } } - pub fn setText(self: *Label_Impl, text: []const u8) void { + pub fn setText(self: *Label, text: []const u8) void { self.text.set(text); } - pub fn getText(self: *Label_Impl) []const u8 { + pub fn getText(self: *Label) []const u8 { return self.text.get(); } }; pub const TextAlignment = enum { Left, Center, Right }; -pub fn Label(config: Label_Impl.Config) Label_Impl { - return Label_Impl.init(config); +pub fn label(config: Label.Config) Label { + return Label.init(config); } // TODO: replace with an actual empty element from the backend // Although this is not necessary and would only provide minimal memory/performance gains -pub fn Spacing() !@import("../widget.zig").Widget { - return try @import("../containers.zig").Expanded(Label(.{})); +pub fn spacing() !@import("../widget.zig").Widget { + return try @import("../containers.zig").expanded(label(.{})); } diff --git a/src/components/Menu.zig b/src/components/Menu.zig index 1cd26a0..c55215c 100644 --- a/src/components/Menu.zig +++ b/src/components/Menu.zig @@ -5,14 +5,14 @@ const Size = @import("../data.zig").Size; const DataWrapper = @import("../data.zig").DataWrapper; const Widget = @import("../widget.zig").Widget; -pub const MenuItem_Impl = struct { +pub const MenuItem = struct { config: Config, /// If there are no items, this is a menu item /// Otherwise, this is a menu - items: []const MenuItem_Impl = &.{}, + items: []const MenuItem = &.{}, }; -pub const MenuBar_Impl = struct { menus: []const MenuItem_Impl }; +pub const MenuBar = struct { menus: []const MenuItem }; const Config = struct { pub const Callback = fn () void; @@ -21,16 +21,16 @@ const Config = struct { onClick: ?*const Callback = null, }; -pub fn MenuItem(config: Config) MenuItem_Impl { - return MenuItem_Impl{ .config = config }; +pub fn menuItem(config: Config) MenuItem { + return MenuItem{ .config = config }; } /// 'items' is a tuple -pub fn Menu(config: Config, items: anytype) MenuItem_Impl { - return MenuItem_Impl{ .config = config, .items = internal.lasting_allocator.dupe(MenuItem_Impl, &items) catch unreachable }; +pub fn menu(config: Config, items: anytype) MenuItem { + return MenuItem{ .config = config, .items = internal.lasting_allocator.dupe(MenuItem, &items) catch unreachable }; } /// 'menus' is a tuple -pub fn MenuBar(menus: anytype) MenuBar_Impl { - return MenuBar_Impl{ .menus = internal.lasting_allocator.dupe(MenuItem_Impl, &menus) catch unreachable }; +pub fn menuBar(menus: anytype) MenuBar { + return MenuBar{ .menus = internal.lasting_allocator.dupe(MenuItem, &menus) catch unreachable }; } diff --git a/src/components/Navigation.zig b/src/components/Navigation.zig index 6179617..6370858 100644 --- a/src/components/Navigation.zig +++ b/src/components/Navigation.zig @@ -5,21 +5,21 @@ const Size = @import("../data.zig").Size; const Atom = @import("../data.zig").Atom; const Widget = @import("../widget.zig").Widget; -pub const Navigation_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Navigation_Impl); +pub const Navigation = struct { + pub usingnamespace @import("../internal.zig").All(Navigation); peer: ?backend.Container = null, - widget_data: Navigation_Impl.WidgetData = .{}, + widget_data: Navigation.WidgetData = .{}, relayouting: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false), routeName: Atom([]const u8), activeChild: *Widget, routes: std.StringHashMap(Widget), - pub fn init(config: Navigation_Impl.Config, routes: std.StringHashMap(Widget)) !Navigation_Impl { + pub fn init(config: Navigation.Config, routes: std.StringHashMap(Widget)) !Navigation { var iterator = routes.valueIterator(); const activeChild = iterator.next() orelse @panic("navigation component is empty"); - var component = Navigation_Impl.init_events(Navigation_Impl{ + var component = Navigation.init_events(Navigation{ .routeName = Atom([]const u8).of(config.routeName), .routes = routes, .activeChild = activeChild, @@ -29,15 +29,15 @@ pub const Navigation_Impl = struct { return component; } - pub fn _pointerMoved(self: *Navigation_Impl) void { + pub fn _pointerMoved(self: *Navigation) void { self.routeName.updateBinders(); } - pub fn onResize(self: *Navigation_Impl, _: Size) !void { + pub fn onResize(self: *Navigation, _: Size) !void { self.relayout(); } - pub fn getChild(self: *Navigation_Impl, name: []const u8) ?*Widget { + pub fn getChild(self: *Navigation, name: []const u8) ?*Widget { // TODO: check self.activeChild.get if it's a container or something like that if (self.activeChild.name.*.get()) |child_name| { if (std.mem.eql(u8, child_name, name)) { @@ -47,12 +47,12 @@ pub const Navigation_Impl = struct { return null; } - pub fn _showWidget(widget: *Widget, self: *Navigation_Impl) !void { + pub fn _showWidget(widget: *Widget, self: *Navigation) !void { self.activeChild.parent = widget; self.activeChild.class.setWidgetFn(self.activeChild); } - pub fn show(self: *Navigation_Impl) !void { + pub fn show(self: *Navigation) !void { if (self.peer == null) { var peer = try backend.Container.create(); self.peer = peer; @@ -65,7 +65,7 @@ pub const Navigation_Impl = struct { } } - pub fn relayout(self: *Navigation_Impl) void { + pub fn relayout(self: *Navigation) void { if (self.relayouting.load(.SeqCst) == true) return; if (self.peer) |peer| { self.relayouting.store(true, .SeqCst); @@ -86,14 +86,14 @@ pub const Navigation_Impl = struct { /// Go deep inside the given URI. /// This will show up as entering the given screen, which you can exit using pop() /// This is analoguous to zooming in on a screen. - pub fn push(self: *Navigation_Impl, name: []const u8, params: anytype) void { + pub fn push(self: *Navigation, name: []const u8, params: anytype) void { // TODO: implement push self.navigateTo(name, params); } /// Navigate to a given screen without pushing it on the stack. /// This is analoguous to sliding to a screen. - pub fn navigateTo(self: *Navigation_Impl, name: []const u8, params: anytype) !void { + pub fn navigateTo(self: *Navigation, name: []const u8, params: anytype) !void { _ = params; if (self.peer) |*peer| { peer.remove(self.activeChild.peer.?); @@ -104,16 +104,16 @@ pub const Navigation_Impl = struct { } } - pub fn pop(self: *Navigation_Impl) void { + pub fn pop(self: *Navigation) void { _ = self; // TODO: implement pop } - pub fn getPreferredSize(self: *Navigation_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Navigation, available: Size) Size { return self.activeChild.getPreferredSize(available); } - pub fn _deinit(self: *Navigation_Impl) void { + pub fn _deinit(self: *Navigation) void { var iterator = self.routes.valueIterator(); while (iterator.next()) |widget| { widget.deinit(); @@ -121,7 +121,7 @@ pub const Navigation_Impl = struct { } }; -pub fn Navigation(opts: Navigation_Impl.Config, children: anytype) anyerror!Navigation_Impl { +pub fn navigation(opts: Navigation.Config, children: anytype) anyerror!Navigation { var routes = std.StringHashMap(Widget).init(internal.lasting_allocator); const fields = std.meta.fields(@TypeOf(children)); @@ -136,5 +136,5 @@ pub fn Navigation(opts: Navigation_Impl.Config, children: anytype) anyerror!Navi try routes.put(field.name, widget); } - return try Navigation_Impl.init(opts, routes); + return try Navigation.init(opts, routes); } diff --git a/src/components/NavigationSidebar.zig b/src/components/NavigationSidebar.zig index 55e0eae..85eb231 100644 --- a/src/components/NavigationSidebar.zig +++ b/src/components/NavigationSidebar.zig @@ -4,28 +4,28 @@ const Size = @import("../data.zig").Size; const DataWrapper = @import("../data.zig").DataWrapper; const Container_Impl = @import("../containers.zig").Container_Impl; -pub const NavigationSidebar_Impl = struct { - pub usingnamespace @import("../internal.zig").All(NavigationSidebar_Impl); +pub const NavigationSidebar = struct { + pub usingnamespace @import("../internal.zig").All(NavigationSidebar); peer: ?backend.NavigationSidebar = null, - widget_data: NavigationSidebar_Impl.WidgetData = .{}, + widget_data: NavigationSidebar.WidgetData = .{}, - pub fn init() NavigationSidebar_Impl { - return NavigationSidebar_Impl.init_events(NavigationSidebar_Impl{}); + pub fn init() NavigationSidebar { + return NavigationSidebar.init_events(NavigationSidebar{}); } - pub fn _pointerMoved(self: *NavigationSidebar_Impl) void { + pub fn _pointerMoved(self: *NavigationSidebar) void { _ = self; } - pub fn show(self: *NavigationSidebar_Impl) !void { + pub fn show(self: *NavigationSidebar) !void { if (self.peer == null) { self.peer = try backend.NavigationSidebar.create(); try self.show_events(); } } - pub fn getPreferredSize(self: *NavigationSidebar_Impl, available: Size) Size { + pub fn getPreferredSize(self: *NavigationSidebar, available: Size) Size { _ = available; if (self.peer) |peer| { return peer.getPreferredSize(); @@ -35,8 +35,8 @@ pub const NavigationSidebar_Impl = struct { } }; -pub fn NavigationSidebar(config: NavigationSidebar_Impl.Config) NavigationSidebar_Impl { - var btn = NavigationSidebar_Impl.init(); +pub fn navigationSidebar(config: NavigationSidebar.Config) NavigationSidebar { + var btn = NavigationSidebar.init(); btn.widget_data.atoms.name.set(config.name); if (config.onclick) |onclick| { btn.addClickHandler(onclick) catch unreachable; // TODO: improve diff --git a/src/components/Scrollable.zig b/src/components/Scrollable.zig index 01aeb17..e61cb33 100644 --- a/src/components/Scrollable.zig +++ b/src/components/Scrollable.zig @@ -4,18 +4,18 @@ const Size = @import("../data.zig").Size; const DataWrapper = @import("../data.zig").DataWrapper; const Widget = @import("../widget.zig").Widget; -pub const Scrollable_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Scrollable_Impl); +pub const Scrollable = struct { + pub usingnamespace @import("../internal.zig").All(Scrollable); peer: ?backend.ScrollView = null, - widget_data: Scrollable_Impl.WidgetData = .{}, + widget_data: Scrollable.WidgetData = .{}, child: Widget, - pub fn init(widget: Widget) Scrollable_Impl { - return Scrollable_Impl.init_events(Scrollable_Impl{ .child = widget }); + pub fn init(widget: Widget) Scrollable { + return Scrollable.init_events(Scrollable{ .child = widget }); } - pub fn show(self: *Scrollable_Impl) !void { + pub fn show(self: *Scrollable) !void { if (self.peer == null) { var peer = try backend.ScrollView.create(); try self.child.show(); @@ -25,12 +25,12 @@ pub const Scrollable_Impl = struct { } } - pub fn getPreferredSize(self: *Scrollable_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Scrollable, available: Size) Size { return self.child.getPreferredSize(available); } }; -pub fn Scrollable(element: anytype) anyerror!Scrollable_Impl { +pub fn scrollable(element: anytype) anyerror!Scrollable { const child = if (comptime @import("../internal.zig").isErrorUnion(@TypeOf(element))) try element @@ -38,5 +38,5 @@ pub fn Scrollable(element: anytype) anyerror!Scrollable_Impl { element; const widget = try @import("../internal.zig").genericWidgetFrom(child); - return Scrollable_Impl.init(widget); + return Scrollable.init(widget); } diff --git a/src/components/Slider.zig b/src/components/Slider.zig index 3350a28..c3257f4 100644 --- a/src/components/Slider.zig +++ b/src/components/Slider.zig @@ -12,11 +12,11 @@ pub const Orientation = enum { Horizontal, Vertical }; /// /// To avoid any cross-platform bugs, ensure that min/stepSize and /// max/stepSize both are between -32767 and 32768. -pub const Slider_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Slider_Impl); +pub const Slider = struct { + pub usingnamespace @import("../internal.zig").All(Slider); peer: ?backend.Slider = null, - widget_data: Slider_Impl.WidgetData = .{}, + widget_data: Slider.WidgetData = .{}, value: Atom(f32) = Atom(f32).of(0), /// The minimum value of the slider. /// Note that min MUST be below or equal to max. @@ -29,14 +29,14 @@ pub const Slider_Impl = struct { step: Atom(f32) = Atom(f32).of(1), enabled: Atom(bool) = Atom(bool).of(true), - pub fn init() Slider_Impl { - return Slider_Impl.init_events(Slider_Impl{ + pub fn init() Slider { + return Slider.init_events(Slider{ .min = Atom(f32).of(undefined), .max = Atom(f32).of(undefined), }); } - pub fn _pointerMoved(self: *Slider_Impl) void { + pub fn _pointerMoved(self: *Slider) void { self.enabled.updateBinders(); } @@ -65,14 +65,14 @@ pub const Slider_Impl = struct { peer.*.?.setEnabled(newValue); } - fn onPropertyChange(self: *Slider_Impl, property_name: []const u8, new_value: *const anyopaque) !void { + fn onPropertyChange(self: *Slider, property_name: []const u8, new_value: *const anyopaque) !void { if (std.mem.eql(u8, property_name, "value")) { const value = @as(*const f32, @ptrCast(@alignCast(new_value))); self.value.set(value.*); } } - pub fn show(self: *Slider_Impl) !void { + pub fn show(self: *Slider) !void { if (self.peer == null) { self.peer = try backend.Slider.create(); self.peer.?.setMinimum(self.min.get()); @@ -92,7 +92,7 @@ pub const Slider_Impl = struct { } } - pub fn getPreferredSize(self: *Slider_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Slider, available: Size) Size { _ = available; if (self.peer) |peer| { return peer.getPreferredSize(); @@ -101,21 +101,21 @@ pub const Slider_Impl = struct { } } - pub fn _deinit(self: *Slider_Impl) void { + pub fn _deinit(self: *Slider) void { self.enabled.deinit(); } }; -pub fn Slider(config: Slider_Impl.Config) Slider_Impl { - var slider = Slider_Impl.init(); - slider.min.set(config.min); - slider.max.set(config.max); - slider.value.set(config.value); - slider.step.set(config.step); - slider.enabled.set(config.enabled); - slider.widget_data.atoms.name.set(config.name); +pub fn slider(config: Slider.Config) Slider { + var s = Slider.init(); + s.min.set(config.min); + s.max.set(config.max); + s.value.set(config.value); + s.step.set(config.step); + s.enabled.set(config.enabled); + s.widget_data.atoms.name.set(config.name); if (config.onclick) |onclick| { - slider.addClickHandler(onclick) catch unreachable; // TODO: improve + s.addClickHandler(onclick) catch unreachable; // TODO: improve } - return slider; + return s; } diff --git a/src/components/Tabs.zig b/src/components/Tabs.zig index 82d0e18..df997f0 100644 --- a/src/components/Tabs.zig +++ b/src/components/Tabs.zig @@ -4,46 +4,46 @@ const Size = @import("../data.zig").Size; const Atom = @import("../data.zig").Atom; const Widget = @import("../widget.zig").Widget; -pub const Tabs_Impl = struct { - pub usingnamespace @import("../internal.zig").All(Tabs_Impl); +pub const Tabs = struct { + pub usingnamespace @import("../internal.zig").All(Tabs); peer: ?backend.TabContainer = null, - widget_data: Tabs_Impl.WidgetData = .{}, - tabs: std.ArrayList(Tab_Impl), + widget_data: Tabs.WidgetData = .{}, + tabs: std.ArrayList(Tab), - /// The widget associated to this Tabs_Impl + /// The widget associated to this Tabs widget: ?*Widget = null, - pub fn init(tabs: std.ArrayList(Tab_Impl)) Tabs_Impl { - return Tabs_Impl.init_events(Tabs_Impl{ .tabs = tabs }); + pub fn init(tabs_list: std.ArrayList(Tab)) Tabs { + return Tabs.init_events(Tabs{ .tabs = tabs_list }); } - pub fn show(self: *Tabs_Impl) !void { + pub fn show(self: *Tabs) !void { if (self.peer == null) { var peer = try backend.TabContainer.create(); - for (self.tabs.items) |*tab| { - try tab.widget.show(); - const tabPosition = peer.insert(peer.getTabsNumber(), tab.widget.peer.?); - peer.setLabel(tabPosition, tab.label); + for (self.tabs.items) |*tab_ptr| { + try tab_ptr.widget.show(); + const tabPosition = peer.insert(peer.getTabsNumber(), tab_ptr.widget.peer.?); + peer.setLabel(tabPosition, tab_ptr.label); } self.peer = peer; try self.show_events(); } } - pub fn getPreferredSize(self: *Tabs_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Tabs, available: Size) Size { _ = self; return available; // TODO } - pub fn _showWidget(widget: *Widget, self: *Tabs_Impl) !void { + pub fn _showWidget(widget: *Widget, self: *Tabs) !void { self.widget = widget; for (self.tabs.items) |*child| { child.widget.parent = widget; } } - pub fn add(self: *Tabs_Impl, widget: anytype) !void { + pub fn add(self: *Tabs, widget: anytype) !void { const ComponentType = @import("../internal.zig").DereferencedType(@TypeOf(widget)); var genericWidget = try @import("../internal.zig").genericWidgetFrom(widget); @@ -63,9 +63,9 @@ pub const Tabs_Impl = struct { } } - pub fn _deinit(self: *Tabs_Impl) void { - for (self.tabs.items) |*tab| { - tab.widget.deinit(); + pub fn _deinit(self: *Tabs) void { + for (self.tabs.items) |*tab_ptr| { + tab_ptr.widget.deinit(); } self.tabs.deinit(); } @@ -78,24 +78,24 @@ fn isErrorUnion(comptime T: type) bool { }; } -pub inline fn Tabs(children: anytype) anyerror!Tabs_Impl { +pub inline fn tabs(children: anytype) anyerror!Tabs { const fields = std.meta.fields(@TypeOf(children)); - var list = std.ArrayList(Tab_Impl).init(@import("../internal.zig").lasting_allocator); + var list = std.ArrayList(Tab).init(@import("../internal.zig").lasting_allocator); inline for (fields) |field| { const element = @field(children, field.name); - const tab = + const tab1 = if (comptime isErrorUnion(@TypeOf(element))) // if it is an error union, unwrap it try element else element; const slot = try list.addOne(); - slot.* = tab; + slot.* = tab1; slot.*.widget.class.setWidgetFn(&slot.*.widget); } - return Tabs_Impl.init(list); + return Tabs.init(list); } -pub const Tab_Impl = struct { +pub const Tab = struct { label: [:0]const u8, widget: Widget, }; @@ -104,12 +104,12 @@ pub const TabConfig = struct { label: [:0]const u8 = "", }; -pub inline fn Tab(config: TabConfig, child: anytype) anyerror!Tab_Impl { +pub inline fn tab(config: TabConfig, child: anytype) anyerror!Tab { const widget = try @import("../internal.zig").genericWidgetFrom(if (comptime isErrorUnion(@TypeOf(child))) try child else child); - return Tab_Impl{ + return Tab{ .label = config.label, .widget = widget, }; diff --git a/src/components/TextArea.zig b/src/components/TextArea.zig index c988ca5..35512c8 100644 --- a/src/components/TextArea.zig +++ b/src/components/TextArea.zig @@ -6,11 +6,11 @@ const Size = dataStructures.Size; const Atom = dataStructures.Atom; const StringAtom = dataStructures.StringAtom; -pub const TextArea_Impl = struct { - pub usingnamespace internal.All(TextArea_Impl); +pub const TextArea = struct { + pub usingnamespace internal.All(TextArea); peer: ?backend.TextArea = null, - widget_data: TextArea_Impl.WidgetData = .{}, + widget_data: TextArea.WidgetData = .{}, text: StringAtom = StringAtom.of(""), _wrapperTextBlock: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false), @@ -18,8 +18,8 @@ pub const TextArea_Impl = struct { /// Whether to let the system choose a monospace font for us and use it in this TextArea.. monospace: Atom(bool) = Atom(bool).of(false), - pub fn init(config: TextArea_Impl.Config) TextArea_Impl { - var area = TextArea_Impl.init_events(TextArea_Impl{ + pub fn init(config: TextArea.Config) TextArea { + var area = TextArea.init_events(TextArea{ .text = StringAtom.of(config.text), .monospace = Atom(bool).of(config.monospace), }); @@ -27,25 +27,25 @@ pub const TextArea_Impl = struct { return area; } - pub fn _pointerMoved(self: *TextArea_Impl) void { + pub fn _pointerMoved(self: *TextArea) void { self.text.updateBinders(); self.monospace.updateBinders(); } fn wrapperTextChanged(newValue: []const u8, userdata: usize) void { - const self = @as(*TextArea_Impl, @ptrFromInt(userdata)); + const self = @as(*TextArea, @ptrFromInt(userdata)); if (self._wrapperTextBlock.load(.Monotonic) == true) return; self.peer.?.setText(newValue); } fn wrapperMonospaceChanged(newValue: bool, userdata: usize) void { - const self = @as(*TextArea_Impl, @ptrFromInt(userdata)); + const self = @as(*TextArea, @ptrFromInt(userdata)); self.peer.?.setMonospaced(newValue); } fn textChanged(userdata: usize) void { - const self = @as(*TextArea_Impl, @ptrFromInt(userdata)); + const self = @as(*TextArea, @ptrFromInt(userdata)); const text = self.peer.?.getText(); self._wrapperTextBlock.store(true, .Monotonic); @@ -53,7 +53,7 @@ pub const TextArea_Impl = struct { self.text.set(text); } - pub fn show(self: *TextArea_Impl) !void { + pub fn show(self: *TextArea) !void { if (self.peer == null) { var peer = try backend.TextArea.create(); peer.setText(self.text.get()); @@ -67,7 +67,7 @@ pub const TextArea_Impl = struct { } } - pub fn getPreferredSize(self: *TextArea_Impl, available: Size) Size { + pub fn getPreferredSize(self: *TextArea, available: Size) Size { _ = available; if (self.peer) |peer| { return peer.getPreferredSize(); @@ -76,15 +76,15 @@ pub const TextArea_Impl = struct { } } - pub fn setText(self: *TextArea_Impl, text: []const u8) void { + pub fn setText(self: *TextArea, text: []const u8) void { self.text.set(text); } - pub fn getText(self: *TextArea_Impl) []const u8 { + pub fn getText(self: *TextArea) []const u8 { return self.text.get(); } }; -pub fn TextArea(config: TextArea_Impl.Config) TextArea_Impl { - return TextArea_Impl.init(config); +pub fn textArea(config: TextArea.Config) TextArea { + return TextArea.init(config); } diff --git a/src/components/TextField.zig b/src/components/TextField.zig index 1a241a0..705d591 100644 --- a/src/components/TextField.zig +++ b/src/components/TextField.zig @@ -6,18 +6,18 @@ const Size = dataStructures.Size; const Atom = dataStructures.Atom; const StringAtom = dataStructures.StringAtom; -pub const TextField_Impl = struct { - pub usingnamespace internal.All(TextField_Impl); - //pub usingnamespace @import("internal.zig").Property(TextField_Impl, "text"); +pub const TextField = struct { + pub usingnamespace internal.All(TextField); + //pub usingnamespace @import("internal.zig").Property(TextField, "text"); peer: ?backend.TextField = null, - widget_data: TextField_Impl.WidgetData = .{}, + widget_data: TextField.WidgetData = .{}, text: StringAtom = StringAtom.of(""), readOnly: Atom(bool) = Atom(bool).of(false), _wrapperTextBlock: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false), - pub fn init(config: TextField_Impl.Config) TextField_Impl { - var field = TextField_Impl.init_events(TextField_Impl{ + pub fn init(config: TextField.Config) TextField { + var field = TextField.init_events(TextField{ .text = StringAtom.of(config.text), .readOnly = Atom(bool).of(config.readOnly), }); @@ -27,13 +27,13 @@ pub const TextField_Impl = struct { /// Internal function used at initialization. /// It is used to move some pointers so things do not break. - pub fn _pointerMoved(self: *TextField_Impl) void { + pub fn _pointerMoved(self: *TextField) void { self.text.updateBinders(); } /// When the text is changed in the StringAtom fn wrapperTextChanged(newValue: []const u8, userdata: usize) void { - const self = @as(*TextField_Impl, @ptrFromInt(userdata)); + const self = @as(*TextField, @ptrFromInt(userdata)); if (self._wrapperTextBlock.load(.Monotonic) == true) return; self.peer.?.setText(newValue); @@ -45,7 +45,7 @@ pub const TextField_Impl = struct { } fn textChanged(userdata: usize) void { - const self = @as(*TextField_Impl, @ptrFromInt(userdata)); + const self = @as(*TextField, @ptrFromInt(userdata)); const text = self.peer.?.getText(); self._wrapperTextBlock.store(true, .Monotonic); @@ -53,7 +53,7 @@ pub const TextField_Impl = struct { self.text.set(text); } - pub fn show(self: *TextField_Impl) !void { + pub fn show(self: *TextField) !void { if (self.peer == null) { var peer = try backend.TextField.create(); peer.setText(self.text.get()); @@ -67,7 +67,7 @@ pub const TextField_Impl = struct { } } - pub fn getPreferredSize(self: *TextField_Impl, available: Size) Size { + pub fn getPreferredSize(self: *TextField, available: Size) Size { _ = available; if (self.peer) |peer| { return peer.getPreferredSize(); @@ -76,23 +76,23 @@ pub const TextField_Impl = struct { } } - pub fn setText(self: *TextField_Impl, text: []const u8) void { + pub fn setText(self: *TextField, text: []const u8) void { self.text.set(text); } - pub fn getText(self: *TextField_Impl) []const u8 { + pub fn getText(self: *TextField) []const u8 { return self.text.get(); } - pub fn setReadOnly(self: *TextField_Impl, readOnly: bool) void { + pub fn setReadOnly(self: *TextField, readOnly: bool) void { self.readOnly.set(readOnly); } - pub fn isReadOnly(self: *TextField_Impl) bool { + pub fn isReadOnly(self: *TextField) bool { return self.readOnly.get(); } }; -pub fn TextField(config: TextField_Impl.Config) TextField_Impl { - return TextField_Impl.init(config); +pub fn textField(config: TextField.Config) TextField { + return TextField.init(config); } diff --git a/src/containers.zig b/src/containers.zig index 48dba9c..002ccc3 100644 --- a/src/containers.zig +++ b/src/containers.zig @@ -190,7 +190,7 @@ pub fn RowLayout(peer: Callbacks, widgets: []Widget) void { } pub fn MarginLayout(peer: Callbacks, widgets: []Widget) void { - const margin = peer.getLayoutConfig(Rectangle); + const margin_rect = peer.getLayoutConfig(Rectangle); if (widgets.len > 1) { std.log.scoped(.capy).warn("Margin container has more than one widget!", .{}); return; @@ -198,10 +198,10 @@ pub fn MarginLayout(peer: Callbacks, widgets: []Widget) void { if (widgets[0].peer) |widgetPeer| { const available = peer.getSize(peer.userdata); - const left = std.math.lossyCast(u32, margin.x()); - const top = std.math.lossyCast(u32, margin.y()); - const right = margin.width(); - const bottom = margin.height(); + const left = std.math.lossyCast(u32, margin_rect.x()); + const top = std.math.lossyCast(u32, margin_rect.y()); + const right = margin_rect.width(); + const bottom = margin_rect.height(); if (peer.computingPreferredSize) { // What to return for computing preferred size @@ -231,21 +231,21 @@ pub fn StackLayout(peer: Callbacks, widgets: []Widget) void { } } -pub const Container_Impl = struct { - pub usingnamespace @import("internal.zig").All(Container_Impl); +pub const Container = struct { + pub usingnamespace @import("internal.zig").All(Container); peer: ?backend.Container, - widget_data: Container_Impl.WidgetData = .{}, + widget_data: Container.WidgetData = .{}, childrens: std.ArrayList(Widget), expand: bool, relayouting: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false), layout: Layout, layoutConfig: [16]u8, - /// The widget associated to this Container_Impl + /// The widget associated to this Container widget: ?*Widget = null, - pub fn init(childrens: std.ArrayList(Widget), config: GridConfig, layout: Layout, layoutConfig: anytype) !Container_Impl { + pub fn init(childrens: std.ArrayList(Widget), config: GridConfig, layout: Layout, layoutConfig: anytype) !Container { const LayoutConfig = @TypeOf(layoutConfig); comptime std.debug.assert(@sizeOf(LayoutConfig) <= 16); var layoutConfigBytes: [16]u8 = undefined; @@ -253,7 +253,7 @@ pub const Container_Impl = struct { layoutConfigBytes[0..@sizeOf(LayoutConfig)].* = std.mem.toBytes(layoutConfig); } - var container = Container_Impl.init_events(Container_Impl{ + var container = Container.init_events(Container{ .peer = null, .childrens = childrens, .expand = config.expand == .Fill, @@ -265,17 +265,17 @@ pub const Container_Impl = struct { return container; } - pub fn onResize(self: *Container_Impl, size: Size) !void { + pub fn onResize(self: *Container, size: Size) !void { _ = size; self.relayout(); } - pub fn getChildAt(self: *Container_Impl, index: usize) !*Widget { + pub fn getChildAt(self: *Container, index: usize) !*Widget { if (index >= self.childrens.items.len) return error.OutOfBounds; return &self.childrens.items[index]; } - pub fn getChild(self: *Container_Impl, name: []const u8) ?*Widget { + pub fn getChild(self: *Container, name: []const u8) ?*Widget { // TODO: use hash map (maybe acting as cache?) for performance for (self.childrens.items) |*widget| { if (widget.name.*.get()) |widgetName| { @@ -284,14 +284,14 @@ pub const Container_Impl = struct { } } - if (widget.cast(Container_Impl)) |container| { + if (widget.cast(Container)) |container| { //return container.getChild(name) orelse continue; // workaround a stage2 bug // TODO: reduce to a unit test and report to ziglang/zig const function = getChild; return function(container, name) orelse continue; - } else if (widget.cast(@import("components/Align.zig").Align_Impl)) |component| { + } else if (widget.cast(@import("components/Alignment.zig").Alignment)) |component| { return component.getChild(name) orelse continue; } } @@ -299,7 +299,7 @@ pub const Container_Impl = struct { } /// Combines getChild() and Widget.as() - pub fn getChildAs(self: *Container_Impl, comptime T: type, name: []const u8) ?*T { + pub fn getChildAs(self: *Container, comptime T: type, name: []const u8) ?*T { if (self.getChild(name)) |widget| { return widget.as(T); } else { @@ -307,7 +307,7 @@ pub const Container_Impl = struct { } } - pub fn getPreferredSize(self: *Container_Impl, available: Size) Size { + pub fn getPreferredSize(self: *Container, available: Size) Size { var size: Size = Size{ .width = 0, .height = 0 }; const callbacks = Callbacks{ .userdata = @intFromPtr(&size), @@ -322,7 +322,7 @@ pub const Container_Impl = struct { return size; } - pub fn show(self: *Container_Impl) !void { + pub fn show(self: *Container) !void { if (self.peer == null) { var peer = try backend.Container.create(); for (self.childrens.items) |*widget| { @@ -342,7 +342,7 @@ pub const Container_Impl = struct { } } - pub fn _showWidget(widget: *Widget, self: *Container_Impl) !void { + pub fn _showWidget(widget: *Widget, self: *Container) !void { self.widget = widget; for (self.childrens.items) |*child| { child.parent = widget; @@ -383,7 +383,7 @@ pub const Container_Impl = struct { @as(*backend.Container, @ptrFromInt(data)).setTabOrder(widgets); } - pub fn relayout(self: *Container_Impl) void { + pub fn relayout(self: *Container) void { if (self.relayouting.load(.SeqCst) == true) return; if (self.peer) |peer| { self.relayouting.store(true, .SeqCst); @@ -411,7 +411,7 @@ pub const Container_Impl = struct { } } - pub fn add(self: *Container_Impl, widget: anytype) !void { + pub fn add(self: *Container, widget: anytype) !void { const ComponentType = @import("internal.zig").DereferencedType(@TypeOf(widget)); var genericWidget = try @import("internal.zig").genericWidgetFrom(widget); @@ -437,7 +437,7 @@ pub const Container_Impl = struct { self.relayout(); } - pub fn removeByIndex(self: *Container_Impl, index: usize) void { + pub fn removeByIndex(self: *Container, index: usize) void { // TODO: deinit widget here? const widget = self.childrens.items[index]; // Remove from the component @@ -452,13 +452,13 @@ pub const Container_Impl = struct { self.relayout(); } - pub fn removeAll(self: *Container_Impl) void { + pub fn removeAll(self: *Container) void { while (self.childrens.items.len > 0) { self.removeByIndex(0); } } - pub fn _deinit(self: *Container_Impl) void { + pub fn _deinit(self: *Container) void { for (self.childrens.items) |*child| { child.deinit(); } @@ -490,7 +490,7 @@ pub const GridConfig = struct { }; /// Set the style of the child to expanded by creating and showing the widget early. -pub inline fn Expanded(child: anytype) anyerror!Widget { +pub inline fn expanded(child: anytype) anyerror!Widget { var widget = try @import("internal.zig").genericWidgetFrom(if (comptime isErrorUnion(@TypeOf(child))) try child else @@ -499,18 +499,18 @@ pub inline fn Expanded(child: anytype) anyerror!Widget { return widget; } -pub inline fn Stack(childrens: anytype) anyerror!Container_Impl { - return try Container_Impl.init(try convertTupleToWidgets(childrens), .{}, StackLayout, {}); +pub inline fn stack(childrens: anytype) anyerror!Container { + return try Container.init(try convertTupleToWidgets(childrens), .{}, StackLayout, {}); } -pub inline fn Row(config: GridConfig, childrens: anytype) anyerror!Container_Impl { - return try Container_Impl.init(try convertTupleToWidgets(childrens), config, RowLayout, ColumnRowConfig{ .spacing = config.spacing, .wrapping = config.wrapping }); +pub inline fn row(config: GridConfig, childrens: anytype) anyerror!Container { + return try Container.init(try convertTupleToWidgets(childrens), config, RowLayout, ColumnRowConfig{ .spacing = config.spacing, .wrapping = config.wrapping }); } -pub inline fn Column(config: GridConfig, childrens: anytype) anyerror!Container_Impl { - return try Container_Impl.init(try convertTupleToWidgets(childrens), config, ColumnLayout, ColumnRowConfig{ .spacing = config.spacing, .wrapping = config.wrapping }); +pub inline fn column(config: GridConfig, childrens: anytype) anyerror!Container { + return try Container.init(try convertTupleToWidgets(childrens), config, ColumnLayout, ColumnRowConfig{ .spacing = config.spacing, .wrapping = config.wrapping }); } -pub inline fn Margin(margin: Rectangle, child: anytype) anyerror!Container_Impl { - return try Container_Impl.init(try convertTupleToWidgets(.{child}), .{}, MarginLayout, margin); +pub inline fn margin(margin_rect: Rectangle, child: anytype) anyerror!Container { + return try Container.init(try convertTupleToWidgets(.{child}), .{}, MarginLayout, margin_rect); } diff --git a/src/list.zig b/src/list.zig index 5e8592a..f74b070 100644 --- a/src/list.zig +++ b/src/list.zig @@ -14,22 +14,22 @@ pub const GenericListModel = struct { userdata: *anyopaque, }; -pub const List_Impl = struct { - pub usingnamespace @import("internal.zig").All(List_Impl); +pub const List = struct { + pub usingnamespace @import("internal.zig").All(List); peer: ?backend.ScrollView = null, - widget_data: List_Impl.WidgetData = .{}, + widget_data: List.WidgetData = .{}, child: Widget, model: GenericListModel, /// The child 'widget' must be the widget of a container. - pub fn init(widget: Widget, model: GenericListModel) List_Impl { - return List_Impl.init_events(List_Impl{ .child = widget, .model = model }); + pub fn init(widget: Widget, model: GenericListModel) List { + return List.init_events(List{ .child = widget, .model = model }); } fn modelSizeChanged(newSize: usize, userdata: usize) void { - const self = @as(*List_Impl, @ptrFromInt(userdata)); - const container = self.child.as(containers.Container_Impl); + const self = @as(*List, @ptrFromInt(userdata)); + const container = self.child.as(containers.Container); // TODO: cache widgets! container.removeAll(); @@ -42,7 +42,7 @@ pub const List_Impl = struct { } } - pub fn show(self: *List_Impl) !void { + pub fn show(self: *List) !void { if (self.peer == null) { var peer = try backend.ScrollView.create(); try self.child.show(); @@ -54,16 +54,16 @@ pub const List_Impl = struct { } } - pub fn getPreferredSize(self: *List_Impl, available: Size) Size { + pub fn getPreferredSize(self: *List, available: Size) Size { return self.child.getPreferredSize(available); } }; -pub inline fn ColumnList(config: containers.GridConfig, model: anytype) anyerror!List_Impl { +pub inline fn columnList(config: containers.GridConfig, model: anytype) anyerror!List { if (comptime !std.meta.trait.isPtrTo(.Struct)(@TypeOf(model))) { @compileError("Expected a mutable pointer to the list model"); } - var row = try containers.Column(config, .{}); + var row = try containers.column(config, .{}); const ModelType = @import("internal.zig").DereferencedType(@TypeOf(model)); // The type of the list model var genericModel = GenericListModel{ .size = &model.size, @@ -86,7 +86,7 @@ pub inline fn ColumnList(config: containers.GridConfig, model: anytype) anyerror } const widget = try @import("internal.zig").genericWidgetFrom(row); - var list = List_Impl.init(widget, genericModel); + var list = List.init(widget, genericModel); return list; } diff --git a/src/main.zig b/src/main.zig index 200b5da..6e4740a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,7 +2,7 @@ const std = @import("std"); pub const Window = @import("window.zig").Window; pub const Widget = @import("widget.zig").Widget; -pub usingnamespace @import("components/Align.zig"); +pub usingnamespace @import("components/Alignment.zig"); pub usingnamespace @import("components/Button.zig"); pub usingnamespace @import("components/Canvas.zig"); pub usingnamespace @import("components/CheckBox.zig"); diff --git a/src/window.zig b/src/window.zig index fbc260f..6b15b09 100644 --- a/src/window.zig +++ b/src/window.zig @@ -3,7 +3,7 @@ const backend = @import("backend.zig"); const internal = @import("internal.zig"); const Widget = @import("widget.zig").Widget; const ImageData = @import("image.zig").ImageData; -const MenuBar_Impl = @import("components/Menu.zig").MenuBar_Impl; +const MenuBar = @import("components/Menu.zig").MenuBar; const Size = @import("data.zig").Size; const Atom = @import("data.zig").Atom; @@ -134,7 +134,7 @@ pub const Window = struct { self.peer.setIconName(name); } - pub fn setMenuBar(self: *Window, bar: MenuBar_Impl) void { + pub fn setMenuBar(self: *Window, bar: MenuBar) void { self.peer.setMenuBar(bar); }