/* * meow_ui_view.c — meow_view 视图/页面框架骨架(§A 视图数据结构/嵌套/生命周期/页面导航)。 * * meow_view 是**薄壳**:容器 + 生命周期 + 事件路由;叶子仍是 meow_widget(不改)。绘制走 * z 序绘制物注册表(on_draw 回调,非保留——不缓存像素)。opt-in:不调 meow_view_* 的 App * 完全照旧(widget/activity/flush 不动)。页面模型 = 定案 b(顶层页切走 activity 栈, * page_push/pop/replace 包装;不做页内子导航栈,sub_push/pop 为预留扩展位 a 桩)。 */ #include "meow_ui.h" #include "meow_ui_internal.h" #include "meow_ui_view.h" #include #include #define MEOW_VIEW_BY_ID_MAX 32 static meow_view *g_view_by_id[MEOW_VIEW_BY_ID_MAX]; /* id → 顶层页 view(page_push/pop 查找) */ static meow_view *g_top_view = NULL; /* 当前进入的顶层页 view(生命周期跟踪) */ static void run_fn(meow_view_fn f, meow_view *v) { if (f) f(v, v->ctx); } /* 登记/清除 id→view 映射(幂等)。 */ static void view_map_set(meow_view *v) { if (!v) return; int id = v->id; if (id >= 0 && id < MEOW_VIEW_BY_ID_MAX) g_view_by_id[id] = v; } static void view_map_clear(meow_view *v) { if (!v) return; int id = v->id; if (id >= 0 && id < MEOW_VIEW_BY_ID_MAX && g_view_by_id[id] == v) g_view_by_id[id] = NULL; } static meow_view *view_map_get(int id) { return (id >= 0 && id < MEOW_VIEW_BY_ID_MAX) ? g_view_by_id[id] : NULL; } /* 进入一个 view(置 ENTERED + on_enter)。 */ static void view_enter(meow_view *v) { if (!v || (v->state & MEOW_VIEW_STATE_ENTERED)) return; v->state |= MEOW_VIEW_STATE_ENTERED; run_fn(v->hooks.on_enter, v); } /* 离开一个 view(清 ENTERED + on_leave;默认不销毁子 view/widget——弹回零重建)。 */ static void view_leave(meow_view *v) { if (!v || !(v->state & MEOW_VIEW_STATE_ENTERED)) return; v->state &= ~MEOW_VIEW_STATE_ENTERED; run_fn(v->hooks.on_leave, v); } /* ============================================================ */ /* 生命周期 */ /* ============================================================ */ meow_view *meow_view_create(int id, meow_view_type type, const meow_view_hooks *hooks, void *ctx) { meow_view *v = (meow_view *)calloc(1, sizeof *v); if (!v) return NULL; v->id = id; v->type = (type == MEOW_VIEW_CONTAINER) ? MEOW_VIEW_CONTAINER : MEOW_VIEW_ACTIVITY; v->x = v->y = v->w = v->h = 0; v->z = 0; v->state = MEOW_VIEW_STATE_CREATED; if (hooks) v->hooks = *hooks; v->ctx = ctx; view_map_set(v); meow_draw_view_register(v); /* 登记为绘制物(on_draw 经 z 序重画触发) */ run_fn(v->hooks.on_create, v); if (v->hooks.on_layout) run_fn(v->hooks.on_layout, v); /* 布局:create 后跑一次 */ return v; } void meow_view_free(meow_view *v) { if (!v) return; if (v->state & MEOW_VIEW_STATE_ENTERED) view_leave(v); run_fn(v->hooks.on_destroy, v); /* 释放视图态资源 */ view_map_clear(v); meow_draw_view_unregister(v); /* 注销 z 序绘制物 */ for (int i = 0; i < v->nwidgets; i++) /* 叶子控件 */ meow_widget_free(v->widgets[i]); v->nwidgets = 0; for (int i = 0; i < v->nchildren; i++) /* 子 view 递归 */ meow_view_free(v->children[i]); v->nchildren = 0; free(v); } /* ============================================================ */ /* 嵌套(组合视图树) */ /* ============================================================ */ int meow_view_add_child(meow_view *parent, meow_view *child) { if (!parent || !child || child == parent) return -1; for (int i = 0; i < parent->nchildren; i++) if (parent->children[i] == child) return -1; /* 去重 */ if (parent->nchildren >= MEOW_VIEW_MAX_CHILD) return -1; parent->children[parent->nchildren++] = child; child->parent = parent; return 0; } int meow_view_add_widget(meow_view *v, meow_widget *w) { if (!v || !w) return -1; for (int i = 0; i < v->nwidgets; i++) if (v->widgets[i] == w) return -1; if (v->nwidgets >= MEOW_VIEW_MAX_WIDGET) return -1; v->widgets[v->nwidgets++] = w; meow_draw_widget_set_view(w, v); /* z 深度源 = view 树;重算 auto z */ return 0; } void meow_view_set_z(meow_view *v, int z) { if (!v) return; v->z = (z < 0) ? 0 : z; meow_draw_view_set_z(v, v->z); } int meow_view_z(const meow_view *v) { return v ? v->z : 0; } /* ============================================================ */ /* 页面导航(包装 activity 栈——唯一驱动 on_enter/on_leave) */ /* ============================================================ */ void meow_view_page_push(int id) { meow_view *cur = g_top_view; meow_view *next = view_map_get(id); if (cur && cur != next) view_leave(cur); meow_ui_activity_push(id); view_enter(next); g_top_view = next ? next : cur; } void meow_view_page_pop(void) { meow_view *cur = g_top_view; view_leave(cur); meow_ui_activity_pop(); meow_view *next = view_map_get(meow_ui_activity_active()); view_enter(next); g_top_view = next ? next : NULL; } /* 说明(诚实):replace 假定目标页已由 App 先 meow_view_create 指定 id 建好;本批不销毁旧页 * 对象(保留弹回),仅 leave+enter 切换——与设计「leave+destroy 当前」的差异见汇报。 */ void meow_view_page_replace(int id) { meow_view *cur = g_top_view; meow_view *next = view_map_get(id); if (cur && cur != next) view_leave(cur); view_enter(next); g_top_view = next ? next : cur; } /* ---- 页内子导航(预留扩展位 a 桩:本批不实现,仅返回占位)---- */ int meow_view_sub_push(meow_view *v, meow_view *sub) { (void)v; (void)sub; return 0; /* 预留:将来在 ACTIVITY view 内维护子栈 */ } meow_view *meow_view_sub_pop(meow_view *v) { (void)v; return NULL; /* 预留 */ } /* ============================================================ */ /* 坐标 / 查询 */ /* ============================================================ */ int meow_view_screen_x(const meow_view *v) { int x = v ? v->x : 0; const meow_view *p = v ? v->parent : NULL; while (p) { x += p->x; p = p->parent; } return x; } int meow_view_screen_y(const meow_view *v) { int y = v ? v->y : 0; const meow_view *p = v ? v->parent : NULL; while (p) { y += p->y; p = p->parent; } return y; } meow_view *meow_view_parent(const meow_view *v) { return v ? v->parent : NULL; } int meow_view_get_state(const meow_view *v) { return v ? (int)v->state : 0; }