Material3 components
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
package main
|
||||
|
||||
import "shared:android"
|
||||
import "core:fmt"
|
||||
import "base:runtime"
|
||||
import engine "../zephr"
|
||||
import "jni"
|
||||
|
||||
counter := 0
|
||||
|
||||
device_model: string
|
||||
device_sdk: i32
|
||||
toast_ctx: Context
|
||||
@@ -20,26 +17,26 @@ Edge_Insets :: struct {
|
||||
insets: Edge_Insets
|
||||
insets_valid: bool
|
||||
|
||||
@export
|
||||
android_main :: proc "c" (state: ^android.android_app) {
|
||||
context = runtime.default_context()
|
||||
context.user_ptr = state
|
||||
main :: proc() {
|
||||
real_main()
|
||||
}
|
||||
|
||||
engine.init("", "", {1000, 600}, false, "")
|
||||
real_main :: proc() {
|
||||
engine.init("", "", {480, 1000}, false, "")
|
||||
defer engine.deinit()
|
||||
|
||||
// Static field reads only -- safe from the engine's thread. Anything
|
||||
// touching the UI toolkit (Toast, dialogs) needs the main looper instead.
|
||||
if jni.init(state) {
|
||||
device_model, _ = build_model()
|
||||
device_sdk, _ = build_sdk_int()
|
||||
toast_ctx = Context(jni.activity(state))
|
||||
main_activity = Activity(jni.activity(state))
|
||||
}
|
||||
|
||||
_, font_ok := engine.ui_text_register_font(#load("/usr/share/fonts/truetype/noto/NotoSans-Regular.ttf"))
|
||||
_, font_ok := engine.ui_text_register_font(#load("./assets/Roboto-VariableFont_wdth_wght.ttf"))
|
||||
ensure(font_ok)
|
||||
|
||||
// Material Symbols, subset to the glyphs the app bar uses: 1.3KB of a 356KB
|
||||
// font. Its codepoints are Private Use Area, so nothing else claims them and
|
||||
// the shaper's per-codepoint fallback routes them here on its own. ☰ and ⋮
|
||||
// were rendering as tofu because Roboto has no glyph for either.
|
||||
_, icon_font_ok := engine.ui_text_register_font(#load("./assets/material_icons.ttf"))
|
||||
ensure(icon_font_ok)
|
||||
|
||||
m3_init_dark()
|
||||
|
||||
for !engine.should_quit() {
|
||||
engine.frame_start()
|
||||
defer engine.frame_end()
|
||||
@@ -63,7 +60,7 @@ android_main :: proc "c" (state: ^android.android_app) {
|
||||
window_size := engine.get_window_size()
|
||||
|
||||
engine.ui_begin_build(window_size)
|
||||
engine.ui_text_set_default_pixel_size(108)
|
||||
engine.ui_text_set_default_pixel_size(16) // dp
|
||||
engine.ui_push_text_color(0xFFFFFF)
|
||||
draw_ui()
|
||||
engine.ui_pop_text_color()
|
||||
@@ -73,21 +70,25 @@ android_main :: proc "c" (state: ^android.android_app) {
|
||||
}
|
||||
}
|
||||
|
||||
draw_ui :: proc() {
|
||||
engine.ui_set_next_width(engine.ui_children_sum(1))
|
||||
engine.ui_column(); {
|
||||
engine.ui_padding(insets.left, {.Left})
|
||||
engine.ui_padding(insets.right, {.Right})
|
||||
engine.ui_padding(insets.top, {.Top})
|
||||
engine.ui_padding(insets.bottom, {.Bottom})
|
||||
engine.ui_text(fmt.tprintf("%d", counter))
|
||||
engine.ui_text(fmt.tprintf("%s / API %d", device_model, device_sdk))
|
||||
engine.ui_text(fmt.tprintf("ins %v %v %v %v ok=%v", insets.left, insets.top, insets.right, insets.bottom, insets_valid))
|
||||
if click, _ := engine.ui_button("Hello"); click {
|
||||
counter += 1
|
||||
show_toast(fmt.tprintf("Clicked %d times", counter))
|
||||
}
|
||||
@export
|
||||
android_main :: proc "c" (state: ^android.android_app) {
|
||||
context = runtime.default_context()
|
||||
context.user_ptr = state
|
||||
|
||||
// Static field reads only -- safe from the engine's thread. Anything
|
||||
// touching the UI toolkit (Toast, dialogs) needs the main looper instead.
|
||||
if jni.init(state) {
|
||||
device_model, _ = build_model()
|
||||
device_sdk, _ = build_sdk_int()
|
||||
toast_ctx = Context(jni.activity(state))
|
||||
main_activity = Activity(jni.activity(state))
|
||||
}
|
||||
|
||||
real_main()
|
||||
}
|
||||
|
||||
draw_ui :: proc() {
|
||||
m3_demo_screen()
|
||||
}
|
||||
|
||||
// Toast needs a Java looper on this thread. Preparing one is a one-time cost
|
||||
@@ -127,12 +128,12 @@ refresh_insets :: proc() -> bool {
|
||||
if cut, got_cut := insets_type_display_cutout(); got_cut {
|
||||
mask |= cut
|
||||
}
|
||||
if ins, got := window_insets_get_ignoring_visibility(wi, mask); got && ins != nil {
|
||||
if ins, got := window_insets_get(wi, mask); got && ins != nil {
|
||||
l := insets_left(ins) or_return
|
||||
t := insets_top(ins) or_return
|
||||
r := insets_right(ins) or_return
|
||||
b := insets_bottom(ins) or_return
|
||||
insets = {f32(l), f32(t), f32(r), f32(b)}
|
||||
insets = to_points({f32(l), f32(t), f32(r), f32(b)})
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -141,6 +142,15 @@ refresh_insets :: proc() -> bool {
|
||||
t := window_insets_sys_top(wi) or_return
|
||||
r := window_insets_sys_right(wi) or_return
|
||||
b := window_insets_sys_bottom(wi) or_return
|
||||
insets = {f32(l), f32(t), f32(r), f32(b)}
|
||||
insets = to_points({f32(l), f32(t), f32(r), f32(b)})
|
||||
return true
|
||||
}
|
||||
|
||||
// WindowInsets are reported in physical pixels, but layout is in dp.
|
||||
to_points :: proc(v: Edge_Insets) -> Edge_Insets {
|
||||
s := engine.get_backing_scale()
|
||||
if s <= 0 {
|
||||
s = 1
|
||||
}
|
||||
return {v.left / s, v.top / s, v.right / s, v.bottom / s}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user