#include "cell.h" #include #include #define LAY_FLOAT 1 #define LAY_IMPLEMENTATION #include "layout.h" static JSClassID js_layout_class_id; #define GETLAY \ lay_context *lay = JS_GetOpaque2(js, self, js_layout_class_id); \ if (!lay) return JS_EXCEPTION; #define GETITEM(VAR, ARG) \ lay_id VAR; \ if (JS_ToUint32(js, &VAR, ARG)) return JS_EXCEPTION; \ static JSValue js_layout_context_new(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { lay_context *lay = js_malloc(js, sizeof(*lay)); lay_init_context(lay); JSValue obj = JS_NewObjectClass(js, js_layout_class_id); JS_SetOpaque(obj, lay); return obj; } static JSValue js_layout_item(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY lay_id item_id = lay_item(lay); return JS_NewUint32(js,item_id); } static JSValue js_layout_set_size(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { if (argc < 2) return JS_EXCEPTION; GETLAY GETITEM(id, argv[0]) double width = 0, height = 0; // Check if it's an array (for backwards compatibility) if (JS_IsArray(js, argv[1])) { JSValue width_val = JS_GetPropertyUint32(js, argv[1], 0); JSValue height_val = JS_GetPropertyUint32(js, argv[1], 1); JS_ToFloat64(js, &width, width_val); JS_ToFloat64(js, &height, height_val); JS_FreeValue(js, width_val); JS_FreeValue(js, height_val); } else { // Handle object with x,y or width,height properties JSValue width_val = JS_GetPropertyStr(js, argv[1], "width"); if (JS_IsNull(width_val)) { width_val = JS_GetPropertyStr(js, argv[1], "x"); } JSValue height_val = JS_GetPropertyStr(js, argv[1], "height"); if (JS_IsNull(height_val)) { height_val = JS_GetPropertyStr(js, argv[1], "y"); } JS_ToFloat64(js, &width, width_val); JS_ToFloat64(js, &height, height_val); JS_FreeValue(js, width_val); JS_FreeValue(js, height_val); } if (isnan(width)) width = 0; if (isnan(height)) height = 0; lay_set_size_xy(lay, id, width, height); return JS_NULL; } static JSValue js_layout_set_behave(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY GETITEM(id, argv[0]) uint32_t behave_flags; JS_ToUint32(js, &behave_flags, argv[1]); lay_set_behave(lay, id, behave_flags); return JS_NULL; } static JSValue js_layout_set_contain(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY GETITEM(id, argv[0]) uint32_t contain_flags; JS_ToUint32(js, &contain_flags, argv[1]); lay_set_contain(lay, id, contain_flags); return JS_NULL; } #define PULLMARGIN(DIR,MARGIN) \ JSValue js_##DIR = JS_GetPropertyStr(js, argv[1], #DIR); \ if (!JS_IsNull(js_##DIR)) { \ JS_ToFloat64(js, &margins[MARGIN], js_##DIR); \ if (isnan(margins[MARGIN])) margins[MARGIN] = 0; \ JS_FreeValue(js, js_##DIR); \ }\ static JSValue js_layout_set_margins(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY GETITEM(id, argv[0]) double margins[4] = {0}; PULLMARGIN(l,0) PULLMARGIN(r,2) PULLMARGIN(t,1) PULLMARGIN(b,3) lay_set_margins_ltrb(lay, id, margins[0], margins[1], margins[2], margins[3]); return JS_NULL; } static JSValue js_layout_insert(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY GETITEM(parent, argv[0]) GETITEM(child, argv[1]) lay_insert(lay, parent, child); return JS_NULL; } static JSValue js_layout_append(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY GETITEM(earlier, argv[0]) GETITEM(later, argv[1]) lay_append(lay, earlier, later); return JS_NULL; } static JSValue js_layout_push(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY GETITEM(parent, argv[0]) GETITEM(child, argv[1]) lay_push(lay, parent, child); return JS_NULL; } static JSValue js_layout_run(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY lay_run_context(lay); return JS_NULL; } static JSValue js_layout_get_rect(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY GETITEM(id, argv[0]) lay_vec4 rect = lay_get_rect(lay, id); JSValue ret = JS_NewObject(js); JS_SetPropertyStr(js, ret, "x", JS_NewFloat64(js, rect[0])); JS_SetPropertyStr(js, ret, "y", JS_NewFloat64(js, rect[1])); JS_SetPropertyStr(js, ret, "width", JS_NewFloat64(js, rect[2])); JS_SetPropertyStr(js, ret, "height", JS_NewFloat64(js, rect[3])); return ret; } static JSValue js_layout_reset(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { GETLAY lay_reset_context(lay); return JS_NULL; } static void js_layout_finalizer(JSRuntime *rt, JSValue val) { lay_context *ctx = JS_GetOpaque(val, js_layout_class_id); lay_destroy_context(ctx); js_free_rt(rt, ctx); } static JSClassDef js_layout_class = { "layout_context", .finalizer = js_layout_finalizer, }; static const JSCFunctionListEntry js_layout_proto_funcs[] = { JS_CFUNC_DEF("item", 1, js_layout_item), JS_CFUNC_DEF("insert", 2, js_layout_insert), JS_CFUNC_DEF("append", 2, js_layout_append), JS_CFUNC_DEF("push", 2, js_layout_push), JS_CFUNC_DEF("run", 0, js_layout_run), JS_CFUNC_DEF("get_rect", 1, js_layout_get_rect), JS_CFUNC_DEF("reset", 0, js_layout_reset), JS_CFUNC_DEF("set_margins", 2, js_layout_set_margins), JS_CFUNC_DEF("set_size", 2, js_layout_set_size), JS_CFUNC_DEF("set_contain", 2, js_layout_set_contain), JS_CFUNC_DEF("set_behave", 2, js_layout_set_behave), }; static const JSCFunctionListEntry js_layout_funcs[] = { JS_CFUNC_DEF("make_context", 0, js_layout_context_new) }; CELL_USE_INIT( JS_NewClassID(&js_layout_class_id); JS_NewClass(JS_GetRuntime(js), js_layout_class_id, &js_layout_class); JSValue proto = JS_NewObject(js); JS_SetPropertyFunctionList(js, proto, js_layout_proto_funcs, sizeof(js_layout_proto_funcs) / sizeof(JSCFunctionListEntry)); JS_SetClassProto(js, js_layout_class_id, proto); JSValue contain = JS_NewObject(js); JSValue behave = JS_NewObject(js); JS_SetPropertyStr(js, contain, "row", JS_NewUint32(js, LAY_ROW)); JS_SetPropertyStr(js, contain, "column", JS_NewUint32(js, LAY_COLUMN)); JS_SetPropertyStr(js, contain, "layout", JS_NewUint32(js, LAY_LAYOUT)); JS_SetPropertyStr(js, contain, "flex", JS_NewUint32(js, LAY_FLEX)); JS_SetPropertyStr(js, contain, "wrap", JS_NewUint32(js, LAY_WRAP)); JS_SetPropertyStr(js, contain, "nowrap", JS_NewUint32(js, LAY_NOWRAP)); JS_SetPropertyStr(js, contain, "start", JS_NewUint32(js, LAY_START)); JS_SetPropertyStr(js, contain, "middle", JS_NewUint32(js, LAY_MIDDLE)); JS_SetPropertyStr(js, contain, "end", JS_NewUint32(js, LAY_END)); JS_SetPropertyStr(js, contain, "justify", JS_NewUint32(js, LAY_JUSTIFY)); JS_SetPropertyStr(js, behave, "left", JS_NewUint32(js, LAY_LEFT)); JS_SetPropertyStr(js, behave, "top", JS_NewUint32(js, LAY_TOP)); JS_SetPropertyStr(js, behave, "right", JS_NewUint32(js, LAY_RIGHT)); JS_SetPropertyStr(js, behave, "bottom", JS_NewUint32(js, LAY_BOTTOM)); JS_SetPropertyStr(js, behave, "hfill", JS_NewUint32(js, LAY_HFILL)); JS_SetPropertyStr(js, behave, "vfill", JS_NewUint32(js, LAY_VFILL)); JS_SetPropertyStr(js, behave, "hcenter", JS_NewUint32(js, LAY_HCENTER)); JS_SetPropertyStr(js, behave, "vcenter", JS_NewUint32(js, LAY_VCENTER)); JS_SetPropertyStr(js, behave, "center", JS_NewUint32(js, LAY_CENTER)); JS_SetPropertyStr(js, behave, "fill", JS_NewUint32(js, LAY_FILL)); JS_SetPropertyStr(js, behave, "break", JS_NewUint32(js, LAY_BREAK)); JSValue export = JS_NewObject(js); JS_SetPropertyFunctionList(js, export, js_layout_funcs, sizeof(js_layout_funcs)/sizeof(JSCFunctionListEntry)); JS_SetPropertyStr(js, export, "behave", behave); JS_SetPropertyStr(js, export, "contain", contain); return export; )