Files
el/ui/examples/native-hello-ios/NativeHello/el_native_target.h

574 lines
23 KiB
C

/*
* el_native_target.h — Native widget declarations for el programs targeting
* native desktop UI (AppKit / GTK4 / Win32).
*
* This header is designed to be included AFTER el_runtime.h without conflict:
* - It does NOT redefine el_to_float, el_from_float, or any el_runtime.h
* static inlines.
* - It does NOT redeclare __println, __print, or other functions whose
* return types differ between el_seed.h and el_runtime.h.
* - It adds: native widget builtins + float arithmetic helpers that the
* current el_runtime.h omits but elc still emits calls to.
*
* Usage:
* Inject via -include at compile time, OR #include it after el_runtime.h.
*
* clang -DEL_TARGET_MACOS -include el_native_target.h -c my_app.c ...
*/
#pragma once
#include <stdint.h>
#include <stdlib.h>
/* el_val_t must already be defined by el_runtime.h or el_seed.h. */
#ifndef EL_VAL_T_DEFINED
typedef int64_t el_val_t;
#endif
/* ── Float arithmetic helpers ───────────────────────────────────────────────
* elc emits calls to float_div / float_mul etc. for Float-typed expressions.
* These were in el_runtime.c through v1.0.0-20260501 but are missing from the
* current el_runtime.h. Redeclared here as static inline to avoid link deps.
* Only defined if not already declared (old runtimes that still have them). */
#ifndef EL_FLOAT_OPS_DEFINED
#define EL_FLOAT_OPS_DEFINED
/* el_to_float / el_from_float — bit-cast between el_val_t and double.
* Defined as static inline in both el_runtime.h and el_seed.h; we do NOT
* redefine them here. We rely on one of those headers being included first. */
static inline el_val_t float_div(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub, ur;
ua.i = a; ub.i = b;
ur.d = (ub.d != 0.0) ? (ua.d / ub.d) : 0.0;
return ur.i;
}
static inline el_val_t float_mul(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub, ur;
ua.i = a; ub.i = b; ur.d = ua.d * ub.d;
return ur.i;
}
static inline el_val_t float_add(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub, ur;
ua.i = a; ub.i = b; ur.d = ua.d + ub.d;
return ur.i;
}
static inline el_val_t float_sub(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub, ur;
ua.i = a; ub.i = b; ur.d = ua.d - ub.d;
return ur.i;
}
static inline el_val_t float_lt(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub;
ua.i = a; ub.i = b;
return (el_val_t)(ua.d < ub.d);
}
static inline el_val_t float_gt(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub;
ua.i = a; ub.i = b;
return (el_val_t)(ua.d > ub.d);
}
static inline el_val_t float_lte(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub;
ua.i = a; ub.i = b;
return (el_val_t)(ua.d <= ub.d);
}
static inline el_val_t float_gte(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub;
ua.i = a; ub.i = b;
return (el_val_t)(ua.d >= ub.d);
}
static inline el_val_t float_eq(el_val_t a, el_val_t b) {
union { double d; int64_t i; } ua, ub;
ua.i = a; ub.i = b;
return (el_val_t)(ua.d == ub.d);
}
#endif /* EL_FLOAT_OPS_DEFINED */
/* ── Native widget system (macOS AppKit) ────────────────────────────────────
* Available when compiled with -DEL_TARGET_MACOS and linked with el_appkit.m.
* Widget handles are opaque int64_t slot indices; -1 = invalid. */
#ifdef EL_TARGET_MACOS
/* Initialisation */
void __native_init(void);
void __native_run_loop(void);
/* Window */
el_val_t __window_create(el_val_t title, el_val_t width, el_val_t height,
el_val_t min_width, el_val_t min_height);
void __window_show(el_val_t handle);
void __window_set_title(el_val_t handle, el_val_t title);
/* Layout containers */
el_val_t __vstack_create(el_val_t spacing);
el_val_t __hstack_create(el_val_t spacing);
el_val_t __zstack_create(void);
el_val_t __scroll_create(void);
/* Widgets */
el_val_t __label_create(el_val_t text);
el_val_t __button_create(el_val_t label);
el_val_t __text_field_create(el_val_t placeholder);
el_val_t __text_area_create(el_val_t placeholder);
el_val_t __image_create(el_val_t path_or_name);
/* Widget properties */
void __widget_set_text(el_val_t handle, el_val_t text);
el_val_t __widget_get_text(el_val_t handle);
void __widget_set_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_font(el_val_t handle, el_val_t family,
el_val_t size, el_val_t bold);
void __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
el_val_t bottom, el_val_t left);
void __widget_set_width(el_val_t handle, el_val_t width);
void __widget_set_height(el_val_t handle, el_val_t height);
void __widget_set_flex(el_val_t handle, el_val_t flex);
void __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void __widget_set_disabled(el_val_t handle, el_val_t disabled);
void __widget_set_hidden(el_val_t handle, el_val_t hidden);
/* Layout / tree */
void __widget_add_child(el_val_t parent, el_val_t child);
void __widget_remove_child(el_val_t parent, el_val_t child);
void __widget_destroy(el_val_t handle);
/* Events */
void __widget_on_click(el_val_t handle, el_val_t fn_name);
void __widget_on_change(el_val_t handle, el_val_t fn_name);
void __widget_on_submit(el_val_t handle, el_val_t fn_name);
/* Manifest reader */
el_val_t __manifest_read(el_val_t path);
#endif /* EL_TARGET_MACOS */
/* ── Native widget system (Linux GTK4) ──────────────────────────────────────
* Available when compiled with -DEL_TARGET_LINUX and linked with el_gtk4.c.
* Widget handles are opaque int64_t slot indices; -1 = invalid.
* All functions have the same signatures as EL_TARGET_MACOS above. */
#ifdef EL_TARGET_LINUX
/* Initialisation */
void __native_init(void);
void __native_run_loop(void);
/* Window */
el_val_t __window_create(el_val_t title, el_val_t width, el_val_t height,
el_val_t min_width, el_val_t min_height);
void __window_show(el_val_t handle);
void __window_set_title(el_val_t handle, el_val_t title);
/* Layout containers */
el_val_t __vstack_create(el_val_t spacing);
el_val_t __hstack_create(el_val_t spacing);
el_val_t __zstack_create(void);
el_val_t __scroll_create(void);
/* Widgets */
el_val_t __label_create(el_val_t text);
el_val_t __button_create(el_val_t label);
el_val_t __text_field_create(el_val_t placeholder);
el_val_t __text_area_create(el_val_t placeholder);
el_val_t __image_create(el_val_t path_or_name);
/* Widget properties */
void __widget_set_text(el_val_t handle, el_val_t text);
el_val_t __widget_get_text(el_val_t handle);
void __widget_set_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_font(el_val_t handle, el_val_t family,
el_val_t size, el_val_t bold);
void __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
el_val_t bottom, el_val_t left);
void __widget_set_width(el_val_t handle, el_val_t width);
void __widget_set_height(el_val_t handle, el_val_t height);
void __widget_set_flex(el_val_t handle, el_val_t flex);
void __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void __widget_set_disabled(el_val_t handle, el_val_t disabled);
void __widget_set_hidden(el_val_t handle, el_val_t hidden);
/* Layout / tree */
void __widget_add_child(el_val_t parent, el_val_t child);
void __widget_remove_child(el_val_t parent, el_val_t child);
void __widget_destroy(el_val_t handle);
/* Events */
void __widget_on_click(el_val_t handle, el_val_t fn_name);
void __widget_on_change(el_val_t handle, el_val_t fn_name);
void __widget_on_submit(el_val_t handle, el_val_t fn_name);
/* Manifest reader — same JSON output as EL_TARGET_MACOS */
el_val_t __manifest_read(el_val_t path);
#endif /* EL_TARGET_LINUX */
/* ── Native widget system (Windows Win32) ───────────────────────────────────
* Available when compiled with -DEL_TARGET_WIN32 and linked with el_win32.c.
* Widget handles are opaque int64_t slot indices; -1 = invalid.
* Link: el_win32.obj comctl32.lib user32.lib gdi32.lib */
#ifdef EL_TARGET_WIN32
/* Initialisation */
void __native_init(void);
void __native_run_loop(void);
/* Window */
el_val_t __window_create(el_val_t title, el_val_t width, el_val_t height,
el_val_t min_width, el_val_t min_height);
void __window_show(el_val_t handle);
void __window_set_title(el_val_t handle, el_val_t title);
/* Layout containers */
el_val_t __vstack_create(el_val_t spacing);
el_val_t __hstack_create(el_val_t spacing);
el_val_t __zstack_create(void);
el_val_t __scroll_create(void);
/* Widgets */
el_val_t __label_create(el_val_t text);
el_val_t __button_create(el_val_t label);
el_val_t __text_field_create(el_val_t placeholder);
el_val_t __text_area_create(el_val_t placeholder);
el_val_t __image_create(el_val_t path_or_name);
/* Widget properties */
void __widget_set_text(el_val_t handle, el_val_t text);
el_val_t __widget_get_text(el_val_t handle);
void __widget_set_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_font(el_val_t handle, el_val_t family,
el_val_t size, el_val_t bold);
void __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
el_val_t bottom, el_val_t left);
void __widget_set_width(el_val_t handle, el_val_t width);
void __widget_set_height(el_val_t handle, el_val_t height);
void __widget_set_flex(el_val_t handle, el_val_t flex);
void __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void __widget_set_disabled(el_val_t handle, el_val_t disabled);
void __widget_set_hidden(el_val_t handle, el_val_t hidden);
/* Layout / tree */
void __widget_add_child(el_val_t parent, el_val_t child);
void __widget_remove_child(el_val_t parent, el_val_t child);
void __widget_destroy(el_val_t handle);
/* Events */
void __widget_on_click(el_val_t handle, el_val_t fn_name);
void __widget_on_change(el_val_t handle, el_val_t fn_name);
void __widget_on_submit(el_val_t handle, el_val_t fn_name);
/* Manifest reader */
el_val_t __manifest_read(el_val_t path);
#endif /* EL_TARGET_WIN32 */
/* ── Native widget system (iOS UIKit) ───────────────────────────────────────
* Available when compiled with -DEL_TARGET_IOS and linked with el_uikit.m.
* Widget handles are opaque int64_t slot indices; -1 = invalid.
*
* iOS lifecycle note: UIApplicationMain never returns. The el program must
* store its UI-build logic in a void(*)(void) function pointer, assign it to
* el_main_entry_fn, then call __native_run_loop. ElAppDelegate invokes
* el_main_entry_fn inside didFinishLaunchingWithOptions.
* Call el_uikit_set_args(argc, argv) from main() before __native_run_loop. */
#ifdef EL_TARGET_IOS
/* Lifecycle entry-function hook — set before calling __native_run_loop. */
extern void (*el_main_entry_fn)(void);
/* Forward argc/argv from main() to UIApplicationMain. */
void el_uikit_set_args(int argc, char** argv);
/* Initialisation */
void __native_init(void);
void __native_run_loop(void);
/* Window */
el_val_t __window_create(el_val_t title, el_val_t width, el_val_t height,
el_val_t min_width, el_val_t min_height);
void __window_show(el_val_t handle);
void __window_set_title(el_val_t handle, el_val_t title);
/* Layout containers */
el_val_t __vstack_create(el_val_t spacing);
el_val_t __hstack_create(el_val_t spacing);
el_val_t __zstack_create(void);
el_val_t __scroll_create(void);
/* Widgets */
el_val_t __label_create(el_val_t text);
el_val_t __button_create(el_val_t label);
el_val_t __text_field_create(el_val_t placeholder);
el_val_t __text_area_create(el_val_t placeholder);
el_val_t __image_create(el_val_t path_or_name);
/* Widget properties */
void __widget_set_text(el_val_t handle, el_val_t text);
el_val_t __widget_get_text(el_val_t handle);
void __widget_set_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_font(el_val_t handle, el_val_t family,
el_val_t size, el_val_t bold);
void __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
el_val_t bottom, el_val_t left);
void __widget_set_width(el_val_t handle, el_val_t width);
void __widget_set_height(el_val_t handle, el_val_t height);
void __widget_set_flex(el_val_t handle, el_val_t flex);
void __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void __widget_set_disabled(el_val_t handle, el_val_t disabled);
void __widget_set_hidden(el_val_t handle, el_val_t hidden);
/* Layout / tree */
void __widget_add_child(el_val_t parent, el_val_t child);
void __widget_remove_child(el_val_t parent, el_val_t child);
void __widget_destroy(el_val_t handle);
/* Events */
void __widget_on_click(el_val_t handle, el_val_t fn_name);
void __widget_on_change(el_val_t handle, el_val_t fn_name);
void __widget_on_submit(el_val_t handle, el_val_t fn_name);
/* Manifest reader */
el_val_t __manifest_read(el_val_t path);
#endif /* EL_TARGET_IOS */
/* ── Native widget system (Android JNI) ─────────────────────────────────────
* Available when compiled with -DEL_TARGET_ANDROID and linked with
* libelruntime.so (which includes el_android.c compiled by the NDK build).
* Widget handles are opaque int64_t slot indices; -1 = invalid.
*
* Java companion: ElBridge.java (package com.neuron.el) must be compiled into
* the APK. The Activity must call ElBridge.init(this) before any widget ops.
*
* Link flags (in Android.mk or CMakeLists.txt):
* -landroid -llog -ldl */
#ifdef EL_TARGET_ANDROID
/* Initialisation */
void __native_init(void);
void __native_run_loop(void); /* no-op on Android */
/* Window */
el_val_t __window_create(el_val_t title, el_val_t width, el_val_t height,
el_val_t min_width, el_val_t min_height);
void __window_show(el_val_t handle);
void __window_set_title(el_val_t handle, el_val_t title);
/* Layout containers */
el_val_t __vstack_create(el_val_t spacing);
el_val_t __hstack_create(el_val_t spacing);
el_val_t __zstack_create(void);
el_val_t __scroll_create(void);
/* Widgets */
el_val_t __label_create(el_val_t text);
el_val_t __button_create(el_val_t label);
el_val_t __text_field_create(el_val_t placeholder);
el_val_t __text_area_create(el_val_t placeholder);
el_val_t __image_create(el_val_t path_or_name);
/* Widget properties */
void __widget_set_text(el_val_t handle, el_val_t text);
el_val_t __widget_get_text(el_val_t handle);
void __widget_set_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_font(el_val_t handle, el_val_t family,
el_val_t size, el_val_t bold);
void __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
el_val_t bottom, el_val_t left);
void __widget_set_width(el_val_t handle, el_val_t width);
void __widget_set_height(el_val_t handle, el_val_t height);
void __widget_set_flex(el_val_t handle, el_val_t flex);
void __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void __widget_set_disabled(el_val_t handle, el_val_t disabled);
void __widget_set_hidden(el_val_t handle, el_val_t hidden);
/* Layout / tree */
void __widget_add_child(el_val_t parent, el_val_t child);
void __widget_remove_child(el_val_t parent, el_val_t child);
void __widget_destroy(el_val_t handle);
/* Events */
void __widget_on_click(el_val_t handle, el_val_t fn_name);
void __widget_on_change(el_val_t handle, el_val_t fn_name);
void __widget_on_submit(el_val_t handle, el_val_t fn_name);
/* Manifest reader */
el_val_t __manifest_read(el_val_t path);
#endif /* EL_TARGET_ANDROID */
/* ── Native widget system (LVGL v9 — embedded / microcontroller) ─────────────
* Available when compiled with -DEL_TARGET_LVGL and linked with el_lvgl.c
* and the LVGL library (lvgl.a or lvgl source tree).
*
* Target platforms: ESP32, STM32, industrial panels. Any system with 256KB+
* RAM and an LVGL-compatible display driver. No OS required.
*
* Widget handles are opaque int64_t slot indices; -1 = invalid.
*
* Bare-metal / no dynamic linker:
* Compile with -DEL_LVGL_NO_DLSYM and provide:
* el_val_t el_lvgl_dispatch(const char *fn, el_val_t a, el_val_t b);
*
* Compile:
* gcc -DEL_TARGET_LVGL -I./lvgl el_lvgl.c -c -o el_lvgl.o
* # Then link with lvgl.a. */
#ifdef EL_TARGET_LVGL
/* Initialisation */
void __native_init(void);
void __native_run_loop(void);
/* Window */
el_val_t __window_create(el_val_t title, el_val_t width, el_val_t height,
el_val_t min_width, el_val_t min_height);
void __window_show(el_val_t handle);
void __window_set_title(el_val_t handle, el_val_t title);
/* Layout containers */
el_val_t __vstack_create(el_val_t spacing);
el_val_t __hstack_create(el_val_t spacing);
el_val_t __zstack_create(void);
el_val_t __scroll_create(void);
/* Widgets */
el_val_t __label_create(el_val_t text);
el_val_t __button_create(el_val_t label);
el_val_t __text_field_create(el_val_t placeholder);
el_val_t __text_area_create(el_val_t placeholder);
el_val_t __image_create(el_val_t path_or_name);
/* Widget properties */
void __widget_set_text(el_val_t handle, el_val_t text);
el_val_t __widget_get_text(el_val_t handle);
void __widget_set_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_font(el_val_t handle, el_val_t family,
el_val_t size, el_val_t bold);
void __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
el_val_t bottom, el_val_t left);
void __widget_set_width(el_val_t handle, el_val_t width);
void __widget_set_height(el_val_t handle, el_val_t height);
void __widget_set_flex(el_val_t handle, el_val_t flex);
void __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void __widget_set_disabled(el_val_t handle, el_val_t disabled);
void __widget_set_hidden(el_val_t handle, el_val_t hidden);
/* Layout / tree */
void __widget_add_child(el_val_t parent, el_val_t child);
void __widget_remove_child(el_val_t parent, el_val_t child);
void __widget_destroy(el_val_t handle);
/* Events */
void __widget_on_click(el_val_t handle, el_val_t fn_name);
void __widget_on_change(el_val_t handle, el_val_t fn_name);
void __widget_on_submit(el_val_t handle, el_val_t fn_name);
/* Manifest reader — same JSON output as all other native targets */
el_val_t __manifest_read(el_val_t path);
#endif /* EL_TARGET_LVGL */
/* ── Native widget system (SDL2 — embedded / Pi) ────────────────────────────
* Available when compiled with -DEL_TARGET_SDL2 and linked with el_sdl2.c.
* Widget handles are opaque int64_t slot indices; -1 = invalid.
*
* Target: Raspberry Pi Zero, embedded Linux, any system with a framebuffer
* and SDL2 available. No GTK, no desktop environment required.
*
* Compile:
* gcc -DEL_TARGET_SDL2 $(sdl2-config --cflags) -c el_sdl2.c -o el_sdl2.o
* Link:
* $(sdl2-config --libs) -lSDL2_ttf -lSDL2_image -ldl */
#ifdef EL_TARGET_SDL2
/* Initialisation */
void __native_init(void);
void __native_run_loop(void);
/* Window */
el_val_t __window_create(el_val_t title, el_val_t width, el_val_t height,
el_val_t min_width, el_val_t min_height);
void __window_show(el_val_t handle);
void __window_set_title(el_val_t handle, el_val_t title);
/* Layout containers */
el_val_t __vstack_create(el_val_t spacing);
el_val_t __hstack_create(el_val_t spacing);
el_val_t __zstack_create(void);
el_val_t __scroll_create(void);
/* Widgets */
el_val_t __label_create(el_val_t text);
el_val_t __button_create(el_val_t label);
el_val_t __text_field_create(el_val_t placeholder);
el_val_t __text_area_create(el_val_t placeholder);
el_val_t __image_create(el_val_t path_or_name);
/* Widget properties */
void __widget_set_text(el_val_t handle, el_val_t text);
el_val_t __widget_get_text(el_val_t handle);
void __widget_set_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_bg_color(el_val_t handle, el_val_t r, el_val_t g,
el_val_t b, el_val_t a);
void __widget_set_font(el_val_t handle, el_val_t family,
el_val_t size, el_val_t bold);
void __widget_set_padding(el_val_t handle, el_val_t top, el_val_t right,
el_val_t bottom, el_val_t left);
void __widget_set_width(el_val_t handle, el_val_t width);
void __widget_set_height(el_val_t handle, el_val_t height);
void __widget_set_flex(el_val_t handle, el_val_t flex);
void __widget_set_corner_radius(el_val_t handle, el_val_t radius);
void __widget_set_disabled(el_val_t handle, el_val_t disabled);
void __widget_set_hidden(el_val_t handle, el_val_t hidden);
/* Layout / tree */
void __widget_add_child(el_val_t parent, el_val_t child);
void __widget_remove_child(el_val_t parent, el_val_t child);
void __widget_destroy(el_val_t handle);
/* Events */
void __widget_on_click(el_val_t handle, el_val_t fn_name);
void __widget_on_change(el_val_t handle, el_val_t fn_name);
void __widget_on_submit(el_val_t handle, el_val_t fn_name);
/* Manifest reader */
el_val_t __manifest_read(el_val_t path);
#endif /* EL_TARGET_SDL2 */