Files
MeowOS-For-R3P2/patch_v2/sdk/meow_ui_view.h
T
MeowOS 5a5e995ebd SDK 冲刺批①+②+⑤: meow_box 线性布局 + meow_anim 动画基座 + meow_scroll 滚动物理
- meow_box(include/meow_ui_box.h + meow_ui_box.c):竖直/水平容器;子项=固定|weight|wrap;
  margin/padding/gap;主轴对齐 start/center/end/space-between/around/evenly;交叉轴 start/center/end/stretch;
  嵌套(深度≤16 静态栈,单遍求解,无递归爆炸)。可作 meow_view 布局提供者
  (meow_view_set_layout/relayout,opt-in;未设布局的 view 保持现有绝对坐标行为)。
  新增 meow_widget_set_rect(只写字段不标脏)作为 box 写坐标的通道。
- meow_anim(include/meow_ui_anim.h + meow_ui_anim.c):时间驱动 tween(from/to/duration/easing:
  linear/ease-out/ease-in-out/overshoot)+ update/done 回调;静态池≤16、取消、并行多动画;
  meow_anim_set_region 让每帧只 flush 动画影响区(不整屏)。meow_anim_tick 挂主循环 on_tick,
  无动画零开销(只查计数即返回)。
- meow_scroll(include/meow_ui_scroll.h + meow_ui_scroll.c):速度跟踪(最近 N 采样加权)+ 松手 fling
  (减速度曲线,用 anim 基座驱动)+ 边界过冲 clamp + 简单回弹(不做 spring)+ 可选 snap;
  跟手拖动行为不变(track 内部调既有 set_scroll);每帧只 redraw 列表视口区;不引 libm。
- 追加式:既有 meow_row/column/box 与全部 meow_*_create/hit/scroll 签名一行未改;旧绝对坐标永远有效;
  既有 App 免改源码。
- 验证:宿主新测试 box(42)/anim(32)/scroll(17) 全 PASS;既存 9 回归(widgets/sdk_input_keys/ime_fix/
  pinyin/overlay_suppress/notif_gesture/sdk_fixes/sb_collapse/p1p2p3_repro)全 PASS;
  离屏 demo(demo_box_scroll.c)渲染 box 布局 + 列表 fling 正常;zig-mipsel -Wall -Wextra 全 TU 0 warning;
  meow_ui.a md5 83dd6a2d0d24cc748a8659c29f1de2b5(未重链/部署 hello/files/ncm/reader,由主会话统一处理)。
2026-09-01 23:49:24 +08:00

112 lines
6.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* meow_ui_view.h — SDK 视图/页面框架(meow_view,嵌套容器 + 生命周期 + 事件路由)。
*
* 源:devdocs/plan/SDK_VIEW_FRAMEWORK_DESIGN.md §A。本文件为机制 ABI(结构 + 生命周期钩子 +
* 页面导航包装),与 z 序绘制物注册表(meow_ui_draw.c,§C/§6.2)协同:
* - meow_view 是**薄壳**:容器 + 生命周期 + 事件路由;叶子仍是 meow_widget(不改)。
* - on_draw 是回调,view 不缓存像素(非保留);重绘由 meow_ui_invalidate 触发。
* - opt-in:不调用 meow_view_* 的 App 完全照旧(widget/activity/flush 不动)。
* - z 深度源 = view 树(parent/children 深度);叶子 widget 深度 = 所属 view 深度 + 1。
*
* 页面模型(定案 b,预留 a):顶层页切换仍由 activity 栈(meow_view_page_push/pop/replace 包装),
* 不做页内子导航栈;meow_view_sub_push/pop 为将来扩展位(仅在一个 ACTIVITY view 内维护子栈)。
*/
#ifndef MEOW_UI_VIEW_H
#define MEOW_UI_VIEW_H
#include "meow_ui.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct meow_view meow_view;
typedef enum { MEOW_VIEW_ACTIVITY = 0, MEOW_VIEW_CONTAINER = 1 } meow_view_type;
typedef enum {
MEOW_VIEW_STATE_CREATED = 1u << 0,
MEOW_VIEW_STATE_ENTERED = 1u << 1,
MEOW_VIEW_STATE_DIRTY = 1u << 2,
} meow_view_state;
/* 生命周期/事件钩子(on_create→on_enter→(事件循环)→on_leave→on_destroy + on_layout)。
* 均以 view 自身 + ctx(=视图控制器,业务-UI 绑定点)为参。可 NULL。 */
typedef void (*meow_view_fn)(meow_view *v, void *ctx);
typedef int (*meow_view_ev_fn)(meow_view *v, int ev, int a, int b, void *ctx);
typedef void (*meow_view_draw_fn)(meow_view *v, const meow_theme *th, void *ctx);
typedef struct meow_view_hooks {
meow_view_fn on_create; /* 建 view 后跑一次(分配视图态/初始布局) */
meow_view_fn on_enter; /* 页面进入(push/replace 后;回页面自动恢复零重建) */
meow_view_fn on_leave; /* 页面离开(pop/replace 前;默认不销毁子 view/widget) */
meow_view_fn on_destroy; /* meow_view_free 释放(递归)时跑 */
meow_view_fn on_layout; /* 布局(on_create/page_push 后跑一次,算子控件绝对坐标) */
meow_view_draw_fn on_draw; /* 绘制回调(非保留;由 meow_ui_invalidate 触发) */
meow_view_ev_fn on_event; /* 事件路由(可 NULL;先发后代按 z 降序,命中即消费) */
} meow_view_hooks;
#define MEOW_VIEW_MAX_CHILD 16
#define MEOW_VIEW_MAX_WIDGET 32
struct meow_view {
int type; /* MEOW_VIEW_ACTIVITY / MEOW_VIEW_CONTAINER */
int id; /* 页面/视图 id(App 命名的稳定值;= page_push 用的 id) */
int x, y, w, h; /* 自身坐标(相对父内容原点;子 view 默认占满,叠放由 z 排) */
meow_view *parent;
meow_view *children[MEOW_VIEW_MAX_CHILD];
int nchildren;
meow_widget *widgets[MEOW_VIEW_MAX_WIDGET]; /* 叶子控件(直接挂本 view) */
int nwidgets;
int z; /* 显式 z(meow_view_set_z);0=未设(由子/注册表推导) */
unsigned state; /* meow_view_state 位掩码 */
meow_view_hooks hooks;
void *ctx; /* 视图控制器(biz-UI 绑定点) */
};
/* ---- 生命周期 ---- */
meow_view *meow_view_create(int id, meow_view_type type,
const meow_view_hooks *hooks, void *ctx);
void meow_view_free(meow_view *v); /* 递归 on_destroy + widget_free 叶子 + 注销 z 序 */
/* ---- 嵌套(组合视图树)---- */
int meow_view_add_child(meow_view *parent, meow_view *child); /* 任意深挂子 view;0/负=结果 */
int meow_view_add_widget(meow_view *v, meow_widget *w); /* 挂叶子控件(登记 z 深度源) */
void meow_view_set_z(meow_view *v, int z); /* 显式 z(999 置顶);影响其绘制物 z */
int meow_view_z(const meow_view *v);
/* ---- 页面导航(包装 activity 栈,唯一驱动 on_enter/on_leave——单一入口,App 不再分别调)----
* 顶层页切换走 activity 栈;页内子导航为预留(见设计定案 b)。 */
void meow_view_page_push(int id); /* activity_push + 旧top on_leave + 新页 on_enter */
void meow_view_page_pop(void); /* 旧top on_leave + activity_pop + 新top on_enter */
void meow_view_page_replace(int id); /* 旧top on_leave + 新页 on_enter(目标页须已 create) */
/* 入口:把语义事件注入当前活动页 view 子树路由——先发子视图(按 z 降序),命中即消费,
* 再落本 view 的 on_event(其内做该 view 的 widget 命中)。返回 1=已消费(§A.7)。
* 未接线于 meow_ui_run(App 可在 on_tap/on_swipe 等回调里改用它实现 SDK 原生路由)。 */
int meow_view_dispatch_event(int ev, int a, int b);
/* ---- 页内子导航(预留扩展位 a;本批为空实现/桩,仅在 ACTIVITY view 内维护子栈)---- */
int meow_view_sub_push(meow_view *v, meow_view *sub); /* 预留;返回 0(未实现于本批) */
meow_view *meow_view_sub_pop(meow_view *v); /* 预留;返回 NULL(未实现于本批) */
/* ---- 坐标:view 相对父内容原点的累计(父坐标链求和 → 屏幕绝对坐标)---- */
int meow_view_screen_x(const meow_view *v);
int meow_view_screen_y(const meow_view *v);
/* ---- 查询 ---- */
meow_view *meow_view_parent(const meow_view *v);
int meow_view_get_state(const meow_view *v); /* MEOW_VIEW_STATE_* 位掩码 */
/* ---- 布局提供者(§12.1.4:meow_box 作为 view 的 layout,opt-in)----
* meow_box(见 include/meow_ui_box.h)是**纯布局计算器**,arrange 把子控件算成绝对坐标。
* 设了布局的 view:其直接挂载控件应**同时**加入该 box(box 会在 arrange 时写这些控件的
* x/y/w/h);page 进入/relayout 时框架自动 arrange。未设布局的 view 保持现有绝对坐标行为
* (on_layout 里自己算,零改动)。box 矩形默认跟 view 内容矩形(w/h 未设时自动填)。 */
void meow_view_set_layout(meow_view *v, struct meow_box *box); /* NULL=取消 */
void meow_view_relayout(meow_view *v); /* 手动重排(改 box 后调) */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_VIEW_H */