Skip to content

Commit 7247c41

Browse files
committed
Add UI layout example code
1 parent ad0cb52 commit 7247c41

3 files changed

Lines changed: 239 additions & 7 deletions

File tree

examples/image.psh

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,48 @@ class Image
9898
}
9999
}
100100

101-
// TODO:
102-
//fill_circle() {}
101+
// Draw a filled rectangle
102+
fill_rect(self, x, y, w, h, color)
103+
{
104+
let var rx = x;
105+
let var ry = y;
106+
let var rw = w;
107+
let var rh = h;
108+
109+
// Clipping
110+
if (rx < 0) { rw = rw + rx; rx = 0; }
111+
if (ry < 0) { rh = rh + ry; ry = 0; }
112+
if (rx + rw > self.width) { rw = self.width - rx; }
113+
if (ry + rh > self.height) { rh = self.height - ry; }
114+
115+
if (rw <= 0 || rh <= 0) { return; }
116+
117+
for (let var j = 0; j < rh; ++j) {
118+
let idx = (ry + j) * self.width + rx;
119+
self.bytes.fill_u32(idx, rw, color);
120+
}
121+
}
122+
123+
// Draw a filled circle
124+
fill_circle(self, x0, y0, r, color)
125+
{
126+
let var x = 0;
127+
let var y = r;
128+
let var d = 3 - 2 * r;
129+
130+
while (y >= x) {
131+
self.fill_rect(x0 - y, y0 + x, 2 * y + 1, 1, color);
132+
self.fill_rect(x0 - y, y0 - x, 2 * y + 1, 1, color);
133+
self.fill_rect(x0 - x, y0 + y, 2 * x + 1, 1, color);
134+
self.fill_rect(x0 - x, y0 - y, 2 * x + 1, 1, color);
135+
136+
x = x + 1;
137+
if (d > 0) {
138+
y = y - 1;
139+
d = d + 4 * (x - y) + 10;
140+
} else {
141+
d = d + 4 * x + 6;
142+
}
143+
}
144+
}
103145
}

examples/layout.psh

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
from ./image import *;
2+
3+
class UINode
4+
{
5+
init(self)
6+
{
7+
// Position and size to be calculated
8+
self.x = nil;
9+
self.y = nil;
10+
self.width = nil;
11+
self.height = nil;
12+
13+
// Margin in pixels
14+
self.margin = 0;
15+
16+
// Background color
17+
self.bgcolor = nil;
18+
19+
// TODO: border color?
20+
21+
self.children = [];
22+
}
23+
24+
add_child(self, node)
25+
{
26+
self.children.push(node);
27+
}
28+
29+
compute_size(self)
30+
{
31+
for (let var i = 0; i < self.children.len; ++i)
32+
{
33+
self.children[i].compute_size();
34+
}
35+
}
36+
37+
compute_pos(self)
38+
{
39+
}
40+
41+
redraw(self, fb)
42+
{
43+
assert(self.x != nil && self.y != nil);
44+
45+
if (self.bgcolor != nil) {
46+
assert(self.bgcolor instanceof Int64);
47+
fb.fill_rect(self.x, self.y, self.width, self.height, self.bgcolor);
48+
}
49+
50+
// Draw the children on top of this node
51+
for (let var i = 0; i < self.children.len; ++i)
52+
{
53+
self.children[i].redraw(fb);
54+
}
55+
}
56+
}
57+
58+
// Box with a fixed size
59+
class Box extends UINode
60+
{
61+
init(self, width, height)
62+
{
63+
UINode.init(self);
64+
self.width = width;
65+
self.height = height;
66+
}
67+
}
68+
69+
// Row of elements
70+
class Row extends UINode
71+
{
72+
init(self)
73+
{
74+
UINode.init(self);
75+
}
76+
77+
compute_size(self)
78+
{
79+
let var height = 0;
80+
let var width = 0;
81+
let var prev_margin = 0;
82+
83+
for (let var i = 0; i < self.children.len; ++i)
84+
{
85+
let child = self.children[i];
86+
child.compute_size();
87+
height = height.max(child.height + 2 * child.margin);
88+
89+
let margin = child.margin.max(prev_margin);
90+
width += margin + child.width;
91+
prev_margin = child.margin;
92+
}
93+
94+
width += prev_margin;
95+
self.width = width;
96+
self.height = height;
97+
}
98+
99+
compute_pos(self)
100+
{
101+
assert(self.x instanceof Int64);
102+
assert(self.y instanceof Int64);
103+
104+
let var prev_margin = 0;
105+
let var cur_x = self.x;
106+
107+
for (let var i = 0; i < self.children.len; ++i)
108+
{
109+
let child = self.children[i];
110+
111+
let margin = child.margin.max(prev_margin);
112+
cur_x += margin;
113+
114+
child.x = cur_x;
115+
child.y = self.y + (self.height - child.height) _/ 2;
116+
child.compute_pos();
117+
118+
cur_x += child.width;
119+
prev_margin = child.margin;
120+
}
121+
}
122+
}
123+
124+
// Node that centers a single child node
125+
class Center extends UINode
126+
{
127+
init(self, child)
128+
{
129+
UINode.init(self);
130+
self.children.push(child);
131+
}
132+
133+
compute_pos(self)
134+
{
135+
assert(self.x instanceof Int64);
136+
assert(self.y instanceof Int64);
137+
assert(self.children.len == 1);
138+
139+
let child = self.children[0];
140+
child.x = self.x + (self.width - child.width) _/ 2;
141+
child.y = self.y + (self.height - child.height) _/ 2;
142+
child.compute_pos();
143+
144+
$println(child.x);
145+
$println(child.y);
146+
}
147+
}
148+
149+
150+
151+
152+
let fb = Image(600, 400);
153+
let window = $window_create(fb.width, fb.height, "Layout Engine Test", 0);
154+
155+
let row = Row();
156+
row.bgcolor = rgb(50, 50, 50);
157+
158+
let center = Center(row);
159+
center.width = fb.width;
160+
center.height = fb.height;
161+
center.x = 0;
162+
center.y = 0;
163+
center.bgcolor = COLOR_BLACK;
164+
165+
for (let var i = 0; i < 16; ++i)
166+
{
167+
let box = Box(24, 24);
168+
box.bgcolor = COLOR_GREY;
169+
box.margin = 6;
170+
row.add_child(box);
171+
}
172+
173+
center.compute_size();
174+
center.compute_pos();
175+
center.redraw(fb);
176+
$window_draw_frame(window, fb.bytes);
177+
178+
179+
180+
181+
182+
loop
183+
{
184+
let msg = $actor_recv();
185+
if (msg instanceof UIEvent) {
186+
if (msg.kind == 'CLOSE_WINDOW' || (msg.kind == 'KEY_DOWN' && msg.key == 'ESCAPE')) {
187+
break;
188+
}
189+
}
190+
191+
192+
193+
}

src/window.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,15 @@ unsafe fn make_static<T>(t: &T) -> &'static T {
143143
pub fn window_draw_frame(
144144
actor: &mut Actor,
145145
window_id: Value,
146-
frame: Value,
146+
mut frame: Value,
147147
) -> Result<Value, String>
148148
{
149149
if actor.actor_id != 0 {
150150
panic!("window functions should only be called from the main actor");
151151
}
152152

153153
let window_id = unwrap_u32!(window_id);
154-
let frame = match frame {
155-
Value::ByteArray(p) => unsafe { &*p }
156-
_ => panic!()
157-
};
154+
let frame = frame.unwrap_ba();
158155

159156
assert!(window_id == 0);
160157
let mut window_lock = WINDOW.lock().unwrap();

0 commit comments

Comments
 (0)