sdk: 增量同步主仓新模块(box/anim/scroll/dispatch/listvirt/str/sb_icons/img)
subtree pull sdk 来自主仓 pub/sdk(主仓 commit 68ce46a 等)。新增: - 布局引擎 meow_ui_box / 动画基座 meow_ui_anim / 滚动物理 meow_ui_scroll - §6.4 事件分发形式化 / W_LISTVIEW 虚拟化多行 / meow_str 字符串资源 i18n - sb_icons 动作图标扩充 + topbar 位图图标 / meow_img_downscale - tools/ 图标生成脚本与 SVG 源 - 对应宿主 test_*.c 与 demo_box_scroll.c build_sdk.sh 冲突解析:保留公开仓自包含版(vendored meow_font + -Iinclude -I.), OBJS 手工并入 4 个新模块(meow_ui_box/anim/scroll/str)。保留 vendored meow_font.c/ meow_ipc.h/meow_font.h/meow_notif.h,剔除宿主测试二进制与编译产物。
This commit is contained in:
commit
4b094d62a5
56 files changed
+4327
-117
No files matched your search
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* meow_ui_anim.h — SDK 动画基座 + UI 节拍器(§12.2:meow_anim / meow_anim_tick)。
|
||||
*
|
||||
* 定位:给应用提供**时间驱动 tween**(from/to/duration/easing)+ 完成/取消回调,并行多动画
|
||||
* (静态池≤MEOW_ANIM_MAX)+ 与脏区集成(动画帧只标动画影响区,不做整屏重绘)。
|
||||
*
|
||||
* 节拍:**挂既有 on_tick 机制**(meow_ui_run 主循环 / meow_ui_feed_tick 阻塞 IME 循环),
|
||||
* 无常驻高频轮询;无动画时 meow_anim_tick() 只做一个计数检查即返回(零开销)。
|
||||
*
|
||||
* 内存纪律:静态池(≤MEOW_ANIM_MAX),start/cancel/tick 全程零 malloc。
|
||||
*
|
||||
* 与 §7 的关系:§7(B1 最小可用)是「应用自己在 on_tick 里用 meow_ui_time_ms 做时间轴」;
|
||||
* 本模块把这件事收敛成声明式 tween 对象 + 结束回调,是 §7 的**正式基座**(应用可任选其一或混用)。
|
||||
*/
|
||||
#ifndef MEOW_UI_ANIM_H
|
||||
#define MEOW_UI_ANIM_H
|
||||
|
||||
#include "meow_ui_types.h" /* 基础类型(子头不引伞头,避免相对路径依赖) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ---- 缓动曲线(t∈[0,1] → 曲线化的进度;OVERSHOOT 在中后段可略>1、末点恰=1)---- */
|
||||
typedef enum {
|
||||
MEOW_EASE_LINEAR = 0,
|
||||
MEOW_EASE_OUT = 1, /* 快进慢停(decelerate) */
|
||||
MEOW_EASE_IN_OUT = 2, /* 慢入慢出 */
|
||||
MEOW_EASE_OVERSHOOT = 3, /* 越过目标再回稳(小回弹) */
|
||||
} meow_ease;
|
||||
|
||||
float meow_ease_apply(meow_ease e, float t);
|
||||
|
||||
/* ---- 动画对象(不透明句柄;静态池)---- */
|
||||
#define MEOW_ANIM_MAX 16
|
||||
|
||||
typedef struct meow_anim meow_anim;
|
||||
|
||||
/* 每帧回调:v = 当前插值值(from + (to-from)*ease(t))。app 在此更新状态并绘制。 */
|
||||
typedef void (*meow_anim_update_fn)(meow_anim *a, float v, void *ctx);
|
||||
/* 完成/取消回调:canceled=1=被取消,0=自然完成。 */
|
||||
typedef void (*meow_anim_done_fn)(meow_anim *a, int canceled, void *ctx);
|
||||
|
||||
typedef struct meow_anim_desc {
|
||||
float from;
|
||||
float to;
|
||||
uint32_t duration_ms; /* 时长(ms);0 视为瞬发(下一 tick 完成) */
|
||||
meow_ease ease;
|
||||
meow_anim_update_fn update; /* 可 NULL */
|
||||
meow_anim_done_fn done; /* 可 NULL */
|
||||
void *ctx;
|
||||
} meow_anim_desc;
|
||||
|
||||
/* 启动一个动画(空闲槽;池满返回 NULL)。start 即置 value=from 并回调一次 update(0)。 */
|
||||
meow_anim *meow_anim_start(const meow_anim_desc *d);
|
||||
/* 取消(触发 done(canceled=1),不再 update)。 */
|
||||
void meow_anim_cancel(meow_anim *a);
|
||||
/* 查询:仍在运行(value 未达终点)。 */
|
||||
int meow_anim_active(meow_anim *a);
|
||||
/* 查询:当前插值值。 */
|
||||
float meow_anim_value(meow_anim *a);
|
||||
|
||||
/* 与脏区集成:动画每 tick 只 flush 影响区(x,y,w,h;x<0 表示不自动 flush)。
|
||||
* app 的 update 回调通常也会用 meow_ui_flush_region 自刷;设了这个则 tick 自动刷一次,
|
||||
* 保证「动画帧只标脏动画影响区,不整屏」。 */
|
||||
void meow_anim_set_region(meow_anim *a, int x, int y, int w, int h);
|
||||
|
||||
/* ---- 节拍器(挂在 on_tick / meow_ui_feed_tick;无动画零开销)---- */
|
||||
void meow_anim_tick(void); /* 推进所有活动动画(完成/取消在内部处理) */
|
||||
unsigned meow_anim_count(void); /* 活动动画数(0=空闲) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MEOW_UI_ANIM_H */
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* meow_ui_box.h — SDK 线性布局引擎(§12.1:meow_box)。
|
||||
*
|
||||
* 定位:既有的 meow_row/column/box(§5.8.5,W_LAYOUT)只支持「固定尺寸子项 + 居中」,
|
||||
* 本模块是其**独立增强**:竖直/水平容器,子项 = 固定尺寸 | weight 权重 | wrap(内容测量),
|
||||
* 支持 margin/padding / 主轴对齐(start/center/end/space-between/around/evenly)/ 交叉轴对齐
|
||||
* (start/center/end/stretch)/ 嵌套。
|
||||
*
|
||||
* 与绝对定位完全兼容:meow_box 是**纯布局计算器**,不是控件,不参与 z 序注册表/命中/绘制;
|
||||
* arrange 把每个子控件的 x/y/w/h 写进现有 meow_widget(用新增 meow_widget_set_rect),
|
||||
* 此后照常 draw/hit/flush_region/owner 闸门——与既有控件绝对定位零冲突。
|
||||
*
|
||||
* 与视图框架集成(opt-in):meow_box 可作 meow_view 的布局提供者(meow_view_set_layout);
|
||||
* view 不设就保持现有绝对坐标行为(§12.1.4)。
|
||||
*
|
||||
* 内存纪律:静态池 + 定长 items 数组(≥MEOW_BOX_MAX_CHILD),热路径(arrange)零 malloc;
|
||||
* 嵌套用深度≤MEOW_BOX_MAX_DEPTH 的静态栈单遍求解,无递归爆炸。
|
||||
*/
|
||||
#ifndef MEOW_UI_BOX_H
|
||||
#define MEOW_UI_BOX_H
|
||||
|
||||
#include "meow_ui_types.h" /* meow_widget 前向 + 基础类型(子头不引伞头,避免相对路径依赖) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct meow_box meow_box;
|
||||
|
||||
/* 主轴方向 */
|
||||
typedef enum {
|
||||
MEOW_BOX_H = 0, /* 横向(row) */
|
||||
MEOW_BOX_V = 1, /* 纵向(column) */
|
||||
} meow_box_dir;
|
||||
|
||||
/* 子项主轴尺寸策略 */
|
||||
typedef enum {
|
||||
MEOW_BOX_FIXED = 0, /* 固定尺寸:内容主轴向取控件当前 w/h */
|
||||
MEOW_BOX_WEIGHT = 1, /* 权重:均分剩余主轴空间(weight>0) */
|
||||
MEOW_BOX_WRAP = 2, /* wrap:按内容测量(min/preferred 或 measure 回调) */
|
||||
} meow_box_size;
|
||||
|
||||
/* 主轴对齐 */
|
||||
typedef enum {
|
||||
MEOW_BOX_ALIGN_START = 0,
|
||||
MEOW_BOX_ALIGN_CENTER = 1,
|
||||
MEOW_BOX_ALIGN_END = 2,
|
||||
MEOW_BOX_ALIGN_SPACE_BETWEEN = 3,
|
||||
MEOW_BOX_ALIGN_SPACE_AROUND = 4,
|
||||
MEOW_BOX_ALIGN_SPACE_EVENLY = 5,
|
||||
} meow_box_align;
|
||||
|
||||
/* 交叉轴对齐 */
|
||||
typedef enum {
|
||||
MEOW_BOX_CROSS_START = 0,
|
||||
MEOW_BOX_CROSS_CENTER = 1,
|
||||
MEOW_BOX_CROSS_END = 2,
|
||||
MEOW_BOX_CROSS_STRETCH = 3,
|
||||
} meow_box_cross;
|
||||
|
||||
/* 内容测量回调(size==MEOW_BOX_WRAP 时用;可 NULL):给出主轴向 min/preferred 尺寸。
|
||||
* ctx = meow_box_add_ex 的 mctx。 */
|
||||
typedef void (*meow_box_measure_fn)(void *ctx, int *min_main, int *pref_main);
|
||||
|
||||
/* 子项描述(add/add_ex/add_sub 提供;app 只读)。w 与 sub 二选一。 */
|
||||
typedef struct meow_box_item {
|
||||
meow_widget *w; /* 子控件(sub==NULL 时用) */
|
||||
meow_box *sub; /* 嵌套 box(w==NULL 时用) */
|
||||
int size; /* MEOW_BOX_* 尺寸策略 */
|
||||
int weight; /* size==WEIGHT 时>0 */
|
||||
int min; /* size==WRAP 的主轴下限 */
|
||||
int preferred;/* size==WRAP 的主轴目标 */
|
||||
meow_box_measure_fn measure; /* size==WRAP 内容测量(可 NULL) */
|
||||
void *mctx;
|
||||
} meow_box_item;
|
||||
|
||||
#define MEOW_BOX_MAX_CHILD 24 /* 每容器子项上限(静态数组) */
|
||||
#define MEOW_BOX_MAX_DEPTH 16 /* 嵌套深度上限(静态求解栈) */
|
||||
|
||||
/* ---- 生命周期(静态池;new 冷路径,arrange 热路径零 malloc)----
|
||||
* 注:命名用 meow_box_new(meow_box_create 已被 §5.8.5 的 W_LAYOUT box 占用)。 */
|
||||
meow_box *meow_box_new(meow_box_dir dir);
|
||||
void meow_box_free(meow_box *b);
|
||||
|
||||
/* ---- 容器配置 ---- */
|
||||
void meow_box_set_rect(meow_box *b, int x, int y, int w, int h); /* 容器矩形(绝对坐标) */
|
||||
void meow_box_set_padding(meow_box *b, int l, int t, int r, int btm);
|
||||
void meow_box_set_gap(meow_box *b, int gap);
|
||||
void meow_box_set_align(meow_box *b, int main_align, int cross_align);
|
||||
|
||||
/* ---- 子项添加(返回 0=成功;越界/无效=负值,不清空既有子项)---- */
|
||||
int meow_box_add(meow_box *b, meow_widget *w, int size, int weight);
|
||||
/* add_ex:WRAP 用 min/preferred(主轴向)+ 可选内容测量回调。 */
|
||||
int meow_box_add_ex(meow_box *b, meow_widget *w, int size, int weight,
|
||||
int min, int preferred, meow_box_measure_fn m, void *mctx);
|
||||
/* 嵌套子 box(parent 布局会为 sub 分配矩形并递归 arrange)。 */
|
||||
int meow_box_add_sub(meow_box *b, meow_box *sub, int size, int weight);
|
||||
|
||||
/* ---- 求解(单遍;深度≤MEOW_BOX_MAX_DEPTH 静态栈,无递归)----
|
||||
* 把每个子控件 x/y/w/h 写进其 meow_widget(meow_widget_set_rect);
|
||||
* 嵌套 sub 的矩形写进 sub 并递归。子控件的 margin(meow_widget_opts.margin_x/y)参与排布。 */
|
||||
void meow_box_arrange(meow_box *b);
|
||||
|
||||
/* ---- 查询 ---- */
|
||||
int meow_box_count(const meow_box *b);
|
||||
meow_widget *meow_box_widget_at(const meow_box *b, int idx); /* 子项控件(无则 NULL) */
|
||||
meow_box *meow_box_sub_at(const meow_box *b, int idx); /* 子项嵌套 box(无则 NULL) */
|
||||
void meow_box_rect(const meow_box *b, int out[4]); /* x,y,w,h */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MEOW_UI_BOX_H */
|
||||
@@ -26,6 +26,9 @@ int meow_img_w(meow_img *img);
|
||||
int meow_img_h(meow_img *img);
|
||||
|
||||
void meow_ui_img(int x, int y, meow_img *img); /* 原始尺寸 */
|
||||
/* 内存瘦身:最近邻等比缩放到最长边 ≤maxdim,返回新图;原图已 ≤maxdim 返回 NULL。
|
||||
* 调用方负责 free 旧图与返回值(若返回)。封面/背景大图驻留内存瘦身用。 */
|
||||
meow_img *meow_img_downscale(meow_img *img, int maxdim);
|
||||
void meow_ui_img_scaled(int x, int y, int w, int h, meow_img *img); /* 最近邻缩放 */
|
||||
void meow_ui_img_alpha(int x, int y, int w, int h, meow_img *img, int alpha);
|
||||
void meow_ui_img_cover(int x, int y, int size, meow_img *img); /* 居中裁方 → size×size */
|
||||
|
||||
@@ -58,6 +58,60 @@ void meow_ui_set_long_press_cb(meow_long_press_fn cb); /* 注册/更换回调
|
||||
void meow_ui_set_long_press_ms(int ms); /* 长按阈值(ms);<=0 恢复默认 500 */
|
||||
int meow_ui_long_press_ms(void); /* 当前阈值(默认 500) */
|
||||
|
||||
/* ============================================================ */
|
||||
/* §6.4 事件分发形式化(2026-09-02)—— 统一「命中测试 / 捕获 / 消费 / 层间隔离 / 焦点」
|
||||
*
|
||||
* 背景:此前命中/捕获/消费/层间隔离各处 ad-hoc 补丁(模式层穿透、弹层叠黑、list 焦点残留、
|
||||
* 同坐标二次消费)。本节把三层模型的形式化落地为**单一仲裁者**(SDK 内部实现,见
|
||||
* devdocs/plan/SDK_VIEW_FRAMEWORK_DESIGN.md §A.7 命中分流 ③②① + 本 SDK 内部拓扑):
|
||||
*
|
||||
* 触摸沿 z 序**自顶向下**命中:模态层永远先审;某一层命中即消费(返回 consumed 才继续下探)。
|
||||
* 某一次 touch-down 命中后,捕获直到 up;期间 move/up 只发给捕获目标(防滑出误触发下层)。
|
||||
* 模态层存在时下层**完全收不到**事件——未命中面板的事件由模态背板消费,不透传。
|
||||
*
|
||||
* 兼容:**只追加、不删改既有签名**;未调用本节 API 的 App 行为与之前完全一致(命中/捕获仍
|
||||
* 由 App 在 on_tap/on_touch_* 里自理)。hello/files/ncm/reader 等既有 App 只把 SDK 提供的
|
||||
* 语义用于收敛 bug,不改正常交互。
|
||||
*/
|
||||
/* ---- 模态作用域(modal scope)----
|
||||
* 一组自顶向下优先的叠层。dialog/sheet/App 自绘模态在「打开时 begin、关闭时 end」。
|
||||
* 作用域存在(meow_ui_modal_active / depth>0)时,下层(view/widget)完全收不到触摸;
|
||||
* 未命中面板的事件由背板消费(meow_ui_hit_topdown 恒返回模态哨兵)。支持嵌套(弹层叠开,
|
||||
* depth 递增)。begin 返回作用域句柄;end 销栈(幂等,NULL 忽略)。 */
|
||||
typedef struct meow_ui_modal meow_ui_modal;
|
||||
meow_ui_modal *meow_ui_modal_begin(void); /* 打开模态层入栈;返回句柄(NULL=栈满/上限) */
|
||||
void meow_ui_modal_end(meow_ui_modal *m); /* 关闭:弹到 m(含 m,一次性关上嵌套) */
|
||||
int meow_ui_modal_active(void); /* 当前是否有任一模态作用域打开(depth>0) */
|
||||
int meow_ui_modal_depth(void); /* 模态栈深(弹层叠开计数) */
|
||||
|
||||
/* ---- 自上而下命中 ---- */
|
||||
/* 沿 z 序(模态最高优先,其次注册控件 z 降序;均含 owner==active+enable 过滤)返回第一个
|
||||
* 命中绘制物(meow_widget* 或 meow_view*);无命中返回 NULL。模态存在时恒返回模态哨兵
|
||||
* (背板消费,不透传)。供 gesture_begin/focus_tap/App 自绘模态命中统一使用。 */
|
||||
void *meow_ui_hit_topdown(int x, int y);
|
||||
/* meow_widget_hit 的公共别名(owner==active + enable + 矩形/自定义命中回调一致)。 */
|
||||
int meow_ui_widget_hit(meow_widget *w, int x, int y);
|
||||
|
||||
/* ---- 手势捕获(gesture capture)----
|
||||
* touch-down 命中目标捕获整个手势直到 up。捕获期 meow_ui_gesture_owner 恒返回捕获目标;
|
||||
* 后续 move/up 只发给它(防滑出后误触发下层)。begin 返回捕获目标(未命中=NULL 不捕获);
|
||||
* end/抬手释放。 */
|
||||
void *meow_ui_gesture_begin(int x, int y); /* 命中+捕获;返回捕获目标(模态存在时=模态哨兵) */
|
||||
void *meow_ui_gesture_owner(void); /* 当前手势捕获目标(无=NULL) */
|
||||
void meow_ui_gesture_end(void); /* 手势结束(抬手/TAP/SWIPE 边沿):释放捕获 */
|
||||
|
||||
/* ---- 唯一焦点(focus,root 根治 list 焦点残留 / 滚动容器间转移)----
|
||||
* 焦点持有者唯一。点非焦点区域 → 释放焦点并触发 lost 回调;滚动容器(list/scroll)在
|
||||
* 获得焦点时 acquire,点外由 meow_ui_focus_tap 统一释放——「命中非 focus 区域 → 释放并通知」。
|
||||
* 转移规则:某滚动容器 acquire 后,随后的纵向 swipe / 拖动滚该容器;任何落在该容器外的
|
||||
* 触摸(hit != focus owner)释放焦点,回退到页面级滚动。 */
|
||||
typedef void (*meow_ui_focus_lost_fn)(void *owner, void *ctx); /* 焦点被释放/转移时回调 */
|
||||
void meow_ui_focus_set_lost_cb(meow_ui_focus_lost_fn cb, void *ctx); /* 注册/更换焦点丢失回调 */
|
||||
void *meow_ui_focus_owner(void); /* 当前唯一焦点持有者(无=NULL) */
|
||||
int meow_ui_focus_acquire(void *owner); /* 设为唯一焦点(覆盖旧焦点并触发其 lost) */
|
||||
int meow_ui_focus_release(void *owner); /* owner==当前焦点才释放+通知(NULL=任意) */
|
||||
void meow_ui_focus_tap(int x, int y); /* TAP 落点:命中焦点持有者→保位;否则释放+通知 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* meow_ui_scroll.h — SDK 滚动物理(§12.3:meow_scroll)。
|
||||
*
|
||||
* 定位:给既有滚动容器(W_LIST / W_LISTVIEW / LazyColumn / LazyRow)加**可惯性滚动**的
|
||||
* **物理层**——速度跟踪(最近 N 个采样加权)、松手 fling(减速度曲线,用 §12.2 动画基座驱动)、
|
||||
* 边界过冲 clamp + 简单回弹(不做复杂 spring)、滚动停止可选 snap。**跟手拖动行为保持现状
|
||||
* 不变**(track 内部调既有 set_scroll,clamp 一致)。
|
||||
*
|
||||
* 设计:meow_scroll 是**滚动会话**,包住一个滚动控件(或任意的 set/max/get/redraw 回调)。
|
||||
* 拖动态:app 在 on_touch_move 里把位移喂给 meow_scroll_track(dy, t)(等价于 app 直接调
|
||||
* meow_list_scroll_by,且额外记录速度采样);松手:app 调 meow_scroll_fling(s),内部用
|
||||
* 加权速度采样得出初速 → 起一条 ease-out 动画推进位移 → 每帧只 redraw(flush 列表视口区)。
|
||||
*
|
||||
* 内存纪律:静态池(应用侧按需创建会话),track/fling/tick 全程零 malloc;无动画时
|
||||
* meow_scroll 不参与节拍(fling 由 meow_anim_tick 驱动,活动计数为 0 则零开销)。
|
||||
*/
|
||||
#ifndef MEOW_UI_SCROLL_H
|
||||
#define MEOW_UI_SCROLL_H
|
||||
|
||||
#include "meow_ui_types.h" /* meow_widget 前向 + 基础类型(子头不引伞头,避免相对路径依赖) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct meow_scroll meow_scroll;
|
||||
|
||||
/* ---- 通用回调(wrap 之外的自定义滚动源用)---- */
|
||||
typedef void (*meow_scroll_set_fn)(void *ctx, int off);
|
||||
typedef int (*meow_scroll_max_fn)(void *ctx);
|
||||
typedef int (*meow_scroll_get_fn)(void *ctx);
|
||||
typedef void (*meow_scroll_redraw_fn)(void *ctx); /* 只刷滚动视口区(不整屏) */
|
||||
|
||||
/* 创建会话:app 提供 set/max/get/redraw。返回 NULL=池满。 */
|
||||
meow_scroll *meow_scroll_create(meow_scroll_set_fn set, meow_scroll_max_fn max,
|
||||
meow_scroll_get_fn get, meow_scroll_redraw_fn redraw,
|
||||
void *ctx);
|
||||
/* 便捷:包一个 meow_widget 列表(is_listview:1=W_LISTVIEW / 0=W_LIST 或 lazycolumn/row)。
|
||||
* redraw 只 flush 该控件矩形(视口区)。 */
|
||||
meow_scroll *meow_scroll_wrap(meow_widget *list, int is_listview);
|
||||
void meow_scroll_free(meow_scroll *s);
|
||||
|
||||
/* 拖动跟手 + 速度采样:dy=本次位移(px);t_ms=采样时刻(单调毫秒)。
|
||||
* 内部 set_scroll(pos+dy)(clamp 到 [0,max],与 app 直接 scroll_by 行为一致)。 */
|
||||
void meow_scroll_track(meow_scroll *s, int dy, uint64_t t_ms);
|
||||
|
||||
/* 松手 fling:内部用「最近 N 个采样加权」算初速,起减速度曲线动画推进位移;
|
||||
* 边界过冲 clamp + 简单回弹;每帧只 redraw 视口区。停止后可选 snap。 */
|
||||
void meow_scroll_fling(meow_scroll *s);
|
||||
/* 立即停止(取消 fling/回弹/snap,停在当前 offset)。 */
|
||||
void meow_scroll_stop(meow_scroll *s);
|
||||
|
||||
/* 当前加权初速(px/s;为 fling 内部所用,供 app 读取/调试)。 */
|
||||
int meow_scroll_velocity(meow_scroll *s);
|
||||
|
||||
/* 查询/配置 */
|
||||
int meow_scroll_active(meow_scroll *s); /* 是否有活动 fling/回弹/snap */
|
||||
int meow_scroll_offset(meow_scroll *s); /* 当前 scroll(get) */
|
||||
void meow_scroll_set_snap(meow_scroll *s, int step); /* >0=fling 停止后吸附到 step 倍数 */
|
||||
void meow_scroll_set_friction(meow_scroll *s, int tau_ms); /* 摩擦时间常数(默认 180ms) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MEOW_UI_SCROLL_H */
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* meow_ui_str.h — SDK 字符串资源(i18n 雏形,§13.meow_str_*)。
|
||||
*
|
||||
* 定位:公开 SDK 前,系统/App UI 文案不得再硬编码在 C 源码里——第三方开发者必须能按
|
||||
* 系统 locale 拿到对应语言文案,且能在不改 SDK 二进制的情况下用 TF 卡覆盖/追加。
|
||||
* 本头声明字符串资源框架的**对外 API**(追加式,既有 App 零改动)。
|
||||
*
|
||||
* 单表双语内置(zh_cn = 内置默认 / en_us),四层取值优先级(见 meow_ui_str.c):
|
||||
* meow_str(id):按当前 locale 取串;override 覆盖表 > 内嵌当前语言 > 内嵌内置默认(zh_cn);
|
||||
* 全程不可得则原样返回 id(调用方永不见 NULL)。
|
||||
* meow_strf(out,outsz,id,...):取串后按 snprintf 语义格式化进调用方缓冲(自带 NUL 终止)。
|
||||
* meow_str_set_locale(locale):切当前 locale("zh_cn"|"en_us"),即时生效 + 重载 TF 覆盖表
|
||||
* + best-effort 持久化到板载 settings.conf 的 ui.locale。
|
||||
*
|
||||
* 依赖:纯 libc(stdio/stdlib/string/stdarg),宿主 gcc 可直接编译单测;不依赖其它 SDK 对象。
|
||||
* - locale 初值:启动首次调用惰性读系统设置 settings.conf 的 `ui.locale`,缺省 "zh_cn"。
|
||||
* - TF 覆盖表:`<MEOW_DATA_DIR>/../strings/<locale>.txt`(即 MeowData/<pkg>/strings/,见
|
||||
* §9.2 数据目录约定),`id=text` 行格式 UTF-8;无卡/无文件/不含该 id → 内嵌表兜底。
|
||||
* - 热路径(meow_str)零 malloc:内嵌为编译期静态表,覆盖表为启动加载的静态数组。
|
||||
*
|
||||
* 边界(§13 明示不做,写清理由):
|
||||
* 不做复数规则 / BiDi / RTL / 动态字体回退——当前形态是「按 locale 取整串」的 i18n 雏形,
|
||||
* 面向 480×720 单行/短文案 UI;复数变体需占位符格式化协议,BiDi/RTL 需文本整形 + 布局镜像,
|
||||
* 两者都超出「字符串资源外置」的最小必要范围,留待后续批次。
|
||||
*/
|
||||
#ifndef MEOW_UI_STR_H
|
||||
#define MEOW_UI_STR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 按当前 locale 取 id 对应的文案。id 形如 `域.名`(common.ok / player.pause)。
|
||||
* 返回静态字符串(内嵌表或覆盖表;永不返回 NULL)。未知 id 原样返回 id。 */
|
||||
const char *meow_str(const char *id);
|
||||
|
||||
/* 取 id 文案后按 snprintf 语义格式化进 out(outsz 为缓冲字节数,含 NUL)。
|
||||
* 返回 snprintf 样式的「应写入字符数」(不截断);out==NULL 或 outsz<=0 返回 -1。
|
||||
* 设计理由:调用方自带缓冲,避免静态/线程局部缓冲在 IME/模态等重入路径的竞态,
|
||||
* 且与 SDK 既有 snprintf 习惯一致(无格式参数时等价深拷贝 meow_str 结果)。 */
|
||||
int meow_strf(char *out, int outsz, const char *id, ...);
|
||||
|
||||
/* 设当前 locale(识别 "zh_cn"|"en_us";任意串作为覆盖表文件名 + 内嵌按非 en 处理为内置默认)。
|
||||
* 即时生效(下次 meow_str 即按新 locale);重载该 locale 的 TF 覆盖表;
|
||||
* best-effort 持久化到 settings.conf 的 ui.locale(失败静默,运行时仍切换)。
|
||||
* 须在 App 主线程(UI 线程)调用,避免与 meow_str 并发写覆盖表。 */
|
||||
void meow_str_set_locale(const char *locale);
|
||||
|
||||
/* 当前生效 locale(内部缓冲;未初始化时读 settings 后返回,默认 "zh_cn")。 */
|
||||
const char *meow_str_locale(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* MEOW_UI_STR_H */
|
||||
@@ -33,6 +33,8 @@ void meow_widget_free(meow_widget *w);
|
||||
|
||||
void meow_widget_draw(meow_widget *w); /* 每次 flush 前调用 */
|
||||
int meow_widget_hit(meow_widget *w, int x, int y); /* 点是否落在控件内 */
|
||||
/* 写控件矩形(§12.1 meow_box 布局引擎用;也可供 app 布局器用)。只设字段不标脏。 */
|
||||
void meow_widget_set_rect(meow_widget *w, int x, int y, int wd, int ht);
|
||||
|
||||
void meow_slider_set(meow_widget *s, int val);
|
||||
int meow_slider_get(meow_widget *s);
|
||||
@@ -184,6 +186,29 @@ void meow_topappbar_set_back(meow_widget *w, int on); /* 1=显示返回箭头
|
||||
int meow_topappbar_add_action(meow_widget *w, const char *label); /* 返回动作下标 */
|
||||
#define MEOW_TOPBAR_BACK (-2)
|
||||
int meow_topappbar_hit(meow_widget *w, int x, int y); /* MEOW_TOPBAR_BACK=返回 idx>=0=动作 -1=无 */
|
||||
/* TopAppBar 位图动作图标(sb_icons[],Material Symbols Rounded 32x32 单通道 alpha,Apache-2.0)。
|
||||
* 动作项默认文本(add_action);经本 API 把某项改成位图:绘制取主题 onSurface(按压淡色),
|
||||
* 与状态栏同源 blit(ink 垂直对齐栏中点)。返回 0=成功;NULL/非 topbar/越界 idx/非法 icon=负值。 */
|
||||
int meow_topappbar_set_item_icon(meow_widget *w, int idx, int icon_idx);
|
||||
/* 位图动作图标索引(= sb_icons[] 下标,与 SDK sb_icons.h 的 SB_I_* 同值)。
|
||||
* 状态栏占用 0-14(不动);动作图标从 15 起连续追加,勿改序(须与 sb_icons.h 表序一致)。 */
|
||||
enum {
|
||||
MEOW_ICON_SETTINGS = 15,
|
||||
MEOW_ICON_REFRESH = 16,
|
||||
MEOW_ICON_SEARCH = 17,
|
||||
MEOW_ICON_PLAY_ARROW = 18,
|
||||
MEOW_ICON_PAUSE = 19,
|
||||
MEOW_ICON_SKIP_NEXT = 20,
|
||||
MEOW_ICON_SKIP_PREV = 21,
|
||||
MEOW_ICON_ARROW_BACK = 22,
|
||||
MEOW_ICON_CLOSE = 23,
|
||||
MEOW_ICON_ADD = 24,
|
||||
MEOW_ICON_CHECK = 25,
|
||||
MEOW_ICON_LYRICS = 26,
|
||||
MEOW_ICON_QUEUE_MUSIC = 27,
|
||||
MEOW_ICON_DOWNLOAD = 28,
|
||||
MEOW_ICON_HEART = 29,
|
||||
};
|
||||
|
||||
/* ---- NavigationBar(底部导航栏)---- */
|
||||
meow_widget *meow_navigationbar_create(int x, int y, int w, int h);
|
||||
@@ -291,6 +316,65 @@ void meow_listview_set_on_tap(meow_widget *lv, meow_listview_tap_fn cb, void *ct
|
||||
/* 命中行:置选中 + 回调(若设)+ 返回 idx;未命中返回 -1。 */
|
||||
int meow_listview_tap_at(meow_widget *lv, int x, int y);
|
||||
|
||||
/* ============================================================ */
|
||||
/* §5.5 虚拟化列表(W_LISTVIEW 扩展层,2026-09-02):固定 item 池 + 多行富 item + 完全自绘
|
||||
* ------------------------------------------------------------
|
||||
* 在既有 W_LISTVIEW(src2 每帧按需取行,行为不变)之上做**虚拟化层**(API 追加式,旧 API 保留):
|
||||
* - 数据源:count_fn() 返回总行数(任意长度,≥65535 不常驻 item 对象);
|
||||
* bind_fn(index, item, ctx) 仅在行「进入视口」(绑定到固定池槽)时调用一次;
|
||||
* - 固定 item 池:池容量 = 视口行数 + 2 静态槽(有界,见实现 MEOW_LV_POOL_MAX);
|
||||
* 行离开视口不销毁,回滚不重绑(同一 index 命中同一槽 → bind 不重调);
|
||||
* - 滚动只改 viewport 偏移(复用既有 set_scroll/max_scroll),不重绑未进视口的项;
|
||||
* - 多行富 item:主标题+副标题(第二行小字)+左图标/缩略图+右尾件(chevron/开关/复选/⋯);
|
||||
* 行高可配(set_item_h 精确 px / set_item_tier 单/双行档位默认高);
|
||||
* - 默认 renderer 用主题语义色绘制富 item;App 也可经 set_item_draw 完全自绘。
|
||||
* 段头:bind 回调把 item->section=1(title=段名)→ 段头占位行(非粘性),默认 renderer 特殊绘制。
|
||||
* 空态:set_empty_text 设置文案,count==0 时视口内居中画出。
|
||||
* 兼容:既有 meow_listview_*(src2 模式)全部保留不动;本层为叠加,src2==NULL 时走既有路径。 */
|
||||
|
||||
/* 虚拟化行 item(bind 回调填充;SDK 固定池持有;不常驻 src2 那样的全量行对象)。 */
|
||||
typedef struct meow_lv_item {
|
||||
const char *title; /* 主标题(必填,NULL 视为空行) */
|
||||
const char *subtitle; /* 副标题(第二行小字),可空 */
|
||||
const meow_img *icon; /* 可选:左图标/缩略图(icon_kind==MEOW_LIST_ICON_IMG 时用) */
|
||||
int icon_kind; /* MEOW_LIST_ICON_*(NONE=无图标) */
|
||||
int right; /* MEOW_LIST_RIGHT_* 右尾件 */
|
||||
int on; /* right==SWITCH 时开关态(0/1) */
|
||||
int enabled; /* 1=可交互;0=变淡不响应 */
|
||||
int section; /* 1=段头占位行(title=段名;默认 renderer 特殊绘制,非粘性) */
|
||||
void *user; /* App 私有(跨 bind 保存业务态/图/index;SDK 不碰) */
|
||||
} meow_lv_item;
|
||||
|
||||
/* 虚拟化数据源:count 返回当前行数(>=0,任意长);bind 在行进入视口时被调一次填充 item。
|
||||
* 二者均不常驻 item 对象;count 每帧实时查(支持搜索过滤/懒加载动态长度)。 */
|
||||
typedef int (*meow_listview_count_fn)(void *ctx);
|
||||
typedef void (*meow_listview_bind_fn)(int index, meow_lv_item *item, void *ctx);
|
||||
|
||||
/* 完全自绘回调(覆盖默认 renderer):idx=行号;x,y,w,h=行视口矩形(已裁剪到列表视口);
|
||||
* state=MEOW_LISTVIEW_ST_* 状态位(选中/按压/禁用组合)。App 用 §3 绘制 API 自绘整行。 */
|
||||
typedef void (*meow_listview_draw_fn)(int idx, int x, int y, int w, int h,
|
||||
int state, void *ctx);
|
||||
/* state 位(set_item_draw 的 draw 回调收到;选中/按压/禁用组合,供自绘整行)。 */
|
||||
#define MEOW_LISTVIEW_ST_SELECTED (1u<<0)
|
||||
#define MEOW_LISTVIEW_ST_PRESSED (1u<<1)
|
||||
#define MEOW_LISTVIEW_ST_DISABLED (1u<<2)
|
||||
|
||||
/* 挂虚拟化数据源:切到 pool 模式(count_fn/bind_fn 均非 NULL 才生效;否则回退 src2 模式)。
|
||||
* 返回 0=成功;NULL 回调/无效=负值。挂虚拟源后既有 sel/滚动/命中/焦点照常。 */
|
||||
int meow_listview_set_vsource(meow_widget *lv, meow_listview_count_fn count,
|
||||
meow_listview_bind_fn bind, void *ctx);
|
||||
/* 默认 renderer 配置:lines=1/2(单行/双行档位,影响副标题显示与行高默认);
|
||||
* show_icon=1 画左图标/缩略图;show_right=1 画右尾件。返回 0=成功。 */
|
||||
int meow_listview_set_item_renderer(meow_widget *lv, int lines, int show_icon,
|
||||
int show_right);
|
||||
/* 行档位默认行高:lines=1→48(单行)、2→56(双行);与 set_item_h(精确 px)互补。 */
|
||||
int meow_listview_set_item_tier(meow_widget *lv, int lines);
|
||||
/* 完全自绘:设 draw_item 回调(覆盖默认 renderer);NULL=用默认 renderer。返回 0=成功。 */
|
||||
int meow_listview_set_item_draw(meow_widget *lv, meow_listview_draw_fn draw,
|
||||
void *ctx);
|
||||
/* 空态占位:count==0 时视口内居中画 empty_text(NULL 不画)。返回 0=成功。 */
|
||||
int meow_listview_set_empty_text(meow_widget *lv, const char *text);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user