Skip to content

Commit 4f124dd

Browse files
Merge pull request #100 from orca-app/ui-styling-revision
UI styling revision
2 parents d11f985 + 8d93179 commit 4f124dd

File tree

19 files changed

+7587
-7631
lines changed

19 files changed

+7587
-7631
lines changed

doc/mkdocs/mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ nav:
3737
- Canvas API: 'api/Graphics/Canvas API.md'
3838
- GLES Surface: 'api/Graphics/GLES Surface.md'
3939
- UI: 'api/UI.md'
40+
- UI Core: 'api/UI Core.md'
41+
- UI Widgets: 'api/UI Widgets.md'
4042

4143
- Developer Guide:
4244
- Building: 'building.md'

samples/ui/src/main.c

Lines changed: 376 additions & 419 deletions
Large diffs are not rendered by default.

scripts/api_dump.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ def generate_type_entry(entries, ast, tu):
356356
}
357357

358358
if ast.kind == cindex.CursorKind.TYPEDEF_DECL:
359+
359360
underlying = ast.underlying_typedef_type
360361

361362
if underlying.kind == cindex.TypeKind.RECORD or underlying.kind == cindex.TypeKind.ENUM:
128 KB
Binary file not shown.
128 KB
Binary file not shown.

sketches/ui-bench/build.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
BINDIR=bin
4+
LIBDIR=../../build/bin
5+
RESDIR=../resources
6+
SRCDIR=../../src
7+
8+
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
9+
LIBS="-L$LIBDIR -lorca"
10+
FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG"
11+
12+
mkdir -p $BINDIR
13+
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_ui main.c
14+
15+
cp $LIBDIR/liborca.dylib $BINDIR/
16+
cp $LIBDIR/libwebgpu.dylib $BINDIR/
17+
18+
install_name_tool -add_rpath "@executable_path" $BINDIR/example_ui

sketches/ui-bench/main.c

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
/*************************************************************************
2+
*
3+
* Orca
4+
* Copyright 2023 Martin Fouilleul and the Orca project contributors
5+
* See LICENSE.txt for licensing information
6+
*
7+
**************************************************************************/
8+
#include <errno.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
13+
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
14+
#include <math.h>
15+
16+
#include "orca.h"
17+
18+
oc_vec2 frameSize = { 1200, 838 };
19+
20+
oc_surface surface;
21+
oc_canvas_renderer renderer;
22+
oc_canvas_context context;
23+
oc_font fontRegular;
24+
oc_font fontBold;
25+
26+
i32 ui_runloop(void* user)
27+
{
28+
context = oc_canvas_context_create();
29+
30+
oc_ui_context* ui = oc_ui_context_create(fontRegular);
31+
32+
oc_ui_radio_group_info radioInfo = {
33+
.optionCount = 4,
34+
.options = (oc_str8[]){
35+
OC_STR8("Option One"),
36+
OC_STR8("Option Two"),
37+
OC_STR8("Option Three"),
38+
OC_STR8("Option Four"),
39+
},
40+
};
41+
42+
oc_ui_select_popup_info popupInfo = {
43+
.selectedIndex = -1,
44+
.optionCount = 3,
45+
.options = (oc_str8[]){
46+
OC_STR8("Option One"),
47+
OC_STR8("Option Two"),
48+
OC_STR8("Options Three"),
49+
},
50+
.placeholder = OC_STR8("None"),
51+
};
52+
53+
oc_arena textArena = { 0 };
54+
oc_arena_init(&textArena);
55+
56+
oc_ui_text_box_info textBoxInfo = {
57+
.defaultText = OC_STR8_LIT("type here"),
58+
};
59+
60+
oc_arena textArena2 = { 0 };
61+
oc_arena_init(&textArena2);
62+
63+
oc_ui_text_box_info textBoxInfo2 = {
64+
.defaultText = OC_STR8_LIT("type here"),
65+
};
66+
67+
while(!oc_should_quit())
68+
{
69+
oc_arena_scope scratch = oc_scratch_begin();
70+
71+
oc_event* event = 0;
72+
while((event = oc_next_event(scratch.arena)) != 0)
73+
{
74+
oc_ui_process_event(event);
75+
76+
switch(event->type)
77+
{
78+
case OC_EVENT_WINDOW_CLOSE:
79+
{
80+
oc_request_quit();
81+
}
82+
break;
83+
84+
case OC_EVENT_WINDOW_RESIZE:
85+
{
86+
frameSize = (oc_vec2){ event->move.content.w, event->move.content.h };
87+
}
88+
break;
89+
90+
default:
91+
break;
92+
}
93+
}
94+
95+
oc_ui_frame(frameSize)
96+
{
97+
oc_ui_menu_bar("menu")
98+
{
99+
oc_ui_menu("file-menu", "File")
100+
{
101+
oc_ui_menu_button("quit", "Quit");
102+
}
103+
oc_ui_menu("theme-menu", "Theme")
104+
{
105+
if(oc_ui_menu_button("dark", "Dark").pressed)
106+
{
107+
oc_log_info("selected dark theme\n");
108+
}
109+
if(oc_ui_menu_button("ligth", "Light").pressed)
110+
{
111+
oc_log_info("selected light theme\n");
112+
}
113+
}
114+
}
115+
116+
oc_ui_style_rule("inner lb")
117+
{
118+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 0, 1, 0, 1 });
119+
}
120+
121+
oc_ui_style_rule("inner .label")
122+
{
123+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 1, 0, 0, 1 });
124+
}
125+
126+
oc_ui_box("outer-box")
127+
{
128+
oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_PIXELS, 200 });
129+
oc_ui_style_set_size(OC_UI_HEIGHT, (oc_ui_size){ OC_UI_SIZE_PIXELS, 200 });
130+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 1, 0, 0, 1 });
131+
132+
// oc_ui_style_set_i32(OC_UI_ALIGN_Y, OC_UI_ALIGN_CENTER);
133+
134+
oc_ui_box("inner-box")
135+
{
136+
oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_PIXELS, 100 });
137+
oc_ui_style_set_size(OC_UI_HEIGHT, (oc_ui_size){ OC_UI_SIZE_PIXELS, 100 });
138+
139+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 0, 1, 0, 1 });
140+
oc_ui_style_set_color(OC_UI_BORDER_COLOR, (oc_color){ 0, 0, 1, 0.5 });
141+
oc_ui_style_set_f32(OC_UI_BORDER_SIZE, 50);
142+
}
143+
}
144+
oc_ui_box("container")
145+
{
146+
oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_CHILDREN });
147+
oc_ui_style_set_size(OC_UI_HEIGHT, (oc_ui_size){ OC_UI_SIZE_CHILDREN });
148+
oc_ui_style_set_var(OC_UI_BG_COLOR, "bg-1");
149+
150+
oc_ui_style_set_i32(OC_UI_AXIS, OC_UI_AXIS_Y);
151+
oc_ui_style_set_f32(OC_UI_MARGIN_X, 10);
152+
oc_ui_style_set_f32(OC_UI_MARGIN_Y, 10);
153+
oc_ui_style_set_f32(OC_UI_SPACING, 10);
154+
155+
oc_ui_style_rule(".label.hover")
156+
{
157+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 1, 0, 1, 1 });
158+
}
159+
160+
oc_ui_label("la", "Label A");
161+
oc_ui_label("lb", "Label B");
162+
oc_ui_label("lc", "Label C");
163+
164+
oc_ui_button("ba", "Button A");
165+
oc_ui_button("bb", "Button B");
166+
oc_ui_button("bc", "Button C");
167+
168+
oc_ui_box("inner")
169+
{
170+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 0, 0, 1, 1 });
171+
172+
oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_CHILDREN });
173+
oc_ui_style_set_size(OC_UI_HEIGHT, (oc_ui_size){ OC_UI_SIZE_CHILDREN });
174+
oc_ui_style_set_f32(OC_UI_MARGIN_X, 10);
175+
oc_ui_style_set_f32(OC_UI_MARGIN_Y, 10);
176+
oc_ui_style_set_f32(OC_UI_SPACING, 10);
177+
178+
oc_ui_label("la", "label A");
179+
oc_ui_label("lb", "label B");
180+
}
181+
popupInfo = oc_ui_select_popup("popup", &popupInfo);
182+
183+
{
184+
oc_ui_text_box_result result = oc_ui_text_box("textbox", scratch.arena, &textBoxInfo);
185+
if(result.changed)
186+
{
187+
oc_arena_clear(&textArena);
188+
textBoxInfo.text = oc_str8_push_copy(&textArena, result.text);
189+
}
190+
}
191+
192+
{
193+
oc_ui_text_box_result result = oc_ui_text_box("textbox2", scratch.arena, &textBoxInfo2);
194+
if(result.changed)
195+
{
196+
oc_arena_clear(&textArena2);
197+
textBoxInfo2.text = oc_str8_push_copy(&textArena2, result.text);
198+
}
199+
}
200+
}
201+
202+
oc_ui_box("panel")
203+
{
204+
oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_PIXELS, 300 });
205+
oc_ui_style_set_size(OC_UI_HEIGHT, (oc_ui_size){ OC_UI_SIZE_PIXELS, 200 });
206+
oc_ui_style_set_var_str8(OC_UI_BG_COLOR, OC_UI_THEME_BG_1);
207+
208+
oc_ui_style_set_i32(OC_UI_OVERFLOW_X, OC_UI_OVERFLOW_CLIP);
209+
oc_ui_style_set_i32(OC_UI_OVERFLOW_Y, OC_UI_OVERFLOW_ALLOW);
210+
211+
/*
212+
oc_ui_style_set_i32(OC_UI_AXIS, OC_UI_AXIS_Y);
213+
oc_ui_style_set_f32(OC_UI_SPACING, 10);
214+
*/
215+
oc_ui_style_set_f32(OC_UI_MARGIN_X, 20);
216+
oc_ui_style_set_f32(OC_UI_MARGIN_Y, 20);
217+
218+
oc_ui_box* box = oc_ui_box("box")
219+
{
220+
// oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_PARENT, 1 });
221+
oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_PIXELS, 250 });
222+
oc_ui_style_set_size(OC_UI_HEIGHT, (oc_ui_size){ OC_UI_SIZE_PIXELS, 400 });
223+
224+
oc_ui_style_set_f32(OC_UI_MARGIN_X, 10);
225+
oc_ui_style_set_f32(OC_UI_MARGIN_Y, 10);
226+
oc_ui_style_set_f32(OC_UI_SPACING, 5);
227+
228+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 0, 0, 0, 1 });
229+
230+
static bool check = true;
231+
oc_ui_checkbox("check", &check);
232+
233+
static f32 slider = 0;
234+
oc_ui_slider("slider", &slider);
235+
236+
radioInfo = oc_ui_radio_group("radio", &radioInfo);
237+
238+
if(oc_ui_box_get_sig(box).hover)
239+
{
240+
oc_ui_tooltip("tooltip", "This is a black box");
241+
}
242+
}
243+
oc_ui_button("mybutton", "clickMe");
244+
}
245+
246+
/*
247+
oc_ui_box("note")
248+
{
249+
oc_ui_set_overlay(true);
250+
251+
oc_ui_style_set_size(OC_UI_WIDTH, (oc_ui_size){ OC_UI_SIZE_PIXELS, 100 });
252+
oc_ui_style_set_size(OC_UI_HEIGHT, (oc_ui_size){ OC_UI_SIZE_PIXELS, 50 });
253+
oc_ui_style_set_color(OC_UI_BG_COLOR, (oc_color){ 1, 0, 0, 1 });
254+
}
255+
*/
256+
}
257+
258+
oc_ui_draw();
259+
oc_canvas_render(renderer, context, surface);
260+
oc_canvas_present(renderer, surface);
261+
262+
oc_scratch_end(scratch);
263+
}
264+
return (0);
265+
}
266+
267+
int main()
268+
{
269+
oc_init();
270+
oc_clock_init(); //TODO put that in oc_init()?
271+
272+
oc_rect windowRect = { .x = 100, .y = 100, .w = frameSize.x, .h = frameSize.y };
273+
oc_window window = oc_window_create(windowRect, OC_STR8("test"), 0);
274+
275+
oc_rect contentRect = oc_window_get_content_rect(window);
276+
277+
oc_window_set_title(window, OC_STR8("UI Test"));
278+
279+
renderer = oc_canvas_renderer_create();
280+
surface = oc_canvas_surface_create_for_window(renderer, window);
281+
282+
oc_arena_scope scratch = oc_scratch_begin();
283+
284+
oc_font* fonts[2] = { &fontRegular, &fontBold };
285+
oc_str8 fontNames[2] = {
286+
oc_path_executable_relative(scratch.arena, OC_STR8("../OpenSans-Regular.ttf")),
287+
oc_path_executable_relative(scratch.arena, OC_STR8("../OpenSans-Bold.ttf"))
288+
};
289+
290+
for(int i = 0; i < 2; i++)
291+
{
292+
oc_file file = oc_file_open(fontNames[i], OC_FILE_ACCESS_READ, 0);
293+
if(oc_file_last_error(file) != OC_IO_OK)
294+
{
295+
oc_log_error("Couldn't open file %.*s\n", oc_str8_ip(fontNames[i]));
296+
}
297+
u64 size = oc_file_size(file);
298+
char* buffer = (char*)oc_arena_push(scratch.arena, size);
299+
oc_file_read(file, size, buffer);
300+
oc_file_close(file);
301+
oc_unicode_range ranges[5] = { OC_UNICODE_BASIC_LATIN,
302+
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
303+
OC_UNICODE_LATIN_EXTENDED_A,
304+
OC_UNICODE_LATIN_EXTENDED_B,
305+
OC_UNICODE_SPECIALS };
306+
307+
*fonts[i] = oc_font_create_from_memory(oc_str8_from_buffer(size, buffer), 5, ranges);
308+
}
309+
oc_scratch_end(scratch);
310+
311+
// start app
312+
oc_window_bring_to_front(window);
313+
oc_window_focus(window);
314+
315+
oc_thread* runloopThread = oc_thread_create(ui_runloop, 0);
316+
317+
while(!oc_should_quit())
318+
{
319+
oc_pump_events(-1);
320+
//TODO: what to do with mem scratch here?
321+
}
322+
323+
i64 exitCode = 0;
324+
oc_thread_join(runloopThread, &exitCode);
325+
326+
oc_surface_destroy(surface);
327+
oc_terminate();
328+
329+
return (0);
330+
}

0 commit comments

Comments
 (0)