| Bring vidya in cfd3e36 nandi 20d ago | 1 | /* |
| 2 | * Vidya's retained-tree ABI — the reactive half. |
| 3 | * |
| 4 | * `raylib/include/vidya.h` is push/pop: the caller writes its UI out top to |
| 5 | * bottom every frame. That suits a program with a frame loop; it does not suit |
| 6 | * a reactive toolkit, which keeps a component tree, diffs it, and emits |
| 7 | * create/patch/append/remove against native widgets. |
| 8 | * |
| 9 | * This header is that widget layer. Nodes are integer handles, mutated by the |
| 10 | * calls below; nothing is drawn until `vidya_tree_frame`, which paints the |
| 11 | * whole tree at once. Interactions come back as a queue of events the caller |
| 12 | * drains and routes to its own handlers — a callback cannot cross this |
| 13 | * boundary, so identity does instead. |
| 14 | * |
| 15 | * The two halves share a window: open it with `vidya_open`, set the mode with |
| 16 | * `vidya_set_mode`, and drive `vidya_tree_frame` in place of |
| 17 | * `vidya_begin_frame` / `vidya_end_frame`. Do not mix them within one frame. |
| 18 | * |
| 19 | * Only the Rust/egui backend (`ffi/`) implements this header; the C/raylib |
| 20 | * backend implements `vidya.h` alone. Every call stays on the thread that |
| 21 | * called `vidya_open`, like the rest of the ABI. |
| 22 | */ |
| 23 | #ifndef VIDYA_TREE_H |
| 24 | #define VIDYA_TREE_H |
| 25 | |
| 26 | #include "vidya.h" |
| 27 | |
| 28 | #ifdef __cplusplus |
| 29 | extern "C" { |
| 30 | #endif |
| 31 | |
| 32 | /* |
| 33 | * Node handles are positive; 0 is "no node" — a failed allocation, and the |
| 34 | * `sibling` argument that means "first position". |
| 35 | * |
| 36 | * Tags are hiccup names without the colon: |
| 37 | * |
| 38 | * containers window box hbox vbox page card frame scroll |
| 39 | * widgets label title title-2 dim-label button checkbutton entry |
| 40 | * separator spacer progress spinner status |
| 41 | * |
| 42 | * An unrecognized tag is kept and paints as a vertical box, so a caller ahead |
| 43 | * of this backend still sees its children. |
| 44 | * |
| 45 | * Props are string-keyed, in the same names: |
| 46 | * |
| 47 | * every node sensitive (bool) |
| 48 | * box orientation ("horizontal"|"vertical"), spacing, margin |
| 49 | * page max-width |
| 50 | * scroll orientation ("vertical"|"horizontal"|"both") |
| 51 | * text widgets label, or text |
| 52 | * button label, kind ("default"|"primary"|"destructive") |
| 53 | * checkbutton label, active (bool) |
| 54 | * entry text, placeholder, multiline (bool), rows |
| 55 | * spacer size |
| 56 | * progress value (0..1), label |
| 57 | * status label, live (bool) |
| 58 | */ |
| 59 | |
| 60 | /* The window node, created on first use. Mount everything under it. */ |
| 61 | VIDYA_API int vidya_tree_root(void); |
| 62 | |
| 63 | VIDYA_API int vidya_node_new(const char *tag); |
| 64 | VIDYA_API void vidya_node_free(int node); |
| 65 | VIDYA_API int vidya_node_exists(int node); |
| 66 | |
| 67 | VIDYA_API void vidya_node_set_str(int node, const char *key, const char *value); |
| 68 | VIDYA_API void vidya_node_set_num(int node, const char *key, double value); |
| 69 | VIDYA_API void vidya_node_set_bool(int node, const char *key, int value); |
| 70 | VIDYA_API void vidya_node_clear_props(int node); |
| 71 | |
| 72 | /* |
| 73 | * Reads answer the empty string / 0 for a prop that is unset or of another |
| 74 | * type. The returned pointer belongs to the library and is valid only until |
| 75 | * the next string-returning call on this thread — copy it before the next one. |
| 76 | */ |
| 77 | VIDYA_API const char *vidya_node_get_str(int node, const char *key); |
| 78 | VIDYA_API double vidya_node_get_num(int node, const char *key); |
| 79 | VIDYA_API int vidya_node_get_bool(int node, const char *key); |
| 80 | |
| 81 | /* |
| 82 | * Reading the structure back. `vidya_node_tag` answers the canonical tag name |
| 83 | * ("box" for both hbox and vbox), under the same borrowed-pointer rule as the |
| 84 | * prop reads above; `vidya_node_child_at` answers 0 past the end. |
| 85 | */ |
| 86 | VIDYA_API const char *vidya_node_tag(int node); |
| 87 | VIDYA_API int vidya_node_child_count(int node); |
| 88 | VIDYA_API int vidya_node_child_at(int node, int index); |
| 89 | |
| 90 | /* |
| 91 | * The subtree at `node` as pretty-printed hiccup — `[:tag {props} children...]`, |
| 92 | * one node to a line — for logging, tests, and bug reports. `node` 0 means the |
| 93 | * root, so `vidya_tree_dump(0)` is the whole window. Borrowed pointer, under |
| 94 | * the same rule as the reads above. |
| 95 | * |
| 96 | * It answers what the tree *is*, read back from the arena, rather than what a |
| 97 | * caller meant to build. Two caveats: `hbox` and `vbox` both dump as `box`, |
| 98 | * with the orientation in the props, and handlers are absent because they |
| 99 | * never crossed this boundary. |
| 100 | */ |
| 101 | VIDYA_API const char *vidya_tree_dump(int node); |
| 102 | |
| 103 | VIDYA_API int vidya_node_append(int parent, int child); |
| 104 | /* Unparents AND frees `child` with everything under it. */ |
| 105 | VIDYA_API void vidya_node_remove(int parent, int child); |
| 106 | /* Moves `child` after `sibling`; `sibling` 0 means the first position. */ |
| 107 | VIDYA_API int vidya_node_insert_after(int parent, int child, int sibling); |
| 108 | /* Puts `new_child` where `old_child` was, and frees `old_child`. */ |
| 109 | VIDYA_API int vidya_node_replace(int parent, int old_child, int new_child); |
| 110 | |
| 111 | /* Paint the whole tree as one frame. Inert with no window open. */ |
| 112 | VIDYA_API void vidya_tree_frame(void); |
| 113 | |
| 114 | /* |
| 115 | * Drain interactions. `vidya_tree_poll_event` dequeues one and answers 1 while |
| 116 | * there was one; the accessors describe whichever was dequeued last. |
| 117 | * |
| 118 | * Event names are glimmer's handler props without the `on-`: |
| 119 | * |
| 120 | * click a button was pressed no payload |
| 121 | * toggled a checkbutton changed num is the new state |
| 122 | * change an entry's text changed text is the new text |
| 123 | * activate Enter was pressed in an entry no payload |
| 124 | * |
| 125 | * A widget does not own its value: `toggled` and `change` write the new state |
| 126 | * back into the node's props as well, so a caller that ignores the event still |
| 127 | * sees a working control, and the next prop write is what settles it. |
| 128 | */ |
| 129 | VIDYA_API int vidya_tree_poll_event(void); |
| 130 | VIDYA_API int vidya_tree_event_node(void); |
| 131 | VIDYA_API const char *vidya_tree_event_name(void); |
| 132 | VIDYA_API const char *vidya_tree_event_text(void); |
| 133 | VIDYA_API double vidya_tree_event_num(void); |
| 134 | |
| 135 | /* Live frames |
| 136 | * |
| 137 | * Hand the tree a frame of raw pixels under `key`; any `:image` node whose |
| 138 | * `feed` prop names it paints the latest one. Returns 1 when accepted. |
| 139 | * |
| 140 | * This is what `src` cannot do: a `src` image decodes a file and caches the |
| 141 | * texture by its path for the life of the process, which is right for a |
| 142 | * picture in a message and useless for a source that makes a new one thirty |
| 143 | * times a second. A caller with its own pixels — a camera, a video decoder, a |
| 144 | * renderer — pushes them here instead. |
| 145 | * |
| 146 | * `rgba` is width * height * 4 bytes, row-major, 8 bits a channel, |
| 147 | * un-premultiplied. It is copied before the call returns; the caller may reuse |
| 148 | * the buffer immediately. A length disagreeing with the dimensions is refused. |
| 149 | * |
| 150 | * Frames coalesce rather than queue: one arriving before the last was painted |
| 151 | * replaces it, so a source faster than the window builds no backlog. |
| 152 | * |
| 153 | * Like the rest of this ABI, on the window's thread. `vidya_frame_drop` |
| 154 | * forgets a feed and releases its texture — without it the last frame of a |
| 155 | * source that has stopped keeps painting. |
| 156 | */ |
| 157 | VIDYA_API int vidya_frame_rgba(const char *key, int width, int height, |
| 158 | const unsigned char *rgba); |
| 159 | VIDYA_API int vidya_frame_drop(const char *key); |
| 160 | |
| 161 | /* Clipboard |
| 162 | * |
| 163 | * Write the picture on the system clipboard to `path` as a PNG; returns 1 when |
| 164 | * there was one and it was written, 0 otherwise (an empty clipboard, text on |
| 165 | * it, an unwritable path, or a platform with no image clipboard at all). |
| 166 | * |
| 167 | * A pasted image arrives through no event — egui carries only clipboard text |
| 168 | * into a frame — so this is asked rather than waited for: bind it to whatever |
| 169 | * gesture means paste, and read the file it names. Needs no window, and unlike |
| 170 | * the rest of this ABI is not tied to the window's thread. |
| 171 | */ |
| 172 | VIDYA_API int vidya_clipboard_image_png(const char *path); |
| 173 | |
| 174 | /* Open a URL |
| 175 | * |
| 176 | * Hand `url` to whatever shows web pages here — xdg-open/open on the desktop, |
| 177 | * an ACTION_VIEW intent on Android; returns 1 when something took it and 0 |
| 178 | * otherwise, in which case show the URL and let the reader carry it across. |
| 179 | * |
| 180 | * Like the clipboard call above it needs no window and no particular thread. |
| 181 | */ |
| 182 | VIDYA_API int vidya_open_url(const char *url); |
| 183 | |
| 184 | #ifdef __cplusplus |
| 185 | } |
| 186 | #endif |
| 187 | |
| 188 | #endif /* VIDYA_TREE_H */ |