git-subtree-dir: examples/hello git-subtree-mainline:f44e3bc6d0git-subtree-split:e88e5a6ff3
167 lines
7.4 KiB
C
167 lines
7.4 KiB
C
/* ui/demo/list/list.c — 控件库 Demo 页内「列表区」CONTAINER 子视图(批次③ 视图深度化)。
|
||
*
|
||
* 目标(SDK_VIEW_FRAMEWORK_DESIGN.md §B.4/§E③):
|
||
* 把 demo 页内的 LazyColumn 列表逻辑区块抽成一个 meow_view CONTAINER 子视图,
|
||
* 挂到 demo ACTIVITY view 的 children(meow_view_add_child),验证
|
||
* ① 嵌套生命周期:on_enter/on_leave 顺序(父进入→子进入;子离开→父离开);
|
||
* ② 嵌套命中(子>父):点落列表区由本子视图消费,落列表区外回退父页;
|
||
* ③ on_draw 直绘:list 区块标题改由本子视图 on_draw 经注册表绘制(view→注册表→invalidate 链路)。
|
||
*
|
||
* 职责边界(诚实):
|
||
* - 本子视图为**组织/结构节点 + 列表交互收口**:持有 list 控件引用 + 列表视图态
|
||
* (focus/drag/scroll/sel),并对外暴露 list_view_hit/down/move/swipe 供 demo 页分发改派,
|
||
* 实现「子>父」命中。list **控件创建/释放**仍留在 demo 页内容重建流(demo_build_at/
|
||
* demo_free_content),因为 widget 由 z 序注册表 auto 注册/注销、并随 scroll 重建——完整
|
||
* 的「控件归容器拥有」需 SDK 侧支持(本批冻结 patch_v2/sdk/),故以绑定引用的方式折中。
|
||
* - SDK(meow_ui_view.c)的 view_enter/view_leave **递归 children**(批次①→③ 后接线):
|
||
* 本子视图随 demo 页 on_enter/on_leave 自动进入/离开,无需 App 层显式驱动(list_view_enter/leave
|
||
* 已退役);父 on_enter 重绘时子视图经 meow_draw_view_entered(含祖先已进入)可见。
|
||
* - on_draw 是回调、view 不缓存像素(非保留,§5.8.7);绘制由 meow_ui_paint_full/invalidate
|
||
* 触发,仅当本子视图 state 含 MEOW_VIEW_STATE_ENTERED 时注册表才绘制(meow_draw_view_entered)。
|
||
*/
|
||
#include "hello_internal.h"
|
||
|
||
/* ---- 本子视图(CONTAINER,非页面:id 用越界值避免占用 g_view_by_id 顶层页槽位) ---- */
|
||
static meow_view *g_list_view = NULL;
|
||
|
||
/* ---- 列表视图态(跨重建保留;extern 供宿主测试对真实状态断言,见 hello_internal.h)----
|
||
* g_dlc/r_list/g_demo_focus/g_drag_list 从 demo.c 迁入本文件(语义归列表区)。
|
||
* g_demo_focus 亦被 demo.c 的页/列表滚动分流读取,经 extern 跨 TU 共享。 */
|
||
meow_widget *g_dlc = NULL;
|
||
rect_t r_list = { 0, 0, 0, 0 };
|
||
int g_demo_focus = 0; /* 1=LazyColumn 聚焦(swipe 滚列表而非页面) */
|
||
int g_drag_list = 0; /* 手指按在 LazyColumn:拖拽滚列表 */
|
||
|
||
static rect_t r_list_title = { 0, 0, 0, 0 }; /* list 区块标题外接框(on_draw 用) */
|
||
static int g_list_scroll = 0; /* 跨重建保留:列表滚动偏移 */
|
||
static int g_list_sel = 0; /* 跨重建保留:选中行 */
|
||
static int g_drag_list_last_y = 0; /* 列表拖拽上一帧 y */
|
||
|
||
/* ---- on_draw:list 区块标题直绘(注册表→invalidate 链路实测,批次③)----
|
||
* 原 demo.c 用 d_title() 把标题注册成 CUSTOM 绘制物;本表标题改由本子视图 on_draw 绘制,
|
||
* 注册表在整帧/区域重画时经 draw_one(VIEW) 调 v->hooks.on_draw(需本子视图已进入)。 */
|
||
static void list_view_draw(meow_view *v, const meow_theme *th, void *ctx)
|
||
{
|
||
(void)ctx;
|
||
if (!g_dlc) return; /* 列表未建成(几何未绑)时不画 */
|
||
meow_ui_text(meow_view_screen_x(v), meow_view_screen_y(v),
|
||
"LIST (LazyColumn, tap+swipe)", 20, th->primary);
|
||
}
|
||
|
||
static void list_page_enter(meow_view *v, void *ctx)
|
||
{
|
||
(void)v; (void)ctx;
|
||
meow_log(MEOW_LOG_INFO, "demo list view enter");
|
||
}
|
||
static void list_page_leave(meow_view *v, void *ctx)
|
||
{
|
||
(void)v; (void)ctx;
|
||
meow_log(MEOW_LOG_INFO, "demo list view leave");
|
||
}
|
||
static void list_page_destroy(meow_view *v, void *ctx)
|
||
{
|
||
(void)v; (void)ctx;
|
||
g_dlc = NULL;
|
||
r_list = RX(0, 0, 0, 0);
|
||
r_list_title = RX(0, 0, 0, 0);
|
||
g_list_view = NULL; /* meow_view_free 递归释放前清引用,防悬垂 */
|
||
}
|
||
|
||
/* 建 CONTAINER 子视图(demo_page_create 调,随即 meow_view_add_child 到 demo ACTIVITY view)。
|
||
* 进入/离开经 SDK view_enter/view_leave 递归驱动(随 demo 页),本文件不再显式接管。 */
|
||
meow_view *list_view_create(void)
|
||
{
|
||
static const meow_view_hooks h = {
|
||
.on_enter = list_page_enter,
|
||
.on_leave = list_page_leave,
|
||
.on_destroy = list_page_destroy,
|
||
.on_draw = list_view_draw,
|
||
};
|
||
/* id 用非页面值:容器不占 g_view_by_id(那是 page_push/pop 顶层页查找表)。 */
|
||
g_list_view = meow_view_create(0x1000, MEOW_VIEW_CONTAINER, &h, NULL);
|
||
return g_list_view;
|
||
}
|
||
meow_view *list_view_get(void)
|
||
{
|
||
return g_list_view;
|
||
}
|
||
|
||
/* 内容重建后绑定:list 控件 + 几何(list 区 + 标题条),并恢复/应用跨重建的 scroll/select。
|
||
* demo_build_at 在创建 g_dlc 后调本函数,把标题条与列表区几何写进容器 view(on_draw/命中用)。 */
|
||
void list_view_bind(meow_widget *w, rect_t list, rect_t title)
|
||
{
|
||
g_dlc = w;
|
||
r_list = list;
|
||
r_list_title = title;
|
||
if (g_list_view) {
|
||
g_list_view->x = title.x;
|
||
g_list_view->y = title.y;
|
||
g_list_view->w = title.w;
|
||
g_list_view->h = title.h + list.h; /* 标题条 + 列表区 */
|
||
}
|
||
if (g_dlc) {
|
||
meow_list_set_scroll(g_dlc, g_list_scroll);
|
||
meow_list_set_selected(g_dlc, g_list_sel);
|
||
}
|
||
}
|
||
|
||
/* 内容释放后清引用(demo_free_content 调;list 控件已由 demo 释放,本处只摘引用)。 */
|
||
void list_view_release(void)
|
||
{
|
||
g_dlc = NULL;
|
||
r_list = RX(0, 0, 0, 0);
|
||
r_list_title = RX(0, 0, 0, 0);
|
||
if (g_list_view) g_list_view->x = g_list_view->y = g_list_view->w = g_list_view->h = 0;
|
||
}
|
||
|
||
/* 点是否落列表区(嵌套命中断言/分发改派用)。 */
|
||
int list_view_contains(int x, int y)
|
||
{
|
||
return g_dlc && meow_widget_hit(g_dlc, x, y);
|
||
}
|
||
|
||
/* Tap 分发给列表区(嵌套命中:demo_content_tap 先查本子视图,命中即消费——子>父)。
|
||
* 命中行→置选中并局部刷;返回 1=已消费。 */
|
||
int list_view_hit(int x, int y)
|
||
{
|
||
if (!list_view_contains(x, y)) return 0;
|
||
g_demo_focus = 1;
|
||
int li = meow_list_tap_at(g_dlc, x, y);
|
||
if (li >= 0) { g_list_sel = li; meow_ui_invalidate(r_list.x, r_list.y, r_list.w, r_list.h); }
|
||
return 1;
|
||
}
|
||
|
||
/* Touch Down 命中列表:置列表聚焦 + 拖拽锁;返回 1=已消费(demo_touch_down 改派)。 */
|
||
int list_view_down(int x, int y)
|
||
{
|
||
if (!list_view_contains(x, y)) return 0;
|
||
g_demo_focus = 1;
|
||
g_drag_list = 1;
|
||
g_drag_list_last_y = y;
|
||
return 1;
|
||
}
|
||
|
||
/* Touch Move 拖动列表:跟随滚动;已有 drag 锁(由 down 设立);返回 1=在列表拖动。 */
|
||
int list_view_move(int y)
|
||
{
|
||
if (!g_drag_list) return 0;
|
||
int dy = y - g_drag_list_last_y;
|
||
g_drag_list_last_y = y;
|
||
if (dy) {
|
||
meow_list_scroll_by(g_dlc, -dy);
|
||
g_list_scroll = meow_list_scroll(g_dlc);
|
||
meow_ui_invalidate(r_list.x, r_list.y, r_list.w, r_list.h);
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
/* Swipe:列表聚焦时滚列表(返回 1=已消费;否则 demo 页滚页面)。del=方向加权位移。 */
|
||
int list_view_swipe(int del)
|
||
{
|
||
if (!(g_demo_focus && g_dlc)) return 0;
|
||
meow_list_scroll_by(g_dlc, del);
|
||
g_list_scroll = meow_list_scroll(g_dlc);
|
||
meow_ui_invalidate(r_list.x, r_list.y, r_list.w, r_list.h);
|
||
return 1;
|
||
}
|