Files
MeowOS-For-R3P2/patch_v2/sdk/include/meow_ui_widgets.h
T
AskaEth 3d70a3dd2c feat: M6.10–M6.19 批量收编 + M6.19 推卡验收
- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘)
- OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复
- ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640
- 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫)
- 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
2026-09-03 12:16:01 +08:00

412 lines
27 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_widgets.h — SDK 控件层(§5 控件)+ 控件层升级(§5.8 基座)+ Material 3 组件子集(§5.8.6)
* + 结构化列表 W_LISTVIEW(§5.5)。
*
* 原 meow_ui.h 拆分的一部分(widgets 模块)。依赖 meow_ui_theme.h(meow_theme/MD3 色板/风格参数)
* 与 meow_ui_ime.h(meow_ime_mode,TextField 接 IME);meow_img 为不透明句柄(meow_ui_types.h)。
* 向后兼容:既有 create 签名一字不改,只在上面扩展(Options/状态机走新增挂载器)。
*/
#ifndef MEOW_UI_WIDGETS_H
#define MEOW_UI_WIDGETS_H
#include "meow_ui_types.h"
#include "meow_ui_theme.h"
#include "meow_ui_ime.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §5 控件层 */
/* ============================================================ */
typedef struct meow_widget meow_widget;
meow_widget *meow_btn_create(int x, int y, int w, int h, const char *label);
meow_widget *meow_slider_create(int x, int y, int w, int min, int max, int val);
meow_widget *meow_switch_create(int x, int y, int on);
/* 列表数据源回调:idx 有效时填 label 并返回 1;越界返回 0([D2] 定案签名) */
typedef int (*meow_list_source)(int idx, char *label, int len, void *ctx);
meow_widget *meow_list_create(int x, int y, int w, int h, int count,
meow_list_source src, void *ctx);
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);
void meow_switch_set(meow_widget *w, int on);
int meow_switch_get(meow_widget *s);
int meow_btn_pressed(meow_widget *w); /* 应用在 on_tap 命中后标记按下 */
/* ============================================================ */
/* §5.8 控件层升级(第一批=通用基座):Options / 状态机 / 自定义画布 / 布局 */
/* ============================================================ */
/* ---- §5.8.2 Modifier 式通用 Options(轻量结构体,非链式 DSL)----
* 经 meow_widget_set_opts 一次性挂载,作用于任意控件(标准/自定义)。全部控件共用。
* 哨兵语义:bg/fg==0=用控件/主题默认;stroke==0=无描边;stroke_w=描边宽;
* radius==-1=控件默认(如按钮 10),>=0=指定圆角(0=直角);pad/margin=0=无;
* disabled/selected=1=置位(立即反映到状态机位)。 */
typedef struct meow_widget_opts {
uint32_t bg; /* 背景色(0=控件/主题默认) */
uint32_t fg; /* 前景/文字(0=主题 onSurface) */
uint32_t stroke; /* 描边色(0=无描边) */
int stroke_w; /* 描边宽(px) */
int radius; /* 圆角(px;-1=控件默认,如按钮 10) */
int pad_x; /* 内边距(水平,px) */
int pad_y; /* 内边距(垂直,px) */
int margin_x; /* 外边距(水平,px;布局用) */
int margin_y; /* 外边距(垂直,px;布局用) */
int disabled; /* 1=禁用(视觉变暗 + 不响应命中,见状态机 §5.8.3) */
int selected; /* 1=选中(列表高亮/勾选,见状态机 §5.8.3) */
} meow_widget_opts;
/* 挂载:作用于任意控件(标准/自定义)。w 内部浅拷这份 opts。
* 返回 0=成功;NULL/无效=负值(不销毁 w)。 */
int meow_widget_set_opts(meow_widget *w, const meow_widget_opts *opts);
/* 取回当前 opts(浅拷到 out;0=成功)。自定义画布用它读通用修饰。 */
int meow_widget_opts_get(const meow_widget *w, meow_widget_opts *out);
/* ---- §5.8.3 统一状态机(enabled / selected / focused / pressed)----
* 标准/自定义控件共用;visual 层由 SDK/App 按状态位叠。enabled=0 阻断 hit/pressed。 */
#define MEOW_WS_ENABLED (1u<<0)
#define MEOW_WS_SELECTED (1u<<1)
#define MEOW_WS_FOCUSED (1u<<2)
#define MEOW_WS_PRESSED (1u<<3)
/* 设/查状态(置位/清位,其它位不动)。on=1 置位 / 0 清位。 */
void meow_widget_set_state(meow_widget *w, unsigned bits, int on);
unsigned meow_widget_state(const meow_widget *w);
/* 便捷:禁用/启用、选中/取消(单态等效于 set_state)。 */
int meow_widget_enabled(const meow_widget *w);
void meow_widget_set_enabled(meow_widget *w, int on);
int meow_widget_selected(const meow_widget *w);
void meow_widget_set_selected(meow_widget *w, int on);
/* 一键叠状态层(自定义画布可选):把 pressed/focused/disabled/selected 的视觉层
* 叠到 w 的矩形上(半透明状态层 + 焦点描边)。标准控件由 SDK 自动叠,无需调用;
* 自定义画布在 render_cb 里画完内容后可调它(App 也可据 meow_widget_state 自行叠)。 */
void meow_widget_draw_state_layer(meow_widget *w, const meow_theme *th);
/* ---- §5.8.1 自定义画布(App 提供 render/hit 回调;同一个 meow_widget)----
* render:SDK 在 meow_widget_draw 时调用,th=当前生效主题(MD3 语义色板);
* w 的 x/y/w/h 已就位;App 用 §3/§4 绘制 API 自绘(往 back_buf 画)。
* hit :命中判定,App 自定义(如圆形/区域外镂空);返回 1=命中。 */
typedef void (*meow_widget_render_fn)(meow_widget *w, const meow_theme *th, void *ctx);
typedef int (*meow_widget_hit_fn)(meow_widget *w, int x, int y, void *ctx);
/* 创建:自定义画布(x,y,w,h = 绝对坐标,同既有控件)。
* 生命周期/Activity 归属:创建时绑定当前 active Activity(同 meow_btn_create,§6.1 ①);
* 命中走 hit_cb(先过 owner==active + enabled 双闸门)。 */
meow_widget *meow_widget_custom_create(int x, int y, int w, int h,
meow_widget_render_fn render_cb,
meow_widget_hit_fn hit_cb,
void *ctx);
/* ---- §5.8.5 可组合布局(Row / Column / Box + Spacer)----
* 布局容器 = meow_widget(W_LAYOUT);arrange 把子控件算成绝对坐标(写进各 child 的
* x/y/w/h)→ 与现有绝对定位完全兼容(draw/hit/flush_region/owner 闸门照常)。
* 本批先支持固定尺寸子项(w/h 均已知);弹性(w/h==0)为后续增强。 */
enum { MEOW_LAYOUT_ROW = 0, MEOW_LAYOUT_COLUMN = 1, MEOW_LAYOUT_BOX = 2 };
meow_widget *meow_row_create(int x, int y, int w, int h, int spacing);
meow_widget *meow_column_create(int x, int y, int w, int h, int spacing);
meow_widget *meow_box_create(int x, int y, int w, int h);
/* 添加子控件(子可为普通控件/自定义/另一布局/Spacer)。返回 0=成功;无效=负值。 */
int meow_layout_add(meow_widget *layout, meow_widget *child);
/* 计算子控件绝对坐标(写入各 child 的 x,y,w/h;嵌套布局递归);此后照常 draw/hit。 */
void meow_layout_arrange(meow_widget *layout);
/* 固定尺寸空白(也作撑余量;不可见,hit 恒 0)。 */
meow_widget *meow_layout_spacer(int w, int h);
/* ============================================================ */
/* §5.8.6 Material 3 组件子集(第二批,基于第一批基座:Options + 状态机 + MD3 色板 + 布局)
* 每个组件 = 新增 meow_widget 类型或组合既有模板的便捷函数;复用主题语义色(th->primary /
* surfaceContainer / outline / ...)+ 风格参数(radius/radius_card/spacing/stroke_w)+ 通用
* Options(meow_widget_set_opts 对它们同样生效)+ 状态机(enabled/selected/pressed/focused)。
* 向后兼容:既有 create 签名一字不改;本批只在其上扩展。 */
/* ============================================================ */
/* ---- Button 五型(meow_btn 扩展;既有 meow_btn_create = FILLED)---- */
enum {
MEOW_BTN_FILLED = 0, /* primary 底 / onPrimary 文 */
MEOW_BTN_TONAL = 1, /* secondaryContainer 底 / onSecondaryContainer 文 */
MEOW_BTN_OUTLINED = 2, /* 透明底 / primary 文 / primary 描边 */
MEOW_BTN_TEXT = 3, /* 透明底 / primary 文 / 无描边 */
MEOW_BTN_ELEVATED = 4, /* surfaceContainerLow 底 / primary 文 */
};
meow_widget *meow_btn_create_variant(int x, int y, int w, int h, const char *label, int variant);
int meow_btn_set_variant(meow_widget *w, int variant); /* 越界 clamp;0=成功 */
/* ---- TextField(单行文本输入,接 IME §5.1)---- */
/* placeholder=提示文案;buf=App 持有的文本缓冲(组件不回拷,只绘制/编辑其上);maxlen=含 NUL 预算 */
meow_widget *meow_textfield_create(int x, int y, int w, int h, const char *placeholder,
char *buf, int maxlen, meow_ime_mode mode);
void meow_textfield_set_placeholder(meow_widget *w, const char *placeholder);
/* 聚焦并打开**阻塞** IME(同 meow_ui_text_input 内层轮询);回车不关闭键盘,ESC/点背景关闭。
* 内容经 on_change 实时同步到 w->buf(返回值关闭路径为 0,提交不依赖返回值回填)。 */
int meow_textfield_activate(meow_widget *w);
const char *meow_textfield_text(meow_widget *w);
/* ---- Card(圆角容器卡片;surfaceContainerLow 底 + 可选描边/状态层)---- */
meow_widget *meow_card_create(int x, int y, int w, int h);
/* 内容子控件:绘制时递归绘到卡片内(卡片 hit 仍为矩形;子控件独立命中) */
void meow_card_set_content(meow_widget *card, meow_widget *child);
/* ---- Divider(分隔线;vertical=1 纵向)---- */
meow_widget *meow_divider_create(int x, int y, int len, int vertical);
/* ---- Badge(角标;count=0 红点 / >0 数字 / <0 隐藏;cx,cy=锚点=角标中心)---- */
meow_widget *meow_badge_create(int cx, int cy);
void meow_badge_set(meow_widget *w, int count);
/* ---- Checkbox / Radio(勾选态走 meow_widget_set_selected/meow_widget_selected)---- */
meow_widget *meow_checkbox_create(int x, int y);
meow_widget *meow_radio_create(int x, int y);
/* ---- ProgressBar(线性/圆形;value=0-100 确定性,-1=不定)---- */
meow_widget *meow_progress_create(int x, int y, int w, int h, int value); /* 线性 */
meow_widget *meow_progress_circular_create(int cx, int cy, int r, int value); /* 圆形 */
void meow_progress_set(meow_widget *w, int value); /* -1=不定 */
/* ---- FloatingActionButton(悬浮按钮;圆角胶囊,无投影仅状态层近似)---- */
meow_widget *meow_fab_create(int x, int y, int size, const char *label);
/* ---- TopAppBar(顶部标题栏:标题 + 返回 + 动作)---- */
meow_widget *meow_topappbar_create(int x, int y, int w, int h, const char *title);
void meow_topappbar_set_title(meow_widget *w, const char *title);
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,
};
/* ---- IconButton(圆形/位图图标按钮,M7.0a 缺口#2)----
* 圆形命中 + 位图图标(sb_icons[],Material Symbols Rounded 单通道 alpha)+ 按压态(实时)。
* 用途:电源菜单圆钮 / Now Playing 播放控制 / 锁屏常用件等「位图图标 + 圆形」按钮。
* icon_idx = sb_icons[] 下标(用上面 MEOW_ICON_* 枚举或 SB_I_*;越界画空位图,命中照常)。
* size = 按钮直径(外接正方形 w=h=size;图标 ink 高 = size*6/10,MD3 图标比)。
* 语义色:底 surfaceContainerLow、图标 onSurface;按压叠 onSurface 状态层(实时,同 meow_btn);
* 禁用变淡;选中态 primaryContainer/onPrimaryContainer(meow_widget_set_selected)。
* 命中:圆形(半径=size/2,圆心=按钮中心),owner==active + enabled 双闸门。
* 返回按钮句柄;App 在 on_tap 里用 meow_widget_hit 判定是否命中本钮(命中即触发动作)。 */
meow_widget *meow_iconbtn_create(int x, int y, int size, int icon_idx);
/* ---- NavigationBar(底部导航栏)---- */
meow_widget *meow_navigationbar_create(int x, int y, int w, int h);
int meow_navigationbar_add_item(meow_widget *w, const char *label);
void meow_navigationbar_set_selected(meow_widget *w, int idx);
int meow_navigationbar_selected(meow_widget *w);
int meow_navigationbar_hit(meow_widget *w, int x, int y); /* 返回项下标/-1 */
/* ---- TabBar(顶部分页页签;swipe 联动 §5.2 由 App 在 on_swipe 驱动)---- */
meow_widget *meow_tabbar_create(int x, int y, int w, int h);
int meow_tabbar_add_tab(meow_widget *w, const char *label);
void meow_tabbar_set_selected(meow_widget *w, int idx);
int meow_tabbar_hit(meow_widget *w, int x, int y); /* 返回页签下标/-1 */
/* ---- 列表容器(LazyColumn/LazyRow:数据源回调 + 可见区虚拟化;复用 meow_list_source)
* meow_lazycolumn_create=纵向(item_h=行高);meow_lazyrow_create=横向(item_w=列宽)。
* 滚动由 App 在 on_swipe 里用 meow_list_scroll_by/set_scroll 驱动。 */
meow_widget *meow_lazycolumn_create(int x, int y, int w, int h, int item_h, int count,
meow_list_source src, void *ctx);
meow_widget *meow_lazyrow_create(int x, int y, int w, int h, int item_w, int count,
meow_list_source src, void *ctx);
void meow_list_set_scroll(meow_widget *w, int offset); /* clamp 到 [0, max_scroll] */
int meow_list_scroll(meow_widget *w);
int meow_list_max_scroll(meow_widget *w); /* max(0, count*item - viewport) */
void meow_list_scroll_by(meow_widget *w, int dy); /* 相对滚动(App on_swipe 用) */
int meow_list_set_item_h(meow_widget *w, int item); /* 改行高/列宽 */
int meow_list_hit_index(meow_widget *w, int x, int y); /* 命中项下标(含滚动换算);-1=未命中项/越界 */
/* M2.71-bug8:列表行选中 + 行点击回调。选中行已有高亮(现有绘制读 w->sel)。
* meow_list_tap_at:命中一行则置选中并回调 tap_cb(若设),返回该行 idx;未命中返回 -1。 */
void meow_list_set_selected(meow_widget *w, int idx); /* 选中行(越界 clamp);标脏 */
int meow_list_selected(meow_widget *w);
typedef void (*meow_list_tap_fn)(int idx, void *ctx);
void meow_list_set_on_tap(meow_widget *w, meow_list_tap_fn cb, void *ctx); /* 命中行→回调 */
int meow_list_tap_at(meow_widget *w, int x, int y); /* 命中行:置选中+回调,返回 idx/-1 */
/* ============================================================ */
/* §5.5 设计模板 A② 结构化列表(W_LISTVIEW):行=图标+标题+副标题+右侧操作 + 选中
* ------------------------------------------------------------
* 在既有「label-only」列表(meow_list_create/lazycolumn,行为不变)之上做**结构化扩展**:
* 行数据源回调逐行给出 meow_list_item(图标 / 标题 / 副标题 / 右侧操作 / 可选中),容器负责
* 绘制/滚动/选中/命中;支持单选/多选/无选择。向后兼容:既有 meow_list_* 全部保留不动。
* 颜色全部取 meow_theme_get() 语义色(日/夜/style 自动),不硬编码。
* 命中:meow_listview_hit 返回行号(含滚动换算 + 禁用行不响应);行右 1/3 为右侧操作区
* (meow_listview_hit_op 另判)。抬手用最新坐标(goodix 免疫,参照既有 W_LIST 习惯)。 */
/* ============================================================ */
/* 选中模式:无(纯入口列表)/ 单选 / 多选。 */
typedef enum { MEOW_LIST_SEL_NONE = 0, MEOW_LIST_SEL_SINGLE, MEOW_LIST_SEL_MULTI } meow_list_sel;
/* 行图标:meow_img*(MEOW_LIST_ICON_IMG)或内置符号(FOLDER/FILE,无图 App 用)。 */
typedef enum {
MEOW_LIST_ICON_NONE = 0, /* 无图标 */
MEOW_LIST_ICON_IMG, /* 用 item->icon(meow_img*) */
MEOW_LIST_ICON_FOLDER, /* 内置目录符号(填充矩形+页签) */
MEOW_LIST_ICON_FILE, /* 内置文件符号(空心矩形+折角) */
} meow_list_icon_kind;
/* 行右侧操作类型:无 / 箭头 / 开关 / 复选 / 详情钮(⋯)。 */
typedef enum {
MEOW_LIST_RIGHT_NONE = 0, /* 无右侧操作 */
MEOW_LIST_RIGHT_ARROW, /* 箭头 › */
MEOW_LIST_RIGHT_SWITCH, /* 开关(on/off = item->on) */
MEOW_LIST_RIGHT_CHECK, /* 复选标记 */
MEOW_LIST_RIGHT_MORE, /* ⋯ 详情钮 */
} meow_list_right;
/* 单行数据(回调填充到栈上,容器不长期持有)。title 必填;subtitle 可空。 */
typedef struct meow_list_item {
const meow_img *icon; /* 可选(icon_kind==MEOW_LIST_ICON_IMG 时用) */
int icon_kind; /* MEOW_LIST_ICON_*(NONE=无图标) */
const char *title; /* 主文本(必填,NULL 视为空行) */
const char *subtitle; /* 副文本,可空 */
int right; /* MEOW_LIST_RIGHT_* 右侧操作类型 */
int on; /* right==SWITCH 时开关态(0/1) */
int enabled; /* 1=可选中/可交互;0=变淡不响应命中 */
} meow_list_item;
/* 行数据源回调:idx 有效时填充 out 并返回 1;越界返回 0。每行轻量填充(不做 IO,§5.5)。 */
typedef int (*meow_list2_source)(int idx, meow_list_item *out, void *ctx);
/* 创建:视口(x,y,w,h) + 行数 count + 行数据源 + 选中模式。行高默认 56(可用 set_item_h 改)。 */
meow_widget *meow_listview_create(int x, int y, int w, int h, int count,
meow_list2_source src, void *ctx, meow_list_sel mode);
/* 行高(固定;越界/<=0 忽略)。 */
int meow_listview_set_item_h(meow_widget *lv, int item);
/* 行数(搜索过滤/懒加载/目录切换时动态更新):截断 sel 到新范围 + clamp scroll。 */
void meow_listview_set_count(meow_widget *lv, int count);
/* 滚动:set 越界 clamp 到 [0, max_scroll];by 相对滚动(App on_swipe/touch_move 用)。 */
void meow_listview_set_scroll(meow_widget *lv, int offset);
void meow_listview_scroll_by(meow_widget *lv, int dy);
int meow_listview_scroll(meow_widget *lv);
int meow_listview_max_scroll(meow_widget *lv); /* max(0, count*item_h - viewport_h) */
/* 选中集(mode 语义):
* NONE :忽略;SINGLE:set_sel(idx) 设/清(idx<0 清除);MULTI:set_sel(idx) 翻转 idx。
* get_sel 把当前选中下标写入 out[0..max),返回写入数;sel_count 返回选中总数。 */
void meow_listview_set_sel(meow_widget *lv, int idx);
int meow_listview_get_sel(meow_widget *lv, int *out, int max);
int meow_listview_sel_count(meow_widget *lv);
/* 命中:返回行号(含滚动换算;禁用行/越界返回 -1);行右 1/3 = 右侧操作区(另判)。 */
int meow_listview_hit(meow_widget *lv, int x, int y);
int meow_listview_hit_op(meow_widget *lv, int x, int y); /* 1=点在行右 1/3 操作区 */
/* 行点击回调(idx=行号;op:0=行体,1=右侧操作区)。 */
typedef void (*meow_listview_tap_fn)(int idx, int op, void *ctx);
void meow_listview_set_on_tap(meow_widget *lv, meow_listview_tap_fn cb, void *ctx);
/* 命中行:置选中 + 回调(若设)+ 返回 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);
/* ============================================================ */
/* §5.5 左滑删除(M7.3 通知中心缺口 #9):列表行横向手势 + 删除/回弹动画 */
/* ------------------------------------------------------------
* 行自绘 set_item_draw 配合(SDK 在自绘行前把该行横向偏移 swipe_dx 传给 x,并画右露删除区)。
* 手势由 App 在 on_touch_move 喂三级:begin(touch-down)/ move(touch-move)/ end(release)。
* 判定:横向小位移|dx|>|dy| 且超容差=swipe(move 返回 1=本列表消费,App 勿滚动);纵向
* |dy|>|dx| 且超容差=滚动手势优先(返回 0 并取消本行 swipe,App 照常 scroll_by);点按
* 无位移(end 时未 started)=行点击(返回 0,App 照常 tap_at)。不修改 tap_at/滚动语义。
* 动画:超阈值 → 删除动画(行滑出 meow_anim,结束后回调 on_delete(idx));未超 → 回弹。
* 颜色:删除区用主题 error/onError;不与行点击/滚动冲突(见判定表)。 */
typedef void (*meow_listview_swipe_fn)(int idx, void *ctx);
void meow_listview_set_swipe_delete(meow_widget *lv, int enabled,
meow_listview_swipe_fn on_delete, void *ctx);
int meow_listview_swipe_begin(meow_widget *lv, int x, int y); /* touch-down:1=命中可滑行(喂后续 move) */
int meow_listview_swipe_move(meow_widget *lv, int x, int y); /* touch-move:1=消费(横向);0=让位(取消/纵向) */
int meow_listview_swipe_end(meow_widget *lv, int x, int y); /* release:1=消费(删/回弹动画);0=未滑动(tap) */
int meow_listview_swipe_active(meow_widget *lv); /* 1=有行处于滑动/动画中 */
int meow_listview_swipe_offset(meow_widget *lv); /* 当前滑动行的 dx(<0=左移;自绘行画用) */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_WIDGETS_H */