99 lines
2.4 KiB
Plaintext
99 lines
2.4 KiB
Plaintext
main :: {
|
|
// imagine a game loop
|
|
while(running) {
|
|
render_ui(build_menu);
|
|
}
|
|
}
|
|
|
|
build_menu :: (ctx: ViewContext) -> View {
|
|
// use ctx to allocate some state at the for Menu ViewContext
|
|
state : MenuState = ctx.state(MenuState);
|
|
|
|
// named args
|
|
HStack(ctx,
|
|
children = .[
|
|
Button(ctx,
|
|
label = "Up",
|
|
onTap = ctx.callback(goUp, state),
|
|
),
|
|
ScrollView(ctx,
|
|
LazyVStack(ctx,
|
|
builder = ctx.callback(build_menu_entry, state),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}
|
|
|
|
build_menu_entry :: (ctx: *ViewContext, index: s32, state: *MenuState) -> View {
|
|
entry := state.entries[index];
|
|
is_selected := index == state.selected_index;
|
|
icon := if entry.is_dir then "[D]" else " ";
|
|
Button(ctx,
|
|
label = concat(icon, " ", entry.name),
|
|
on_tap = ctx.callback(menu_go, state, index),
|
|
);
|
|
}
|
|
|
|
ViewContext :: struct {
|
|
//TBD
|
|
}
|
|
|
|
MenuState :: struct {
|
|
current_path: string;
|
|
entries: List(MenuEntry);
|
|
error_message: string;
|
|
}
|
|
|
|
MenuEntry :: struct {
|
|
name: string;
|
|
is_dir: bool;
|
|
}
|
|
|
|
menu_go_up :: (state: *MenuState) {
|
|
parent := fs.path.dirname(state.current_path) else return;
|
|
// this frees the current path & copies parent to be owned by MenuState
|
|
state.current_path = parent;
|
|
menu_refresh(state);
|
|
}
|
|
|
|
menu_go :: (state: *MenuState, s32 index) {
|
|
entry := state.entries[index] else return;
|
|
state.current_path := concat(state.current_path, "/", entry.name);
|
|
menu_refresh(state);
|
|
}
|
|
|
|
menu_refresh :: (state: *MenuState) {
|
|
// this could retain the capacity
|
|
state.entries.clear();
|
|
// this would basically create a copy of the empty string :(
|
|
state.error_message = "";
|
|
|
|
// ... multi return params vs Generic Result to deal with exceptions
|
|
// ... nullable
|
|
dir := io.Dir.open(state.current_path);
|
|
if !dir {
|
|
state.error_message = "failed to open";
|
|
return;
|
|
};
|
|
defer dir.close();
|
|
|
|
for iter.iterate() {
|
|
entries.append(.{it.name, it.kind == .Directory});
|
|
}
|
|
}
|
|
|
|
HStackState :: struct {
|
|
spacing: f32 = 8;
|
|
alignment: VerticalAlignment = .center;
|
|
padding: f32 = 0;
|
|
background: ?Color;
|
|
corner_radius: f32 = 0,
|
|
}
|
|
|
|
HStack :: (ctx: ViewContext, children: []View) -> View {
|
|
data := ctx.alloc(HStackState);
|
|
data.* = .{};
|
|
}
|
|
|