Skip to content

Commit d76ba47

Browse files
committed
add 2024 recap
1 parent 146bf18 commit d76ba47

File tree

5 files changed

+201
-1
lines changed

5 files changed

+201
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
public/
22
resources/
3+
static/api-reference/
34

content/blog/capy-2024.md

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
---
2+
title: "Capy -- 2024 Recap"
3+
authors: ["zenith391"]
4+
date: 2025-01-01T10:35:14+01:00
5+
tags: ["capy", "recap"]
6+
---
7+
8+
**Reminder: Capy is NOT ready for use in production as I'm still making breaking changes**
9+
10+
[Capy](https://github.com/capy-ui/capy) is a **GUI framework** for Zig made with performance,
11+
cross-compilation and native widgets in mind. The goal is to be able to seamlessly cross-compile
12+
from any platform to any other one. This includes Windows, Linux, WebAssembly, and soon will include
13+
macOS, Android and iOS.
14+
15+
## [`AnimationController`](https://capy-ui.org/api-reference/#capy.AnimationController)
16+
17+
The animation system for [Atom](https://capy-ui.org/api-reference/#capy.data.Atom) has been remade.
18+
It now requires an [`AnimationController`](https://capy-ui.org/api-reference/#capy.AnimationController)
19+
which is used to periodically update the Atom.
20+
21+
Previously, this was implemented using global variables, but using global variables had two
22+
problems: it couldn't synchronise the animation with the window's refresh rate, and due to that,
23+
animations worked at the maximum speed the CPU could allow, which meant Capy maximized one CPU core
24+
for animations !
25+
26+
Now, animations don't hog CPU cores anymore while also looking more smooth. The tradeoff means
27+
that the new syntax for animating atoms is now:
28+
```zig
29+
atom.animate(
30+
animation_controller,
31+
capy.Easings.InOut, // easing
32+
capy.Colors.red, // target value
33+
1000 // duration in milliseconds
34+
);
35+
```
36+
37+
## API Reference (!)
38+
39+
Capy now has an [API reference](/api-reference) which is auto-generated by Zig itself. This piece
40+
of documentation has been long overdue, but I couldn't add the API reference as, at first, I
41+
encountered compiler errors, which have now been fixed thanks to the latest compiler updates. And
42+
then, the API reference simply wouldn't use the `capy` module as its main page, which meant that
43+
all the functions and structs couldn't be discovered on the API reference, which kind of defeated
44+
its purpose.
45+
46+
The fix to that ended up being renaming `src/main.zig` to `src/capy.zig`, as the new documentation
47+
generator in Zig silently expects this naming convention.
48+
49+
<!-- insert image -->
50+
51+
## Improvements to [`Label`](https://capy-ui.org/api-reference/#capy.components.Label.Label)
52+
53+
The component can now use different fonts in different sizes using the new [`TextLayout`](/api-reference/#capy.misc.TextLayout)
54+
struct. This allows for more complex typography for Capy applications.
55+
56+
<!-- insert image -->
57+
58+
## Userdata
59+
See the `many-counters.zig` example.
60+
This system allows for each component to hold their state or their data.
61+
In the following example, it's used to hold the count for each counter widget:
62+
```zig
63+
//! This is a test for Capy's ease of use when using lists of many items
64+
const capy = @import("capy");
65+
const std = @import("std");
66+
pub usingnamespace capy.cross_platform;
67+
68+
const CounterState = struct {
69+
count: capy.Atom(i64) = capy.Atom(i64).of(0),
70+
};
71+
72+
fn counter() anyerror!*capy.Alignment {
73+
var state1 = try capy.internal.lasting_allocator.create(CounterState);
74+
state1.* = .{};
75+
const format = try capy.FormattedAtom(capy.internal.lasting_allocator, "{d}", .{&state1.count});
76+
77+
return capy.alignment(
78+
.{},
79+
(try capy.row(.{}, .{
80+
capy.button(.{
81+
.label = "-",
82+
.onclick = (struct {
83+
fn sub(pointer: *anyopaque) !void {
84+
const button: *capy.Button = @ptrCast(@alignCast(pointer));
85+
const state: *CounterState = button.getUserdata(CounterState).?;
86+
state.count.set(state.count.get() - 1);
87+
}
88+
}).sub,
89+
}),
90+
capy.textField(.{ .text = "0", .readOnly = true })
91+
.bind("text", format),
92+
capy.button(.{ .label = "+", .onclick = struct {
93+
fn add(pointer: *anyopaque) anyerror!void {
94+
const button: *capy.Button = @ptrCast(@alignCast(pointer));
95+
const state: *CounterState = button.getUserdata(CounterState).?;
96+
state.count.set(state.count.get() + 1);
97+
}
98+
}.add }),
99+
}))
100+
.addUserdata(CounterState, state1),
101+
);
102+
}
103+
104+
pub fn main() !void {
105+
try capy.init();
106+
defer capy.deinit();
107+
108+
var window = try capy.Window.init();
109+
try window.set(capy.column(.{}, .{
110+
capy.column(.{ .name = "counters-column" }, .{
111+
counter(),
112+
}),
113+
}));
114+
115+
window.show();
116+
capy.runEventLoop();
117+
}
118+
```
119+
120+
## [`Monitor`](/api-reference/#capy.monitor.Monitor) and Fullscreen API
121+
122+
Capy now has an API for handling monitors. It currently handles monitor names, sizes, and most
123+
importantly, the list of video modes a monitor supports. This can be used to set windows fullscreen,
124+
be it in borderless maximized mode or in exclusive fullscreen mode (the one that allows you to
125+
change the monitor's resolution).
126+
127+
## Progress on the macOS backend
128+
129+
Thanks to effort by [geon](https://github.com/geon), the macOS backend has tremendously progressed
130+
in the past month. Up until the start of October, the macOS backend could only show an empty window.
131+
Now it can already run small examples (like the `border-layout` example).
132+
133+
## Grid Layout
134+
135+
Before now, Capy used to only support few layout algorithms: `Row`, `Column` and `Stack`. The
136+
problem is this set only allows for simple layouts, given that `Row` and `Column` are essentially
137+
akin to flex boxes (with a few features missing) and `Stack` is just Z-ordering.
138+
139+
Hence, a new layout was introduced: the grid layout. Its implementation in Capy is based on
140+
[CSS Grid Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout), which is a
141+
flexible and expressive API that has the advantage of being familiar to most developers.
142+
143+
Capy's implementation isn't an exact copy of this (as the way styling and layouting happens is
144+
different from CSS), but shares a lot of similarities with it. Nonetheless, a picture's worth a
145+
thousand words:
146+
147+
![Grid Layout demonstration](/img/grid-layout.png)
148+
149+
```zig
150+
const grid = try capy.grid(.{
151+
.template_columns = &([_]capy.GridLayoutConfig.LengthUnit{.{ .fraction = 1 }} ** 5),
152+
.template_rows = &.{ .{ .pixels = 150 }, .{ .pixels = 300 } },
153+
.column_spacing = 5,
154+
.row_spacing = 10,
155+
}, .{});
156+
// add buttons to grid
157+
// ...
158+
// display the grid on the window
159+
try window.set(
160+
// by default, capy.alignment centers the given component.
161+
capy.alignment(.{},
162+
grid
163+
)
164+
)
165+
```
166+
167+
As the features are similar to CSS Grid, I recommend [Josh W. Comeau's tutorial](https://www.joshwcomeau.com/css/interactive-guide-to-grid/)
168+
for an introduction to its capabilities. The only feature that's been intentionally ommited are
169+
grid template areas.
170+
171+
## Added [`Dropdown`](/api-reference/#capy.components.Dropdown.Dropdown) component
172+
173+
![dropdown example](/img/capy-dropdown.gif)
174+
175+
The above example was made with
176+
```zig
177+
const selectedValue = capy.Atom([]const u8).alloc("");
178+
defer selectedValue.deinit();
179+
180+
try window.set(capy.column(.{}, .{
181+
capy.dropdown(.{
182+
.values = &.{ "hello", "world", "test" },
183+
})
184+
.bind("selected_value", selectedValue),
185+
186+
capy.label(.{})
187+
.bind("text", selectedValue),
188+
}));
189+
window.show();
190+
```
191+
192+
## Progress on the WebAssembly backend
193+
194+
The WebAssembly backend has also been enhanced. Most efforts have been in bug fixing.
195+
196+
- Fixed [`Canvas`](https://capy-ui.org/api-reference/#capy.components.Canvas.Canvas) on high-DPI
197+
screens. This means the [osm-viewer](/zig-osm/) example now properly works on screens with high-DPI.
198+
- Add support for `TextField.read_only` and `Button.enabled`
199+
- Add support for `Window.on_frame`

static/img/capy-dropdown.gif

3.39 MB
Loading

static/img/grid-layout.png

13 KB
Loading

themes/capy/layouts/partials/header.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
<li><a href="/demos/">Demo</a></li>
55
<li><a href="/api-reference/">API</a></li>
66
<li><a href="/docs/">Documentation</a></li>
7-
<li><a href="/features/">Features</a></li>
87
<li><a href="/blog/">Blog</a></li>
8+
<li><a href="/features/">Features</a></li>
99
<li><a href="https://github.com/capy-ui/capy" target="_blank">GitHub</a></li>
1010
</ul>
1111
<ul style="justify-content: right;">

0 commit comments

Comments
 (0)