From adadaee4ad738759f96476645c68495f49be05cc Mon Sep 17 00:00:00 2001 From: smiling boy Date: Wed, 14 Jan 2026 10:57:46 +0800 Subject: [PATCH 01/27] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=92=8C=E4=B8=BB=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubList.cpp | 121 +----- epdiy-epub/src/SConscript | 2 +- .../boards/controls/SF32_TouchControls.cpp | 76 +++- .../src/boards/controls/SF32_TouchControls.h | 8 +- epdiy-epub/src/epub_screen.cpp | 358 ++++++++++++++++++ epdiy-epub/src/epub_screen.h | 24 ++ epdiy-epub/src/main.cpp | 88 ++--- 7 files changed, 508 insertions(+), 169 deletions(-) create mode 100644 epdiy-epub/src/epub_screen.cpp create mode 100644 epdiy-epub/src/epub_screen.h diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp index efd6603..2998a34 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp @@ -16,45 +16,24 @@ static const char *TAG = "PUBLIST"; #define PADDING 20 #define EPUBS_PER_PAGE 5 -#define BOTTOM_AREA_HEIGHT 50 -#define BOTTOM_AREA_ITEM_INDEX -1 void EpubList::next() { - // 如果当前选中的是最后一个电子书项,则切换到底部区域 - if (state.selected_item == state.num_epubs - 1) - { - state.selected_item = BOTTOM_AREA_ITEM_INDEX; - } - else if (state.selected_item == BOTTOM_AREA_ITEM_INDEX) - { - // 如果当前已在底部区域,则回到第一个电子书项 + if (state.num_epubs == 0) return; + // 正常切换到下一个电子书项 + if (state.selected_item >= 0 && state.selected_item < state.num_epubs - 1) + state.selected_item++; + else state.selected_item = 0; - } - else - { - // 正常切换到下一个电子书项 - state.selected_item = (state.selected_item + 1) % state.num_epubs; - } } void EpubList::prev() { - if (state.selected_item == 0) - { - // 如果当前是第一个电子书项,则切换到底部区域 - state.selected_item = BOTTOM_AREA_ITEM_INDEX; - } - else if (state.selected_item == BOTTOM_AREA_ITEM_INDEX) - { - // 如果当前已在底部区域,则切换到最后一个电子书项 - state.selected_item = state.num_epubs > 0 ? state.num_epubs - 1 : 0; - } - else - { - // 正常切换到上一个电子书项 - state.selected_item = (state.selected_item - 1 + state.num_epubs) % state.num_epubs; - } + if (state.num_epubs == 0) return; + if (state.selected_item <= 0) + state.selected_item = state.num_epubs - 1; + else + state.selected_item--; } bool EpubList::load(const char *path) @@ -149,8 +128,8 @@ void EpubList::render() ulog_d(TAG, "Rendering EPUB list"); // what page are we on? int current_page = state.selected_item / EPUBS_PER_PAGE; - // 计算单元格高度,减去底部区域的高度 - int cell_height = (renderer->get_page_height() - BOTTOM_AREA_HEIGHT) / EPUBS_PER_PAGE; + // 计算单元格高度(不再预留底部区域) + int cell_height = (renderer->get_page_height()) / EPUBS_PER_PAGE; ulog_d(TAG, "Cell height is %d", cell_height); int start_index = current_page * EPUBS_PER_PAGE; int ypos = 0; @@ -225,79 +204,5 @@ void EpubList::render() state.previous_selected_item = state.selected_item; state.previous_rendered_page = current_page; - // touch 开关底部区域 - - int screen_height = renderer->get_page_height(); - int bottom_area_y = screen_height - BOTTOM_AREA_HEIGHT - 11; - - - int original_width = renderer->get_page_width() - 2 * PADDING; - int rect_width = original_width * 2 / 3; - int rect_x = PADDING + (original_width - rect_width) / 2; - - int rect_height = BOTTOM_AREA_HEIGHT; - - if (bottom_area_y < 0) - { - bottom_area_y = 5; - rect_height = BOTTOM_AREA_HEIGHT; - } - - - renderer->fill_rect(rect_x, bottom_area_y, rect_width, rect_height, 255); - - bool touch_state = touch_controls ? touch_controls->isTouchEnabled() : false; - const char* text = touch_state ? "Touch : On" : "Touch : Off"; - - int text_height = renderer->get_line_height(); - int text_y = bottom_area_y + (rect_height - text_height) / 2; - - if (text_y < bottom_area_y + 2) - { - text_y = bottom_area_y + 2; - } - if (text_y + text_height > bottom_area_y + rect_height - 2) - { - text_y = bottom_area_y + rect_height - text_height - 2; - } - - int text_length = strlen(text); - int estimated_text_width = text_length * 12; - int text_x = rect_x + (rect_width - estimated_text_width) / 2; - - - if (text_x < rect_x + 5) - { - text_x = rect_x + 5; - } - if (text_x + estimated_text_width > rect_x + rect_width - 5) - { - text_x = rect_x + rect_width - estimated_text_width - 5; - } - - renderer->draw_text(text_x, text_y, text, 0); - - if (state.selected_item == BOTTOM_AREA_ITEM_INDEX) - { - int border_thickness = 3; - for (int i = 0; i < border_thickness; i++) - { - renderer->draw_rect(rect_x + i, bottom_area_y + i, - rect_width - 2 * i, - rect_height - 2 * i, 0); - } - } - else - { - if (state.previous_selected_item == BOTTOM_AREA_ITEM_INDEX) - { - int border_thickness = 3; - for (int i = 0; i < border_thickness; i++) - { - renderer->draw_rect(rect_x + i, bottom_area_y + i, - rect_width - 2 * i, - rect_height - 2 * i, 255); - } - } - } + // 移除书库页底部触控开关区域 } \ No newline at end of file diff --git a/epdiy-epub/src/SConscript b/epdiy-epub/src/SConscript index dd9b659..6c590b3 100644 --- a/epdiy-epub/src/SConscript +++ b/epdiy-epub/src/SConscript @@ -4,7 +4,7 @@ from building import * import rtconfig cwd = GetCurrentDir() -src = ['main.cpp','epub_mem.c','epub_fonts.c'] +src = ['main.cpp','epub_screen.cpp','epub_mem.c','epub_fonts.c'] src = src + Glob('./assets/*.c') CPPPATH = [cwd] diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index a2f85c9..9d17027 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -6,6 +6,9 @@ #include "drv_touch.h" #endif +volatile int g_touch_last_settings_row = -1; +volatile int g_touch_last_settings_dir = 0; + rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { SF32_TouchControls *instance = static_cast (dev->user_data); @@ -29,24 +32,65 @@ rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) UIAction action = NONE; // LOG_I("TOUCH", "Received touch event %d,%d", x, y); - if (x >= 10 && x <= 10 + instance->ui_button_width && y < 200) - { - action = DOWN; - instance->renderPressedState(instance->renderer, UP, false); - } - else if (x >= 150 && x <= 150 + instance->ui_button_width && y < 200) - { - action = UP; - instance->renderPressedState(instance->renderer, DOWN, false); - } - else if (x >= 300 && x <= 300 + instance->ui_button_width && y < 200) + // 主页面底部按键区域:左"<"、右">"、中间文本框 + int page_w = instance->renderer->get_page_width(); + int page_h = instance->renderer->get_page_height(); + int margin_side = 10; + int margin_bottom = 60; + int rect_w = 80; + int rect_h = 40; + int y_bottom = page_h - rect_h - margin_bottom; + int left_x = margin_side; + int right_x = page_w - rect_w - margin_side; + int mid_x = left_x + rect_w + margin_side; + int mid_w = right_x - margin_side - mid_x; + + if (x >= left_x && x <= left_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) + { + rt_kprintf("Touch left < \n"); + action = UP; + } + + else if (x >= right_x && x <= right_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) + { + action = DOWN; + rt_kprintf("Touch right > \n"); + } + + // 设置页面每行左右箭头触控区域(与设置页布局一致) + if (action == NONE) { - action = SELECT; + int page_w2 = instance->renderer->get_page_width(); + int margin_lr2 = 6; + int item_h2 = 100; + int gap2 = 54; + int arrow_col_w2 = 40; + int lh2 = instance->renderer->get_line_height(); + int y_start2 = 40 + lh2 + 20; + g_touch_last_settings_row = -1; + g_touch_last_settings_dir = 0; + for (int row = 0; row < 3; ++row) + { + int ry = y_start2 + row * (item_h2 + gap2); + int left_ax = margin_lr2; + int right_ax = page_w2 - margin_lr2 - arrow_col_w2; + if (x >= left_ax && x <= left_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) + { + action = UP; + g_touch_last_settings_row = row; + g_touch_last_settings_dir = -1; // 左=减 + break; + } + if (x >= right_ax && x <= right_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) + { + action = DOWN; + g_touch_last_settings_row = row; + g_touch_last_settings_dir = +1; // 右=加 + break; + } + } } - else - { - } instance->last_action = action; if (action != NONE) { @@ -157,6 +201,8 @@ void SF32_TouchControls::renderPressedState(Renderer *renderer, UIAction action, case LAST_INTERACTION: case NONE: break; + default: + break; } renderer->set_margin_top(35); } \ No newline at end of file diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.h b/epdiy-epub/src/boards/controls/SF32_TouchControls.h index 23f2c56..d9dfba6 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.h +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.h @@ -23,4 +23,10 @@ class SF32_TouchControls : public TouchControls void renderPressedState(Renderer *renderer, UIAction action, bool state = true) override; void powerOnTouch() override; void powerOffTouch() override; -}; \ No newline at end of file +}; + +// 最近一次设置页左右箭头触控标记 +// 行号:0=触控开关,1=超时关机,2=全刷周期;-1=无 +extern volatile int g_touch_last_settings_row; +// 方向:-1=左(减),+1=右(加),0=无 +extern volatile int g_touch_last_settings_dir; \ No newline at end of file diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp new file mode 100644 index 0000000..ede9f23 --- /dev/null +++ b/epdiy-epub/src/epub_screen.cpp @@ -0,0 +1,358 @@ +#include "epub_screen.h" +#include + + +extern TouchControls *touch_controls; + +// 主页面选项 +typedef enum +{ + OPTION_OPEN_LIBRARY = 0, + OPTION_CONTINUE_READING, + OPTION_ENTER_SETTINGS +} MainOption; + +static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” +static int full_refresh_period = 10; // 全刷周期次数,仅用于设置页显示 + +// 设置页列表项 +typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; +static int settings_selected_idx = 0; + +// 超时关机:1/3/5/7/10/不关机(0) +static const int kTimeoutOptions[] = {1, 3, 5, 7, 10, 0}; +static const int kTimeoutOptionsCount = sizeof(kTimeoutOptions) / sizeof(kTimeoutOptions[0]); +static int timeout_shutdown_hours = 5; // 运行时关机超时(小时),0 表示不关机 +static int timeout_idx = -1; // 指向 kTimeoutOptions 的索引 + +static int find_timeout_idx(int hours) +{ + for (int i = 0; i < kTimeoutOptionsCount; ++i) + { + if (kTimeoutOptions[i] == hours) return i; + } + return 2; // 默认索引:5小时 +} + +static void adjust_timeout(bool increase) +{ + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); + if (increase) + { + timeout_idx = (timeout_idx + 1) % kTimeoutOptionsCount; + } + else + { + timeout_idx = (timeout_idx - 1 + kTimeoutOptionsCount) % kTimeoutOptionsCount; + } + timeout_shutdown_hours = kTimeoutOptions[timeout_idx]; +} + +void screen_init(int default_timeout_hours) +{ + timeout_shutdown_hours = default_timeout_hours; + timeout_idx = find_timeout_idx(timeout_shutdown_hours); +} + +int screen_get_timeout_shutdown_hours() +{ + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); + return timeout_shutdown_hours; +} + +int screen_get_main_selected_option() +{ + return (int)main_option; // 0: 打开书库, 1: 继续阅读, 2: 进入设置 +} + +// 主页面 +static void render_main_page(Renderer *renderer) +{ + renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); + + const char *title = "S I F L I"; + int title_w = renderer->get_text_width(title); + int title_h = renderer->get_line_height(); + int center_x = renderer->get_page_width() / 2; + int center_y = 35 + (renderer->get_page_height() - 35) / 2; + renderer->draw_text(center_x - title_w / 2, center_y - title_h / 2, title, true, true); + + int margin_side = 10; + int margin_bottom = 60; // 与底部距离 + int rect_w = 80; + int rect_h = 40; + int y = renderer->get_page_height() - rect_h - margin_bottom; + int left_x = margin_side; + int right_x = renderer->get_page_width() - rect_w - margin_side; + + // 左 "<" + const char *lt = "<"; + int lt_w = renderer->get_text_width(lt); + int lt_h = renderer->get_line_height(); + renderer->draw_text(left_x + (rect_w - lt_w) / 2, y + (rect_h - lt_h) / 2, lt, false, true); + + // 右 ">" + const char *gt = ">"; + int gt_w = renderer->get_text_width(gt); + int gt_h = renderer->get_line_height(); + renderer->draw_text(right_x + (rect_w - gt_w) / 2, y + (rect_h - gt_h) / 2, gt, false, true); + + // 中间选项文本 + int mid_x = left_x + rect_w + margin_side; + int mid_w = right_x - margin_side - mid_x; + + const char *opt_text = NULL; + switch (main_option) + { + case OPTION_OPEN_LIBRARY: opt_text = "打开书库"; break; + case OPTION_CONTINUE_READING: opt_text = "继续阅读"; break; + case OPTION_ENTER_SETTINGS: opt_text = "进入设置"; break; + } + int opt_w = renderer->get_text_width(opt_text); + int opt_h = renderer->get_line_height(); + renderer->draw_text(mid_x + (mid_w - opt_w) / 2, y + (rect_h - opt_h) / 2, opt_text, false, true); +} + +void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) +{ + if (needs_redraw || action == NONE) + { + render_main_page(renderer); + return; + } + switch (action) + { + case UP: // 左切换 + if (main_option == OPTION_OPEN_LIBRARY) main_option = OPTION_ENTER_SETTINGS; + else if (main_option == OPTION_CONTINUE_READING) main_option = OPTION_OPEN_LIBRARY; + else main_option = OPTION_CONTINUE_READING; + render_main_page(renderer); + break; + case DOWN: // 右切换 + if (main_option == OPTION_OPEN_LIBRARY) main_option = OPTION_CONTINUE_READING; + else if (main_option == OPTION_CONTINUE_READING) main_option = OPTION_ENTER_SETTINGS; + else main_option = OPTION_OPEN_LIBRARY; + render_main_page(renderer); + break; + case SELECT: + // 由上层 main.cpp 负责切换 页面UIState + switch (main_option) + { + case OPTION_OPEN_LIBRARY: + rt_kprintf("1\n"); + break; + case OPTION_CONTINUE_READING: + rt_kprintf("2\n"); + break; + case OPTION_ENTER_SETTINGS: + rt_kprintf("3\n"); + break; + } + break; + default: + break; + } +} + +// 设置页面 +static void render_settings_page(Renderer *renderer) +{ + renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); + + // 标题 + const char *title = "设置"; + int title_w = renderer->get_text_width(title); + int title_h = renderer->get_line_height(); + int page_w = renderer->get_page_width(); + int page_h = renderer->get_page_height(); + renderer->draw_text((page_w - title_w) / 2, 40, title, true, true); + + // 列表项布局参数 + int margin_lr = 6; // 左右边距,给左右触控箭头 + int item_h = 100; // 矩形高度 + int gap = 54; // 列表项之间的间距 + int arrow_col_w = 40; // 左右触控箭头列宽度 + int y = 40 + title_h + 20; // 第一项起始Y + + // 1) 触控开关 + int item_w = page_w - margin_lr * 2 - arrow_col_w * 2; // 为左右箭头列留边 + int item_x = margin_lr + arrow_col_w; + { + const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); + const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); + } + if (settings_selected_idx == SET_TOUCH) + { + for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + } + else + { + renderer->draw_rect(item_x, y, item_w, item_h, 0); //画框线 + } + bool touch_on = touch_controls ? touch_controls->isTouchEnabled() : false; + char buf1[48]; + rt_snprintf(buf1, sizeof(buf1), "触控开关:%s", touch_on ? "开" : "关"); + int t1_w = renderer->get_text_width(buf1); + int lh = renderer->get_line_height(); + { + int tx = item_x + (item_w - t1_w) / 2; + if (tx < item_x + 4) tx = item_x + 4; + if (tx + t1_w > item_x + item_w - 4) tx = item_x + item_w - t1_w - 4; + renderer->draw_text(tx, y + (item_h - lh) / 2, buf1, false, true); + } + y += item_h + gap; + + // 2) 超时关机 + { + const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); + const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); + } + if (settings_selected_idx == SET_TIMEOUT) + { + for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + } + else + { + renderer->draw_rect(item_x, y, item_w, item_h, 0); + } + char buf2[64]; + if (timeout_shutdown_hours == 0) + { + rt_snprintf(buf2, sizeof(buf2), "超时关机:不关机"); + } + else + { + rt_snprintf(buf2, sizeof(buf2), "超时关机:%d 小时", timeout_shutdown_hours); + } + { + int t2_w = renderer->get_text_width(buf2); + int tx = item_x + (item_w - t2_w) / 2; + if (tx < item_x + 4) tx = item_x + 4; + if (tx + t2_w > item_x + item_w - 4) tx = item_x + item_w - t2_w - 4; + renderer->draw_text(tx, y + (item_h - lh) / 2, buf2, false, true); + } + y += item_h + gap; + + // 3) 全刷周期 + { + const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); + const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); + } + if (settings_selected_idx == SET_FULL_REFRESH) + { + for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + } + else + { + renderer->draw_rect(item_x, y, item_w, item_h, 0); + } + char buf3[64]; + rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", full_refresh_period); + { + int t3_w = renderer->get_text_width(buf3); + int tx = item_x + (item_w - t3_w) / 2; + if (tx < item_x + 4) tx = item_x + 4; + if (tx + t3_w > item_x + item_w - 4) tx = item_x + item_w - t3_w - 4; + renderer->draw_text(tx, y + (item_h - lh) / 2, buf3, false, true); + } + y += item_h + gap; + + // 底部 确认 按钮 + int confirm_h = 120; // 矩形框高度 + int confirm_w = item_w; // 宽度 + int confirm_x = (page_w - confirm_w) / 2; // 居中 + int confirm_y = page_h - confirm_h - 60; // 距离底部位置 + if (settings_selected_idx == SET_CONFIRM) + { + for (int i = 0; i < 2; ++i) renderer->draw_rect(confirm_x + i, confirm_y + i, confirm_w - 2 * i, confirm_h - 2 * i, 0); + } + else + { + renderer->draw_rect(confirm_x, confirm_y, confirm_w, confirm_h, 0); + } + const char *confirm = "确认"; + int c_w = renderer->get_text_width(confirm); + int c_h = renderer->get_line_height(); + renderer->draw_text(confirm_x + (confirm_w - c_w) / 2, confirm_y + (confirm_h - c_h) / 2, confirm, false, true); +} + +bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) +{ + // 读取并清除一次性的触控箭头标记,避免后续硬件按键误用 + int touch_row = g_touch_last_settings_row; + int touch_dir = g_touch_last_settings_dir; + g_touch_last_settings_row = -1; + g_touch_last_settings_dir = 0; + + if (needs_redraw || action == NONE) + { + render_settings_page(renderer); + return false; + } + + switch (action) + { + case UP: + // 触控箭头若命中“超时关机”行且为左箭头(减),执行减;否则执行上下选择 + if (settings_selected_idx == SET_TIMEOUT && touch_row == 1 && touch_dir == -1) + { + adjust_timeout(false); + render_settings_page(renderer); + } + else + { + if (settings_selected_idx > 0) settings_selected_idx--; else settings_selected_idx = SET_CONFIRM; + render_settings_page(renderer); + } + break; + case DOWN: + // 触控箭头若命中“超时关机”行且为右箭头(加),执行加;否则执行上下选择 + if (settings_selected_idx == SET_TIMEOUT && touch_row == 1 && touch_dir == +1) + { + adjust_timeout(true); + render_settings_page(renderer); + } + else + { + if (settings_selected_idx < SET_CONFIRM) settings_selected_idx++; else settings_selected_idx = SET_TOUCH; + render_settings_page(renderer); + } + break; + case SELECT: + if (settings_selected_idx == SET_TOUCH) + { + bool current_state = touch_controls ? touch_controls->isTouchEnabled() : false; + if (touch_controls) + { + touch_controls->setTouchEnable(!current_state); + if (!current_state) touch_controls->powerOnTouch(); + else touch_controls->powerOffTouch(); + } + render_settings_page(renderer); + break; + } + if (settings_selected_idx == SET_TIMEOUT) + { + // SELECT 在超时关机项上为加操作(循环) + adjust_timeout(true); + render_settings_page(renderer); + break; + } + if (settings_selected_idx == SET_CONFIRM) + { + // 由上层切回主页面 + return true; + } + // 其他项当前不处理 + break; + default: + break; + } + return false; +} diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h new file mode 100644 index 0000000..c97c3c4 --- /dev/null +++ b/epdiy-epub/src/epub_screen.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include "boards/SF32PaperRenderer.h" +#include "boards/controls/Actions.h" +#include "boards/controls/TouchControls.h" +#include "boards/controls/SF32_TouchControls.h" + + +// 初始化屏幕模块(设置默认的关机超时小时数,0 表示不关机) +void screen_init(int default_timeout_hours); + +// 获取当前关机超时设置(小时;0 表示不关机) +int screen_get_timeout_shutdown_hours(); + +// 获取当前主页面选中的选项(0: 打开书库, 1: 继续阅读, 2: 进入设置) +int screen_get_main_selected_option(); + +// 主页面交互与渲染 +void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw); + +// 设置页面交互与渲染;返回 true 表示确认并退出到主页面 +bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw); + diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 171f083..ebe3d87 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -6,6 +6,7 @@ #include #include "boards/Board.h" #include "boards/controls/SF32_TouchControls.h" +#include "epub_screen.h" #include "boards/SF32PaperRenderer.h" #include "gui_app_pm.h" #include "bf0_pm.h" @@ -15,7 +16,7 @@ #undef DBG_LEVEL #define DBG_LEVEL DBG_LOG //DBG_INFO // #define LOG_TAG "EPUB.main" - +#define TIMEOUT_SHUTDOWN_TIME 5 // 默认关机超时(小时);0 表示不关机 #include @@ -35,9 +36,11 @@ const char *TAG = "main"; typedef enum { - SELECTING_EPUB, + MAIN_PAGE, // 新主页面 + SELECTING_EPUB, SELECTING_TABLE_CONTENTS, READING_EPUB, + SETTINGS_PAGE // 通用功能设置页面 } UIState; typedef enum { @@ -47,8 +50,8 @@ typedef enum CHARGING_PAGE } UIState2; -// default to showing the list of epubs to the user -UIState ui_state = SELECTING_EPUB; +// 默认显示新主页面,而非书库页面 +UIState ui_state = MAIN_PAGE; UIState2 lowpower_ui_state = MAIN_MENU; // the state data for the epub list and reader EpubListState epub_list_state; @@ -63,12 +66,19 @@ static EpubReader *reader = nullptr; static EpubToc *contents = nullptr; static bool charge_full = false; Battery *battery = nullptr; -// 声明全局变量,以便open_tp_lcd和close_tp_lcd函数可以访问 +// 给open_tp_lcd和close_tp_lcd用的 Renderer *renderer = nullptr; TouchControls *touch_controls = nullptr; rt_mq_t ui_queue = RT_NULL; +// 主页面选项 +typedef enum { + OPTION_OPEN_LIBRARY = 0, // 打开书库 -> 打印 1 + OPTION_CONTINUE_READING, // 继续阅读 -> 打印 2 + OPTION_ENTER_SETTINGS // 进入设置 -> 打印 3 +} MainOption; + void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -168,30 +178,6 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) epub_list->next(); break; case SELECT: - // 检查是否选中了底部特殊区域 - if (epub_list_state.selected_item == -1) { - // 打印"1" - rt_kprintf("touch open or off\n"); - bool current_state = touch_controls->isTouchEnabled(); - touch_controls->setTouchEnable(!current_state); - - // 刷新屏幕以更新底部区域的文本显示 - if (!current_state) // 之前是关闭状态,现在要打开 - { - touch_controls->powerOnTouch(); - } - else // 之前是打开状态,现在要关闭 - { - touch_controls->powerOffTouch(); - } - - epub_list->render(); - - - return; - } - else - { // switch to reading the epub // setup the reader state ui_state = SELECTING_TABLE_CONTENTS; @@ -201,7 +187,6 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) contents->set_needs_redraw(); handleEpubTableContents(renderer, NONE, true); return; - } case NONE: default: // nothing to do @@ -288,13 +273,31 @@ void handleUserInteraction(Renderer *renderer, UIAction ui_action, bool needs_re uint32_t start_tick = rt_tick_get(); switch (ui_state) { + case MAIN_PAGE: // 新主页面 + handleMainPage(renderer, ui_action, needs_redraw); + if (ui_action == SELECT && screen_get_main_selected_option() == 2) + { + ui_state = SETTINGS_PAGE; + (void)handleSettingsPage(renderer, NONE, true); + } + break; case READING_EPUB: //阅读界面 handleEpub(renderer, ui_action); break; case SELECTING_TABLE_CONTENTS: //目录界面 handleEpubTableContents(renderer, ui_action, needs_redraw); break; - case SELECTING_EPUB: //电子书列表(主界面) + case SETTINGS_PAGE: // 设置页面 + { + bool exit_to_main = handleSettingsPage(renderer, ui_action, needs_redraw); + if (exit_to_main) + { + ui_state = MAIN_PAGE; + handleMainPage(renderer, NONE, true); + } + break; + } + case SELECTING_EPUB: //电子书列表页面(书库页面) default: handleEpubList(renderer, ui_action, needs_redraw); break; @@ -338,15 +341,8 @@ void back_to_main_page() renderer->set_margin_top(35); renderer->set_margin_left(10); renderer->set_margin_right(10); - - if (!epub_list) - { - epub_list = new EpubList(renderer, epub_list_state); - if (epub_list->load("/")) - { - ulog_i("main", "Epub files loaded"); - } - } + // 返回新的主页面,不再默认进入书库页面 + ui_state = MAIN_PAGE; handleUserInteraction(renderer, NONE, true); if (battery) @@ -538,6 +534,7 @@ void main_task(void *param) // reset the screen renderer->reset(); // make sure the UI is in the right state + ui_state = MAIN_PAGE; handleUserInteraction(renderer, NONE, true); } @@ -557,9 +554,12 @@ void main_task(void *param) // keep track of when the user last interacted and go to sleep after N seconds rt_tick_t last_user_interaction = rt_tick_get_millisecond(); + // 初始化屏幕模块默认关机超时 + screen_init(TIMEOUT_SHUTDOWN_TIME); -while (rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 *5) //5小时无操作自动关机 -{ + while ((screen_get_timeout_shutdown_hours() == 0) || + (rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 * screen_get_timeout_shutdown_hours())) // 按设置的小时数无操作自动关机;0为不关机 + { // 检查是否超过5分钟无操作,如果是在欢迎页面、充电页面或低电量页面则不跳转 if (rt_tick_get_millisecond() - last_user_interaction >= 60 * 1000 *5 && @@ -687,7 +687,7 @@ extern "C" int main() { // dump out the epub list state - //rt_pm_request(PM_SLEEP_MODE_IDLE); + rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); @@ -701,4 +701,4 @@ extern "C" } return 0; } -} \ No newline at end of file +} From 424e1d3715b10604571a1dcd6973587d405c02c1 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Wed, 14 Jan 2026 16:28:44 +0800 Subject: [PATCH 02/27] =?UTF-8?q?1.=E5=AE=8C=E5=96=84=20=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8C=E4=B9=A6=E5=BA=93=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E7=9B=AE=E5=BD=95=E9=A1=B5=E9=9D=A2=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=AF=B9=E5=BA=94=E4=B8=8B=E6=A0=8F=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=202.=E5=A2=9E=E5=8A=A0=E9=98=85=E8=AF=BB=E8=A6=86=E7=9B=96?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=88=E7=B2=97=E7=B3=99=E7=89=88=EF=BC=9A?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E5=B8=83=E5=B1=80=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E8=BF=9B=E5=85=A5=E5=92=8C=E9=80=80=E5=87=BA=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubList.cpp | 51 ++- epdiy-epub/lib/Epub/EpubList/EpubList.h | 7 + epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 79 +++++ epdiy-epub/lib/Epub/EpubList/EpubReader.h | 11 + epdiy-epub/lib/Epub/EpubList/EpubToc.cpp | 47 ++- epdiy-epub/lib/Epub/EpubList/EpubToc.h | 7 + epdiy-epub/src/boards/controls/Actions.h | 1 + .../boards/controls/SF32_ButtonControls.cpp | 11 +- epdiy-epub/src/epub_screen.cpp | 9 +- epdiy-epub/src/main.cpp | 309 +++++++++++++++--- 10 files changed, 472 insertions(+), 60 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp index 2998a34..2853941 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp @@ -15,7 +15,7 @@ static const char *TAG = "PUBLIST"; #define PADDING 20 -#define EPUBS_PER_PAGE 5 +#define EPUBS_PER_PAGE 4 void EpubList::next() { @@ -128,8 +128,10 @@ void EpubList::render() ulog_d(TAG, "Rendering EPUB list"); // what page are we on? int current_page = state.selected_item / EPUBS_PER_PAGE; - // 计算单元格高度(不再预留底部区域) - int cell_height = (renderer->get_page_height()) / EPUBS_PER_PAGE; + // 计算单元格高度,并为底部按钮预留区域与底部间距 + const int bottom_area_height = 100; // 底部三按钮区域高度 + const int bottom_margin = 30; // 与屏幕底部的间距 + int cell_height = (renderer->get_page_height() - bottom_area_height - bottom_margin) / EPUBS_PER_PAGE; ulog_d(TAG, "Cell height is %d", cell_height); int start_index = current_page * EPUBS_PER_PAGE; int ypos = 0; @@ -203,6 +205,45 @@ void EpubList::render() } state.previous_selected_item = state.selected_item; state.previous_rendered_page = current_page; - - // 移除书库页底部触控开关区域 + // 绘制底部三按钮区域 + int page_w = renderer->get_page_width(); + int page_h = renderer->get_page_height(); + int area_y = page_h - bottom_area_height - bottom_margin; + // 背景 + renderer->fill_rect(0, area_y, page_w, bottom_area_height, 255); + // 三个等宽按钮 + int btn_gap = 10; + int btn_w = (page_w - btn_gap * 4) / 3; + int btn_h = 80; + int btn_y = area_y + (bottom_area_height - btn_h) / 2; + int btn_x0 = btn_gap; // 上一页 + int btn_x1 = btn_gap * 2 + btn_w; // 主页面 + int btn_x2 = btn_gap * 3 + btn_w * 2; // 下一页 + + // 高亮边框:当处于底部模式时,高亮当前选择 + auto draw_button = [&](int x, const char* text, bool selected) + { + if (selected) + { + // 加粗描边,表示选中 + for (int i = 0; i < 5; ++i) + { + renderer->draw_rect(x + i, btn_y + i, btn_w - 2 * i, btn_h - 2 * i, 0); + } + } + else + { + // 非选中用细描边 + renderer->draw_rect(x, btn_y, btn_w, btn_h, 80); + } + int t_w = renderer->get_text_width(text); + int t_h = renderer->get_line_height(); + int tx = x + (btn_w - t_w) / 2; + int ty = btn_y + (btn_h - t_h) / 2; + renderer->draw_text(tx, ty, text, false, true); + }; + + draw_button(btn_x0, "上一页", m_bottom_mode && m_bottom_idx == 0); + draw_button(btn_x1, "主页面", m_bottom_mode && m_bottom_idx == 1); + draw_button(btn_x2, "下一页", m_bottom_mode && m_bottom_idx == 2); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.h b/epdiy-epub/lib/Epub/EpubList/EpubList.h index c70a727..da2c910 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.h @@ -31,9 +31,16 @@ class EpubList EpubListState &state; bool m_needs_redraw = false; TouchControls* touch_controls = nullptr; + // 底部按钮选择状态:是否处于底部按钮选择模式与当前索引(0:上一页,1:主页面,2:下一页) + bool m_bottom_mode = false; + int m_bottom_idx = 1; public: EpubList(Renderer *renderer, EpubListState &state) : renderer(renderer), state(state){}; void setTouchControls(TouchControls* controls) { touch_controls = controls; } + // 设置底部按钮选择状态 + void set_bottom_selection(bool enabled, int idx) { m_bottom_mode = enabled; m_bottom_idx = idx; } + bool is_bottom_mode() const { return m_bottom_mode; } + int bottom_index() const { return m_bottom_idx; } ~EpubList() {} bool load(const char *path); void set_needs_redraw() { m_needs_redraw = true; } diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 5be05ac..dc7b515 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -103,9 +103,88 @@ void EpubReader::render() parser->render_page(state.current_page, renderer, epub); ulog_d(TAG, "rendered page %d of %d", state.current_page, parser->get_page_count()); ulog_d(TAG, "after render: %d", heap_free_size()); + // 绘制半屏覆盖操作层 + if (overlay_active) + { + render_overlay(); + } } void EpubReader::set_state_section(uint16_t current_section) { ulog_i(TAG, "go to section:%d", current_section); state.current_section = current_section; +} + +void EpubReader::render_overlay() +{ + int page_w = renderer->get_page_width(); + int page_h = renderer->get_page_height(); + int area_y = (page_h * 2) / 3; // 覆盖下方 1/3 屏幕 + int area_h = page_h - area_y; + // 半透明效果不可用,使用浅灰底区分 + renderer->fill_rect(0, area_y, page_w, area_h, 240); + + // 三行布局:3,5,3 + const int rows = 3; + const int cols[rows] = {3, 5, 3}; + const int gap_h = 20; // 行间距 + const int gap_w = 10; + const int row_h = 80; // 每行高度 + // 纵向居中放置三行 + int content_h = rows * row_h + (rows + 1) * gap_h; + int y0 = area_y + (area_h - content_h) / 2; + if (y0 < area_y + 4) y0 = area_y + 4; + + int index = 0; + for (int r = 0; r < rows; ++r) + { + int c = cols[r]; + int usable_w = page_w - (c + 1) * gap_w; + int btn_w = usable_w / c; + int y = y0 + gap_h + r * (row_h + gap_h); + for (int i = 0; i < c; ++i) + { + int x = gap_w + i * (btn_w + gap_w); + bool selected = (index == overlay_selected); + if (selected) + { + for (int k = 0; k < 5; ++k) + { + renderer->draw_rect(x + k, y + k, btn_w - 2 * k, row_h - 2 * k, 0); + } + } + else + { + renderer->draw_rect(x, y, btn_w, row_h, 80); + } + // 文本:第9个显示"确认",其余显示编号 + char label[16]; + if (index == 8) + { + rt_snprintf(label, sizeof(label), "确认"); + } + else + { + rt_snprintf(label, sizeof(label), "%d", index + 1); + } + int t_w = renderer->get_text_width(label); + int t_h = renderer->get_line_height(); + int tx = x + (btn_w - t_w) / 2; + int ty = y + (row_h - t_h) / 2; + renderer->draw_text(tx, ty, label, false, true); + index++; + } + } +} + +void EpubReader::overlay_move_left() +{ + if (!overlay_active) return; + overlay_selected = (overlay_selected - 1 + 11) % 11; +} + +void EpubReader::overlay_move_right() +{ + if (!overlay_active) return; + overlay_selected = (overlay_selected + 1) % 11; } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index 5d46081..75f10ae 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -13,8 +13,12 @@ class EpubReader Epub *epub = nullptr; Renderer *renderer = nullptr; RubbishHtmlParser *parser = nullptr; + // 阅读页半屏覆盖操作层状态 + bool overlay_active = false; + int overlay_selected = 0; // 0..10,共11个 void parse_and_layout_current_section(); + void render_overlay(); public: EpubReader(EpubListItem &state, Renderer *renderer) : state(state), renderer(renderer){}; @@ -24,4 +28,11 @@ class EpubReader void prev(); void render(); void set_state_section(uint16_t current_section); + // 覆盖层控制 + void start_overlay() { overlay_active = true; overlay_selected = 0; } + void stop_overlay() { overlay_active = false; } + bool is_overlay_active() const { return overlay_active; } + void overlay_move_left(); + void overlay_move_right(); + int get_overlay_selected() const { return overlay_selected; } }; \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp index 46ca552..c6c5061 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp @@ -60,8 +60,10 @@ void EpubToc::render() ulog_d(TAG, "Rendering EPUB index"); // what page are we on? int current_page = state.selected_item / ITEMS_PER_PAGE; - // show five items per page - int cell_height = renderer->get_page_height() / ITEMS_PER_PAGE; + // 为底部按钮预留区域与底部间距 + const int bottom_area_height = 100; + const int bottom_margin = 30; + int cell_height = (renderer->get_page_height() - bottom_area_height - bottom_margin) / ITEMS_PER_PAGE; int start_index = current_page * ITEMS_PER_PAGE; int ypos = 0; // starting a fresh page or rendering from scratch? @@ -118,6 +120,47 @@ void EpubToc::render() } state.previous_selected_item = state.selected_item; state.previous_rendered_page = current_page; + + // 绘制底部三按钮区域 + int page_w = renderer->get_page_width(); + int page_h = renderer->get_page_height(); + int area_y = page_h - bottom_area_height - bottom_margin; + // 背景 + renderer->fill_rect(0, area_y, page_w, bottom_area_height, 255); + // 三个等宽按钮 + int btn_gap = 10; + int btn_w = (page_w - btn_gap * 4) / 3; // 左右边距各一个gap,再加中间两个gap + int btn_h = 80; + int btn_y = area_y + (bottom_area_height - btn_h) / 2; + int btn_x0 = btn_gap; // 上一页 + int btn_x1 = btn_gap * 2 + btn_w; // 主页面 + int btn_x2 = btn_gap * 3 + btn_w * 2; // 下一页 + + auto draw_button = [&](int x, const char* text, bool selected) + { + if (selected) + { + // 多重描边(黑色),与列表选中效果一致 + for (int i = 0; i < 5; ++i) + { + renderer->draw_rect(x + i, btn_y + i, btn_w - 2 * i, btn_h - 2 * i, 0); + } + } + else + { + // 非选中用细描边(灰色) + renderer->draw_rect(x, btn_y, btn_w, btn_h, 80); + } + int t_w = renderer->get_text_width(text); + int t_h = renderer->get_line_height(); + int tx = x + (btn_w - t_w) / 2; + int ty = btn_y + (btn_h - t_h) / 2; + renderer->draw_text(tx, ty, text, false, true); + }; + + draw_button(btn_x0, "上一页", m_bottom_mode && m_bottom_idx == 0); + draw_button(btn_x1, "书库", m_bottom_mode && m_bottom_idx == 1); + draw_button(btn_x2, "下一页", m_bottom_mode && m_bottom_idx == 2); } uint16_t EpubToc::get_selected_toc() diff --git a/epdiy-epub/lib/Epub/EpubList/EpubToc.h b/epdiy-epub/lib/Epub/EpubList/EpubToc.h index 5ef96a8..56563f0 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubToc.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubToc.h @@ -32,6 +32,9 @@ class EpubToc EpubListItem &selected_epub; EpubTocState &state; bool m_needs_redraw = false; + // 底部按钮选择状态:是否处于底部按钮选择模式与当前索引(0:上一页,1:主页面,2:下一页) + bool m_bottom_mode = false; + int m_bottom_idx = 1; public: EpubToc(EpubListItem &selected_epub, EpubTocState &state, Renderer *renderer) : renderer(renderer), selected_epub(selected_epub), state(state){}; @@ -42,4 +45,8 @@ class EpubToc void render(); void set_needs_redraw() { m_needs_redraw = true; } uint16_t get_selected_toc(); + // 目录项总数 + int get_items_count() const { return epub ? epub->get_toc_items_count() : 0; } + // 设置底部按钮选择状态 + void set_bottom_selection(bool enabled, int idx) { m_bottom_mode = enabled; m_bottom_idx = idx; } }; \ No newline at end of file diff --git a/epdiy-epub/src/boards/controls/Actions.h b/epdiy-epub/src/boards/controls/Actions.h index 785384d..8e83835 100644 --- a/epdiy-epub/src/boards/controls/Actions.h +++ b/epdiy-epub/src/boards/controls/Actions.h @@ -8,6 +8,7 @@ typedef enum UP, DOWN, SELECT, + UPGLIDE, // 长按触发的上滑操作,用于阅读页半屏操作覆盖 LAST_INTERACTION, MSG_DRAW_LOW_POWER_PAGE, MSG_DRAW_CHARGE_PAGE, diff --git a/epdiy-epub/src/boards/controls/SF32_ButtonControls.cpp b/epdiy-epub/src/boards/controls/SF32_ButtonControls.cpp index 91cb956..458343a 100644 --- a/epdiy-epub/src/boards/controls/SF32_ButtonControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_ButtonControls.cpp @@ -12,6 +12,11 @@ void button_event_handler(int32_t pin, button_action_t action) { action_cbk(UIAction::UP); } + else if (action == BUTTON_LONG_PRESSED) + { + rt_kprintf("长按 1"); + action_cbk(UIAction::UPGLIDE); + } } #else if (pin == EPD_KEY1) @@ -28,10 +33,7 @@ void button_event_handler(int32_t pin, button_action_t action) { action_cbk(UIAction::SELECT); } - else if (action == BUTTON_LONG_PRESSED) - { - rt_kprintf("长按 1"); - } + } else if (pin == EPD_KEY3) { @@ -39,6 +41,7 @@ void button_event_handler(int32_t pin, button_action_t action) { action_cbk(UIAction::UP); } + } #endif diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index ede9f23..d58ca7b 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -185,7 +185,8 @@ static void render_settings_page(Renderer *renderer) } if (settings_selected_idx == SET_TOUCH) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + // 选中强化:多重描边,提高可见度 + for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { @@ -213,7 +214,7 @@ static void render_settings_page(Renderer *renderer) } if (settings_selected_idx == SET_TIMEOUT) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { @@ -246,7 +247,7 @@ static void render_settings_page(Renderer *renderer) } if (settings_selected_idx == SET_FULL_REFRESH) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { @@ -270,7 +271,7 @@ static void render_settings_page(Renderer *renderer) int confirm_y = page_h - confirm_h - 60; // 距离底部位置 if (settings_selected_idx == SET_CONFIRM) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(confirm_x + i, confirm_y + i, confirm_w - 2 * i, confirm_h - 2 * i, 0); + for (int i = 0; i < 5; ++i) renderer->draw_rect(confirm_x + i, confirm_y + i, confirm_w - 2 * i, confirm_h - 2 * i, 0); } else { diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index ebe3d87..b765824 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -37,9 +37,9 @@ const char *TAG = "main"; typedef enum { MAIN_PAGE, // 新主页面 - SELECTING_EPUB, - SELECTING_TABLE_CONTENTS, - READING_EPUB, + SELECTING_EPUB, // 电子书列表页面(书库) + SELECTING_TABLE_CONTENTS, // 电子书目录页面 + READING_EPUB, // 阅读页面 SETTINGS_PAGE // 通用功能设置页面 } UIState; typedef enum @@ -60,6 +60,7 @@ EpubTocState epub_index_state; void handleEpub(Renderer *renderer, UIAction action); void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw); +void back_to_main_page(); static EpubList *epub_list = nullptr; static EpubReader *reader = nullptr; @@ -70,6 +71,10 @@ Battery *battery = nullptr; Renderer *renderer = nullptr; TouchControls *touch_controls = nullptr; +// 书库页底部按钮选择状态 +static bool library_bottom_mode = false; // 是否处于底部三按钮选择模式 +static int library_bottom_idx = 1; // 当前底部按钮索引:0上一页,1主页面,2下一页 + rt_mq_t ui_queue = RT_NULL; // 主页面选项 @@ -89,34 +94,64 @@ void handleEpub(Renderer *renderer, UIAction action) switch (action) { case UP: - reader->prev(); + if (reader->is_overlay_active()) + { + reader->overlay_move_left(); + } + else + { + reader->prev(); + } break; case DOWN: - reader->next(); + if (reader->is_overlay_active()) + { + reader->overlay_move_right(); + } + else + { + reader->next(); + } break; case SELECT: - - // switch back to main screen - ui_state = SELECTING_EPUB; - renderer->clear_screen(); - // clear the epub reader away - delete reader; - reader = nullptr; - // force a redraw - if (!epub_list) + if (reader->is_overlay_active()) { - epub_list = new EpubList(renderer, epub_list_state); + // 在覆盖层中,SELECT仅作用于覆盖区域:当选中"确认"时关闭覆盖层 + if (reader->get_overlay_selected() == 8) + { + reader->stop_overlay(); + } + // 非“确认”暂不执行其他操作 } - handleEpubList(renderer, NONE, true); + else + { + // switch back to main screen + ui_state = SELECTING_EPUB; + renderer->clear_screen(); + // clear the epub reader away + delete reader; + reader = nullptr; + // force a redraw + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + handleEpubList(renderer, NONE, true); - return; + return; + } + break; + case UPGLIDE: + // 激活阅读页下半屏覆盖操作层 + reader->start_overlay(); + break; case NONE: default: break; } reader->render(); } - +//目录页的处理 void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw) { if (!contents) @@ -125,32 +160,122 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red contents->set_needs_redraw(); contents->load(); } + static bool toc_bottom_mode = false; + static int toc_bottom_idx = 1; // 0:上一页,1:主页面,2:下一页 + if (needs_redraw) + { + toc_bottom_mode = false; + toc_bottom_idx = 1; + } switch (action) { case UP: - contents->prev(); + if (toc_bottom_mode) + { + toc_bottom_idx = (toc_bottom_idx + 2) % 3; // 左移 + } + else + { + int per_page = 6; + int start_idx = (epub_index_state.selected_item / per_page) * per_page; + if (contents->get_items_count() > 0 && epub_index_state.selected_item == start_idx) + { + toc_bottom_mode = true; + } + else + { + contents->prev(); + } + } break; case DOWN: - contents->next(); + if (toc_bottom_mode) + { + toc_bottom_idx = (toc_bottom_idx + 1) % 3; // 右移 + } + else + { + int per_page = 6; + int start_idx = (epub_index_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + int count = contents->get_items_count(); + if (end_idx >= count) end_idx = count - 1; + if (count > 0 && epub_index_state.selected_item == end_idx) + { + toc_bottom_mode = true; + } + else + { + contents->next(); + } + } break; case SELECT: - // setup the reader state - ui_state = READING_EPUB; - // create the reader and load the book - reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); - reader->set_state_section(contents->get_selected_toc()); - reader->load(); - //switch to reading the epub - delete contents; - handleEpub(renderer, NONE); - return; + if (toc_bottom_mode) + { + int per_page = 6; + int count = contents->get_items_count(); + int current_page = (count > 0) ? (epub_index_state.selected_item / per_page) : 0; + int max_page = (count == 0) ? 0 : ((count - 1) / per_page); + if (toc_bottom_idx == 1) + { + // 书库:切换到书库页面 + rt_kprintf("从目录页返回书库页\n"); + ui_state = SELECTING_EPUB; + if (contents) + { + delete contents; + contents = nullptr; + } + handleEpubList(renderer, NONE, true); + return; + } + else if (toc_bottom_idx == 0) + { + // 上一页 + if (current_page > 0) + { + epub_index_state.selected_item -= per_page; + if (epub_index_state.selected_item < 0) epub_index_state.selected_item = 0; + contents->set_needs_redraw(); + } + toc_bottom_mode = false; + } + else if (toc_bottom_idx == 2) + { + // 下一页 + if (current_page < max_page) + { + epub_index_state.selected_item += per_page; + if (epub_index_state.selected_item >= count) + epub_index_state.selected_item = count - 1; + contents->set_needs_redraw(); + } + toc_bottom_mode = false; + } + } + else + { + // 进入阅读界面 + ui_state = READING_EPUB; + reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); + reader->set_state_section(contents->get_selected_toc()); + reader->load(); + delete contents; + handleEpub(renderer, NONE); + return; + } + break; case NONE: default: break; } + // 将底部选择状态传递给目录渲染 + contents->set_bottom_selection(toc_bottom_mode, toc_bottom_idx); contents->render(); } +//书库页的处理 void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) { // load up the epub list from the filesystem @@ -167,31 +292,114 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (needs_redraw) { epub_list->set_needs_redraw(); + // 进入书库页时重置底部选择状态 + library_bottom_mode = false; + library_bottom_idx = 1; } // work out what the user wants us to do switch (action) { case UP: - epub_list->prev(); + if (library_bottom_mode) + { + // UP 表示向左选择 + library_bottom_idx = (library_bottom_idx + 2) % 3; + } + else + { + // 若处于当前页第一个条目,UP 切换到底部按钮模式 + int per_page = 4; + int start_idx = (epub_list_state.selected_item / per_page) * per_page; + if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == start_idx) + { + library_bottom_mode = true; + } + else + { + epub_list->prev(); + } + } break; case DOWN: - epub_list->next(); + if (library_bottom_mode) + { + // DOWN 表示向右选择 + library_bottom_idx = (library_bottom_idx + 1) % 3; + } + else + { + int per_page = 4; + int start_idx = (epub_list_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; + // 若处于当前页最后一个条目,DOWN 切换到底部按钮模式 + if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == end_idx) + { + library_bottom_mode = true; + } + else + { + epub_list->next(); + } + } break; case SELECT: - // switch to reading the epub - // setup the reader state - ui_state = SELECTING_TABLE_CONTENTS; - // create the reader and load the book - contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); - contents->load(); - contents->set_needs_redraw(); - handleEpubTableContents(renderer, NONE, true); - return; + if (library_bottom_mode) + { + int per_page = 4; + int current_page = epub_list_state.selected_item / per_page; + int max_page = (epub_list_state.num_epubs == 0) ? 0 : ( (epub_list_state.num_epubs - 1) / per_page ); + if (library_bottom_idx == 1) + { + // 主页面:返回主页面 + rt_kprintf("从书库页返回主页面\n"); + back_to_main_page(); + return; + } + else if (library_bottom_idx == 0) + { + // 上一页 + if (current_page > 0) + { + epub_list_state.selected_item -= per_page; + if (epub_list_state.selected_item < 0) epub_list_state.selected_item = 0; + epub_list->set_needs_redraw(); + } + // 切回条目选择模式 + library_bottom_mode = false; + } + else if (library_bottom_idx == 2) + { + // 下一页 + if (current_page < max_page) + { + epub_list_state.selected_item += per_page; + if (epub_list_state.selected_item >= epub_list_state.num_epubs) + epub_list_state.selected_item = epub_list_state.num_epubs - 1; + epub_list->set_needs_redraw(); + } + // 切回条目选择模式 + library_bottom_mode = false; + } + } + else + { + // 进入目录选择页面 + ui_state = SELECTING_TABLE_CONTENTS; + contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); + contents->load(); + contents->set_needs_redraw(); + handleEpubTableContents(renderer, NONE, true); + return; + } + break; case NONE: default: // nothing to do break; } + // 将底部选择状态传递给列表渲染 + epub_list->set_bottom_selection(library_bottom_mode, library_bottom_idx); epub_list->render(); } // TODO - add the battery level @@ -275,10 +483,20 @@ void handleUserInteraction(Renderer *renderer, UIAction ui_action, bool needs_re { case MAIN_PAGE: // 新主页面 handleMainPage(renderer, ui_action, needs_redraw); - if (ui_action == SELECT && screen_get_main_selected_option() == 2) + if (ui_action == SELECT && screen_get_main_selected_option() == 2) //切换到设置页面 { ui_state = SETTINGS_PAGE; - (void)handleSettingsPage(renderer, NONE, true); + (void)handleSettingsPage(renderer, NONE, true); + } + else if (ui_action == SELECT && screen_get_main_selected_option() == 1) //切换到阅读页面 + { + // ui_state = READING_EPUB; + // handleEpub(renderer, NONE); + } + else if (ui_action == SELECT && screen_get_main_selected_option() == 0) //切换到书库页面 + { + ui_state = SELECTING_EPUB; + handleEpubList(renderer, NONE, true); } break; case READING_EPUB: //阅读界面 @@ -322,8 +540,9 @@ const char* getCurrentPageName() { //回到主界面接口 void back_to_main_page() { - if (strcmp(getCurrentPageName(), "MAIN_MENU") == 0) + if (ui_state == MAIN_PAGE) { + rt_kprintf("已经在主页面,无需返回\n"); return; } lowpower_ui_state = MAIN_MENU; @@ -389,7 +608,7 @@ void draw_welcome_page(Battery *battery) } -// 绘制低电量页面 +// 低电量页面 void draw_low_power_page(Battery *battery) { if (strcmp(getCurrentPageName(), "LOW_POWER_PAGE") == 0) From c3c4907e896d4f9f40bb009b6b21e3d546009616 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Wed, 14 Jan 2026 17:58:27 +0800 Subject: [PATCH 03/27] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=98=85=E8=AF=BB?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2=EF=BC=9A1.=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20=E7=9B=AE=E5=BD=95=E9=A1=B5=E9=9D=A2=20=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=20=E4=B9=A6=E5=BA=93=E9=A1=B5=E9=9D=A2=E7=9A=84?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=8A=9F=E8=83=BD=202.=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=B4=AF=E7=A7=AF=E8=B7=B3=E8=BD=AC=E9=A1=B5=E9=9D=A2=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 70 ++++++++++++++++++--- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 8 ++- epdiy-epub/src/main.cpp | 56 +++++++++++++++-- 3 files changed, 122 insertions(+), 12 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index dc7b515..a13ace7 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -157,15 +157,24 @@ void EpubReader::render_overlay() { renderer->draw_rect(x, y, btn_w, row_h, 80); } - // 文本:第9个显示"确认",其余显示编号 + // 文本映射: + // 1:"<" 2:保留原编号 3:">" 4:"-5" 5:"-1" 6:"acc" 7:"+1" 8:"+5" 9:"确认" 10:"目录" 11:"书库" char label[16]; - if (index == 8) + switch (index) { - rt_snprintf(label, sizeof(label), "确认"); - } - else - { - rt_snprintf(label, sizeof(label), "%d", index + 1); + case 0: rt_snprintf(label, sizeof(label), "<"); break; + case 1: rt_snprintf(label, sizeof(label), "2"); break; + case 2: rt_snprintf(label, sizeof(label), ">"); break; + case 3: rt_snprintf(label, sizeof(label), "-5"); break; + case 4: rt_snprintf(label, sizeof(label), "-1"); break; + case 5: rt_snprintf(label, sizeof(label), "%d", overlay_jump_acc); break; + case 6: rt_snprintf(label, sizeof(label), "+1"); break; + case 7: rt_snprintf(label, sizeof(label), "+5"); break; + case 8: rt_snprintf(label, sizeof(label), "确认"); break; + case 9: rt_snprintf(label, sizeof(label), "目录"); break; + case 10: rt_snprintf(label, sizeof(label), "书库"); break; + default: + break; } int t_w = renderer->get_text_width(label); int t_h = renderer->get_line_height(); @@ -187,4 +196,51 @@ void EpubReader::overlay_move_right() { if (!overlay_active) return; overlay_selected = (overlay_selected + 1) % 11; +} + +void EpubReader::jump_pages(int delta) +{ + if (delta == 0) return; + if (!parser) //没解析的情况下 则解析当前节 + { + parse_and_layout_current_section(); + } + int spine_count = epub ? epub->get_spine_items_count() : 0; //获取章节总数 + if (spine_count <= 0) return; + + auto at_book_start = [&]() -> bool { + return state.current_section == 0 && state.current_page == 0; + }; + auto at_book_end = [&]() -> bool { + // 需要知道当前节页数;parser 非空时有效 + if (!parser) return false; + return (state.current_section == spine_count - 1) && (state.current_page >= state.pages_in_current_section - 1); + }; + // 开始实现页面跳转 + if (delta > 0) + { + for (int i = 0; i < delta; ++i) + { + if (at_book_end()) break; + next(); + // 如果跨节,parser 在 next() 时会置空;后续渲染时会自动 parse + if (!parser) + { + parse_and_layout_current_section(); + } + } + } + else // delta < 0 + { + for (int i = 0; i < -delta; ++i) + { + if (at_book_start()) break; + prev(); + if (!parser) + { + //空则解析 + parse_and_layout_current_section(); + } + } + } } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index 75f10ae..1ceebe8 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -16,6 +16,7 @@ class EpubReader // 阅读页半屏覆盖操作层状态 bool overlay_active = false; int overlay_selected = 0; // 0..10,共11个 + int overlay_jump_acc = 0; // 覆盖层累积跳页值(可为负) void parse_and_layout_current_section(); void render_overlay(); @@ -26,13 +27,18 @@ class EpubReader bool load(); void next(); void prev(); + void jump_pages(int delta); void render(); void set_state_section(uint16_t current_section); // 覆盖层控制 - void start_overlay() { overlay_active = true; overlay_selected = 0; } + void start_overlay() { overlay_active = true; overlay_selected = 0; overlay_jump_acc = 0; } void stop_overlay() { overlay_active = false; } bool is_overlay_active() const { return overlay_active; } void overlay_move_left(); void overlay_move_right(); int get_overlay_selected() const { return overlay_selected; } + // 覆盖层跳页累积控制 + void overlay_add_jump(int d) { overlay_jump_acc += d; } + void overlay_reset_jump() { overlay_jump_acc = 0; } + int overlay_get_jump() const { return overlay_jump_acc; } }; \ No newline at end of file diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index b765824..adaecd9 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -83,7 +83,7 @@ typedef enum { OPTION_CONTINUE_READING, // 继续阅读 -> 打印 2 OPTION_ENTER_SETTINGS // 进入设置 -> 打印 3 } MainOption; - +void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw); void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -116,12 +116,60 @@ void handleEpub(Renderer *renderer, UIAction action) case SELECT: if (reader->is_overlay_active()) { - // 在覆盖层中,SELECT仅作用于覆盖区域:当选中"确认"时关闭覆盖层 - if (reader->get_overlay_selected() == 8) + int sel = reader->get_overlay_selected(); + if (sel == 9) //目录 { + ui_state = SELECTING_TABLE_CONTENTS; reader->stop_overlay(); + delete reader; + reader = nullptr; + contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); + contents->load(); + contents->set_needs_redraw(); + handleEpubTableContents(renderer, NONE, true); + return; } - // 非“确认”暂不执行其他操作 + else if (sel == 8) //确认:1.按第六格累积值跳页 + { + int delta = reader->overlay_get_jump(); + if (delta != 0) + { + reader->jump_pages(delta); + } + reader->overlay_reset_jump(); + reader->stop_overlay(); + } + else if (sel == 10) //书库 + { + ui_state = SELECTING_EPUB; + reader->stop_overlay(); + renderer->clear_screen(); + delete reader; + reader = nullptr; + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + handleEpubList(renderer, NONE, true); + return; + } + else if (sel == 3) + { + reader->overlay_add_jump(-5); + } + else if (sel == 4) + { + reader->overlay_add_jump(-1); + } + else if (sel == 6) + { + reader->overlay_add_jump(1); + } + else if (sel == 7) + { + reader->overlay_add_jump(5); + } + } else { From 6116910587ea2b48a29ee4318ae81c89e028762d Mon Sep 17 00:00:00 2001 From: smiling boy Date: Thu, 15 Jan 2026 11:22:33 +0800 Subject: [PATCH 04/27] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=98=85=E8=AF=BB?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E9=A1=B5=EF=BC=9A1=EF=BC=8C2=EF=BC=8C3?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E7=9F=A9=E5=BD=A2=E5=AE=9E=E7=8E=B0=20?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E8=A7=A6=E6=8E=A7=20=E4=B8=8E=20=E5=85=A8?= =?UTF-8?q?=E5=88=B7=E5=91=A8=E6=9C=9F=E6=AC=A1=E6=95=B0=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=8A=9F=E8=83=BD=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2=EF=BC=9A=E5=85=A8=E5=88=B7?= =?UTF-8?q?=E5=91=A8=E6=9C=9F=E6=AC=A1=E6=95=B0=E5=8A=A8=E6=80=81=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 125 +++++++++++++++----- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 15 +++ epdiy-epub/src/epub_screen.cpp | 42 ++++++- epdiy-epub/src/epub_screen.h | 5 +- epdiy-epub/src/main.cpp | 46 +++++++ 5 files changed, 202 insertions(+), 31 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index a13ace7..c885238 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -12,6 +12,7 @@ #include "../RubbishHtmlParser/RubbishHtmlParser.h" #include "../Renderer/Renderer.h" #include "epub_mem.h" +#include "epub_screen.h" static const char *TAG = "EREADER"; extern "C" rt_uint32_t heap_free_size(void); @@ -121,7 +122,7 @@ void EpubReader::render_overlay() int page_h = renderer->get_page_height(); int area_y = (page_h * 2) / 3; // 覆盖下方 1/3 屏幕 int area_h = page_h - area_y; - // 半透明效果不可用,使用浅灰底区分 + renderer->fill_rect(0, area_y, page_w, area_h, 240); // 三行布局:3,5,3 @@ -136,15 +137,86 @@ void EpubReader::render_overlay() if (y0 < area_y + 4) y0 = area_y + 4; int index = 0; + auto fill_label = [&](int idx, char *label, size_t cap) { + switch (idx) + { + case 0: rt_snprintf(label, cap, "<"); break; + case 1: + { + if (overlay_center_mode == CENTER_TOUCH) + { + rt_snprintf(label, cap, "触摸开关:%s", overlay_touch_enabled ? "开" : "关"); + } + else + { + int v = overlay_get_full_refresh_value(); + if (v == 0) + rt_snprintf(label, cap, "全刷周期:不刷新"); + else + rt_snprintf(label, cap, "全刷周期:%d次", v); + } + break; + } + case 2: rt_snprintf(label, cap, ">"); break; + case 3: rt_snprintf(label, cap, "-5"); break; + case 4: rt_snprintf(label, cap, "-1"); break; + case 5: rt_snprintf(label, cap, "%d", overlay_jump_acc); break; + case 6: rt_snprintf(label, cap, "+1"); break; + case 7: rt_snprintf(label, cap, "+5"); break; + case 8: rt_snprintf(label, cap, "确认"); break; + case 9: rt_snprintf(label, cap, "目录"); break; + case 10: rt_snprintf(label, cap, "书库"); break; + default: label[0] = '\0'; break; + } + }; for (int r = 0; r < rows; ++r) { int c = cols[r]; - int usable_w = page_w - (c + 1) * gap_w; - int btn_w = usable_w / c; int y = y0 + gap_h + r * (row_h + gap_h); - for (int i = 0; i < c; ++i) + // 顶部第1行(3列)采用不等宽布局:1/3半宽,2双宽 + if (r == 0) { - int x = gap_w + i * (btn_w + gap_w); + int usable_w = page_w - (c + 1) * gap_w; + // 宽度权重为 1:3:1(约 左20% / 中60% / 右20%) + int w0 = (usable_w * 1) / 5; + int w1 = (usable_w * 3) / 5; + int w2 = usable_w - w0 - w1; + int widths[3] = { w0, w1, w2 }; + int cur_x = gap_w; + for (int i = 0; i < c; ++i) + { + int w = widths[i]; + int x = cur_x; + bool selected = (index == overlay_selected); + if (selected) + { + for (int k = 0; k < 5; ++k) + { + renderer->draw_rect(x + k, y + k, w - 2 * k, row_h - 2 * k, 0); + } + } + else + { + renderer->draw_rect(x, y, w, row_h, 80); + } + char label[32]; + fill_label(index, label, sizeof(label)); + int t_w = renderer->get_text_width(label); + int t_h = renderer->get_line_height(); + int tx = x + (w - t_w) / 2; + int ty = y + (row_h - t_h) / 2; + renderer->draw_text(tx, ty, label, false, true); + index++; + cur_x = x + w + gap_w; + } + } + else + { + int usable_w = page_w - (c + 1) * gap_w; + int btn_w = usable_w / c; + for (int i = 0; i < c; ++i) + { + int x = gap_w + i * (btn_w + gap_w); bool selected = (index == overlay_selected); if (selected) { @@ -157,31 +229,15 @@ void EpubReader::render_overlay() { renderer->draw_rect(x, y, btn_w, row_h, 80); } - // 文本映射: - // 1:"<" 2:保留原编号 3:">" 4:"-5" 5:"-1" 6:"acc" 7:"+1" 8:"+5" 9:"确认" 10:"目录" 11:"书库" - char label[16]; - switch (index) - { - case 0: rt_snprintf(label, sizeof(label), "<"); break; - case 1: rt_snprintf(label, sizeof(label), "2"); break; - case 2: rt_snprintf(label, sizeof(label), ">"); break; - case 3: rt_snprintf(label, sizeof(label), "-5"); break; - case 4: rt_snprintf(label, sizeof(label), "-1"); break; - case 5: rt_snprintf(label, sizeof(label), "%d", overlay_jump_acc); break; - case 6: rt_snprintf(label, sizeof(label), "+1"); break; - case 7: rt_snprintf(label, sizeof(label), "+5"); break; - case 8: rt_snprintf(label, sizeof(label), "确认"); break; - case 9: rt_snprintf(label, sizeof(label), "目录"); break; - case 10: rt_snprintf(label, sizeof(label), "书库"); break; - default: - break; - } + char label[32]; + fill_label(index, label, sizeof(label)); int t_w = renderer->get_text_width(label); int t_h = renderer->get_line_height(); int tx = x + (btn_w - t_w) / 2; int ty = y + (row_h - t_h) / 2; renderer->draw_text(tx, ty, label, false, true); index++; + } } } } @@ -208,11 +264,14 @@ void EpubReader::jump_pages(int delta) int spine_count = epub ? epub->get_spine_items_count() : 0; //获取章节总数 if (spine_count <= 0) return; - auto at_book_start = [&]() -> bool { + //检查是不是第一页 + auto at_book_start = [&]() -> bool + { return state.current_section == 0 && state.current_page == 0; }; - auto at_book_end = [&]() -> bool { - // 需要知道当前节页数;parser 非空时有效 + //检查是不是最后一页 + auto at_book_end = [&]() -> bool + { if (!parser) return false; return (state.current_section == spine_count - 1) && (state.current_page >= state.pages_in_current_section - 1); }; @@ -238,9 +297,19 @@ void EpubReader::jump_pages(int delta) prev(); if (!parser) { - //空则解析 + //空就解析 parse_and_layout_current_section(); } } } +} + +void EpubReader::overlay_cycle_full_refresh() +{ + screen_cycle_full_refresh_period(); +} + +int EpubReader::overlay_get_full_refresh_value() const +{ + return screen_get_full_refresh_period(); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index 1ceebe8..355278f 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -17,6 +17,13 @@ class EpubReader bool overlay_active = false; int overlay_selected = 0; // 0..10,共11个 int overlay_jump_acc = 0; // 覆盖层累积跳页值(可为负) + // 覆盖层中心属性模式:触控开关 或 全刷周期 + enum OverlayCenterMode { CENTER_TOUCH = 0, CENTER_FULL_REFRESH = 1 }; + OverlayCenterMode overlay_center_mode = CENTER_TOUCH; + // 触控开关当前状态(由上层同步) + bool overlay_touch_enabled = false; + // 全刷周期索引:0->5, 1->10, 2->20, 3->不刷新(0) + int overlay_fr_idx = 0; void parse_and_layout_current_section(); void render_overlay(); @@ -41,4 +48,12 @@ class EpubReader void overlay_add_jump(int d) { overlay_jump_acc += d; } void overlay_reset_jump() { overlay_jump_acc = 0; } int overlay_get_jump() const { return overlay_jump_acc; } + // 覆盖层中心属性控制 + void overlay_set_center_mode_touch() { overlay_center_mode = CENTER_TOUCH; } + void overlay_set_center_mode_full_refresh() { overlay_center_mode = CENTER_FULL_REFRESH; } + bool overlay_is_center_touch() const { return overlay_center_mode == CENTER_TOUCH; } + void overlay_set_touch_enabled(bool en) { overlay_touch_enabled = en; } + bool overlay_get_touch_enabled() const { return overlay_touch_enabled; } + void overlay_cycle_full_refresh(); + int overlay_get_full_refresh_value() const; }; \ No newline at end of file diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index d58ca7b..1750d5d 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -13,7 +13,34 @@ typedef enum } MainOption; static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” -static int full_refresh_period = 10; // 全刷周期次数,仅用于设置页显示 +// 全刷周期选项:5、10、20、不刷新(0) +static const int kFullRefreshOptions[] = {5, 10, 20, 0}; +static const int kFullRefreshOptionsCount = sizeof(kFullRefreshOptions) / sizeof(kFullRefreshOptions[0]); +static int full_refresh_idx = 1; // 默认10次 + +// 获取当前全刷周期值 +int screen_get_full_refresh_period() +{ + return kFullRefreshOptions[full_refresh_idx]; +} + +// 切换全刷周期(循环) +void screen_cycle_full_refresh_period() +{ + full_refresh_idx = (full_refresh_idx + 1) % kFullRefreshOptionsCount; // ?% 4 +} + +// 设置全刷周期索引 +void screen_set_full_refresh_idx(int idx) +{ + if (idx >= 0 && idx < kFullRefreshOptionsCount) full_refresh_idx = idx; +} + +// 获取当前全刷周期索引 +int screen_get_full_refresh_idx() +{ + return full_refresh_idx; +} // 设置页列表项 typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; @@ -254,7 +281,11 @@ static void render_settings_page(Renderer *renderer) renderer->draw_rect(item_x, y, item_w, item_h, 0); } char buf3[64]; - rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", full_refresh_period); + int fr_val = screen_get_full_refresh_period(); + if (fr_val == 0) + rt_snprintf(buf3, sizeof(buf3), "全刷周期:不刷新"); + else + rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", fr_val); { int t3_w = renderer->get_text_width(buf3); int tx = item_x + (item_w - t3_w) / 2; @@ -345,6 +376,13 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) render_settings_page(renderer); break; } + if (settings_selected_idx == SET_FULL_REFRESH) + { + // SELECT 在全刷周期项上为加操作(循环) + screen_cycle_full_refresh_period(); + render_settings_page(renderer); + break; + } if (settings_selected_idx == SET_CONFIRM) { // 由上层切回主页面 diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h index c97c3c4..a1b589d 100644 --- a/epdiy-epub/src/epub_screen.h +++ b/epdiy-epub/src/epub_screen.h @@ -21,4 +21,7 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw); // 设置页面交互与渲染;返回 true 表示确认并退出到主页面 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw); - +// 切换全刷周期(循环) +void screen_cycle_full_refresh_period(); +// 获取当前全刷周期值 +int screen_get_full_refresh_period(); \ No newline at end of file diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index adaecd9..8e34237 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -117,6 +117,48 @@ void handleEpub(Renderer *renderer, UIAction action) if (reader->is_overlay_active()) { int sel = reader->get_overlay_selected(); + // 1/3:改变中心属性;2:执行当前属性(触控取反 / 全刷周期循环) + if (sel == 0) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + } + else if (sel == 2) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + + } + else if (sel == 1) + { + // 中心矩形:根据当前属性执行 + if (reader->overlay_is_center_touch()) + { + bool cur = touch_controls ? touch_controls->isTouchEnabled() : false; + if (touch_controls) + { + touch_controls->setTouchEnable(!cur); + if (!cur) touch_controls->powerOnTouch(); else touch_controls->powerOffTouch(); + } + reader->overlay_set_touch_enabled(!cur); + } + else + { + reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/不刷新 之间循环 + } + } if (sel == 9) //目录 { ui_state = SELECTING_TABLE_CONTENTS; @@ -192,6 +234,10 @@ void handleEpub(Renderer *renderer, UIAction action) case UPGLIDE: // 激活阅读页下半屏覆盖操作层 reader->start_overlay(); + // 默认中心属性为触控开关,初始同步当前触控状态 + reader->overlay_set_center_mode_touch(); + if (touch_controls) + reader->overlay_set_touch_enabled(touch_controls->isTouchEnabled()); break; case NONE: default: From 3379f5b239e7ef74da4735216eb98e8ae99fb407 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Thu, 15 Jan 2026 16:33:03 +0800 Subject: [PATCH 05/27] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=85=A8=E5=88=B7=E5=91=A8=E6=9C=9F=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 2 +- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 2 +- .../src/boards/display_dbi/epd_display.c | 27 ++++++++++++++++ .../src/boards/display_spi/epd_display.c | 32 +++++++++++++------ epdiy-epub/src/epub_screen.cpp | 9 ++++-- epdiy-epub/src/main.cpp | 5 ++- 6 files changed, 62 insertions(+), 15 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index c885238..90685cb 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -151,7 +151,7 @@ void EpubReader::render_overlay() { int v = overlay_get_full_refresh_value(); if (v == 0) - rt_snprintf(label, cap, "全刷周期:不刷新"); + rt_snprintf(label, cap, "全刷周期:每次"); else rt_snprintf(label, cap, "全刷周期:%d次", v); } diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index 355278f..a5a71b0 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -22,7 +22,7 @@ class EpubReader OverlayCenterMode overlay_center_mode = CENTER_TOUCH; // 触控开关当前状态(由上层同步) bool overlay_touch_enabled = false; - // 全刷周期索引:0->5, 1->10, 2->20, 3->不刷新(0) + // 全刷周期索引:0->5, 1->10, 2->20, 3->每次(0) int overlay_fr_idx = 0; void parse_and_layout_current_section(); diff --git a/epdiy-epub/src/boards/display_dbi/epd_display.c b/epdiy-epub/src/boards/display_dbi/epd_display.c index 2bd6d80..cd32c84 100644 --- a/epdiy-epub/src/boards/display_dbi/epd_display.c +++ b/epdiy-epub/src/boards/display_dbi/epd_display.c @@ -91,6 +91,9 @@ static uint32_t wait_lcd_ticks; static uint16_t epic_out_buffer_idx = 0; static uint16_t epic_out_buffer[2][LCD_HOR_RES_MAX]; static uint32_t lut_copy_ticks; + +static int g_part_disp_times = 10; // After g_part_disp_times-1 partial refreshes, perform a full refresh once +static int reflesh_times = 0; // Total number of refreshes performed /* Define a mixed grey framebuffer on PSRAM high 4 bits for old pixel and low 4 bits for new pixel in every byte. @@ -525,6 +528,15 @@ void epd_load_and_send_pic(LCDC_HandleTypeDef *hlcdc, uint32_t line_type, const } } +void set_part_disp_times(int val) +{ + g_part_disp_times = val > 0 ? val : 1; + reflesh_times = 1; +} +int get_part_disp_times(void) +{ + return g_part_disp_times; +} #define PART_DISP_TIMES 10 static uint32_t reflesh_times = 0; @@ -557,6 +569,19 @@ L1_RET_CODE_SECT(epd_codes, static void LCD_WriteMultiplePixels(LCDC_HandleTypeD uint8_t temperature = 26; + EpdDrawMode mode; + if (reflesh_times % g_part_disp_times == 0) + { + rt_kprintf("cleared all \n"); + mode = EPD_DRAW_MODE_FULL; + } + else + { + rt_kprintf("executing partial refresh, this is the %dth partial refresh (there are %d partial refreshes left until the next full refresh)\n", + (reflesh_times % g_part_disp_times), + g_part_disp_times - (reflesh_times % g_part_disp_times)); + mode = EPD_DRAW_MODE_PARTIAL; + } if (reflesh_times % PART_DISP_TIMES == 0) { frame_times = epd_wave_table_get_frames(temperature, EPD_DRAW_MODE_FULL); @@ -673,6 +698,8 @@ L1_RET_CODE_SECT(epd_codes, static void LCD_WriteMultiplePixels(LCDC_HandleTypeD rt_tick_get() - start_tick, wait_lcd_ticks / 240, lut_copy_ticks / 240); + reflesh_times++; + EPD_GMODE_L_hs(); EPD_STV_L_hs(); TPS_WAKEUP_L_hs(); diff --git a/epdiy-epub/src/boards/display_spi/epd_display.c b/epdiy-epub/src/boards/display_spi/epd_display.c index 60860bd..09f0563 100644 --- a/epdiy-epub/src/boards/display_spi/epd_display.c +++ b/epdiy-epub/src/boards/display_spi/epd_display.c @@ -47,10 +47,11 @@ #define REG_VDCS 0x82 #define REG_WRITE_NEW_DATA 0x13 -static int reflesh_times; +static int reflesh_times = 0; static uint8_t current_refresh_mode; static unsigned char LUT_Flag = 0; // LUT切换标志 static unsigned char Var_Temp = 0; // 温度值 +static int g_part_disp_times = 10; // After g_part_disp_times-1 partial refreshes, perform a full refresh once static LCDC_InitTypeDef lcdc_int_cfg = { .lcd_itf = LCDC_INTF_SPI_DCX_1DATA, @@ -79,6 +80,16 @@ static void EPD_LoadLUT(LCDC_HandleTypeDef *hlcdc, uint8_t lut_mode); static rt_sem_t epd_busy_sem = RT_NULL; +void set_part_disp_times(int val) +{ + g_part_disp_times = val > 0 ? val : 1; + reflesh_times = 1; +} +int get_part_disp_times(void) +{ + return g_part_disp_times; +} + static void epd_busy_callback(void *args) { rt_sem_release(epd_busy_sem); @@ -123,18 +134,19 @@ static void EPD_ReadBusy(void) } static uint8_t epd_get_refresh_mode(void) { - uint8_t mode = 2; // 默认局刷(DU模式) - - if (reflesh_times % PART_DISP_TIMES == 0) + uint8_t mode; + if (reflesh_times % g_part_disp_times == 0) { - mode = 1; // 全刷(GC模式) - } - - if (Var_Temp < 0 || Var_Temp > 50) + rt_kprintf("cleared all \n"); + mode = 1; //全刷 + } + else { - mode = 1; + rt_kprintf("executing partial refresh, this is the %dth partial refresh (there are %d partial refreshes left until the next full refresh)\n", + (reflesh_times % g_part_disp_times), + g_part_disp_times - (reflesh_times % g_part_disp_times)); + mode = 2; //局刷 } - current_refresh_mode = mode; return mode; } diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index 1750d5d..fbfdc7e 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -3,6 +3,10 @@ extern TouchControls *touch_controls; +extern "C" +{ + extern void set_part_disp_times(int val); +} // 主页面选项 typedef enum @@ -13,7 +17,7 @@ typedef enum } MainOption; static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” -// 全刷周期选项:5、10、20、不刷新(0) +// 全刷周期选项:5、10、20、每次(0) static const int kFullRefreshOptions[] = {5, 10, 20, 0}; static const int kFullRefreshOptionsCount = sizeof(kFullRefreshOptions) / sizeof(kFullRefreshOptions[0]); static int full_refresh_idx = 1; // 默认10次 @@ -283,7 +287,7 @@ static void render_settings_page(Renderer *renderer) char buf3[64]; int fr_val = screen_get_full_refresh_period(); if (fr_val == 0) - rt_snprintf(buf3, sizeof(buf3), "全刷周期:不刷新"); + rt_snprintf(buf3, sizeof(buf3), "全刷周期:每次"); else rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", fr_val); { @@ -380,6 +384,7 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) { // SELECT 在全刷周期项上为加操作(循环) screen_cycle_full_refresh_period(); + set_part_disp_times(screen_get_full_refresh_period()); render_settings_page(renderer); break; } diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 8e34237..7d020f9 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -25,6 +25,7 @@ extern "C" { int main(); rt_uint32_t heap_free_size(void); + extern void set_part_disp_times(int val); extern const uint8_t low_power_map[]; extern const uint8_t chargeing_map[]; extern const uint8_t welcome_map[]; @@ -84,6 +85,7 @@ typedef enum { OPTION_ENTER_SETTINGS // 进入设置 -> 打印 3 } MainOption; void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw); + void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -156,7 +158,8 @@ void handleEpub(Renderer *renderer, UIAction action) } else { - reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/不刷新 之间循环 + reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/每次(0) 之间循环 + set_part_disp_times(reader->overlay_get_full_refresh_value()); } } if (sel == 9) //目录 From 65ea00d206abf5f67f4c54dfcb3c7edd3a74dcc9 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 16 Jan 2026 14:05:04 +0800 Subject: [PATCH 06/27] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=EF=BC=9A=20=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E9=98=85=E8=AF=BB=E8=BF=9B=E5=BA=A6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=A1=B5=E9=9D=A2=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E7=BC=BA=E9=99=B7=EF=BC=8C=E5=AE=8C=E5=96=84=E7=BB=A7=E7=BB=AD?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubList.cpp | 23 +- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 18 + epdiy-epub/lib/Epub/EpubList/EpubToc.cpp | 21 +- .../boards/controls/SF32_TouchControls.cpp | 59 ---- epdiy-epub/src/epub_screen.cpp | 52 ++- epdiy-epub/src/epub_screen.h | 2 +- epdiy-epub/src/main.cpp | 326 ++++++++++-------- 7 files changed, 262 insertions(+), 239 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp index 2853941..0394e57 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp @@ -193,12 +193,27 @@ void EpubList::render() renderer->draw_rect(i, ypos + PADDING / 2 + i, renderer->get_page_width() - 2 * i, cell_height - PADDING - 2 * i, 255); } } - // draw the selection box around the current selection - if (state.selected_item == i) + // 当不处于底部按钮选择模式时,绘制列表高亮 + // 若处于底部模式,则擦除列表高亮,避免同时双高亮 + if (!m_bottom_mode) { - for (int i = 0; i < 5; i++) + if (state.selected_item == i) + { + for (int line = 0; line < 5; line++) + { + renderer->draw_rect(line, ypos + PADDING / 2 + line, renderer->get_page_width() - 2 * line, cell_height - PADDING - 2 * line, 0); + } + } + } + else + { + if (state.selected_item == i) { - renderer->draw_rect(i, ypos + PADDING / 2 + i, renderer->get_page_width() - 2 * i, cell_height - PADDING - 2 * i, 0); + // 擦除之前的黑色高亮边框 + for (int line = 0; line < 5; line++) + { + renderer->draw_rect(line, ypos + PADDING / 2 + line, renderer->get_page_width() - 2 * line, cell_height - PADDING - 2 * line, 255); + } } } ypos += cell_height; diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 90685cb..ca3c17b 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -58,6 +58,9 @@ void EpubReader::parse_and_layout_current_section() parser = new RubbishHtmlParser(html, strlen(html), base_path); epub_mem_free(html); ulog_d(TAG, "After parse: %d", heap_free_size()); + // 为底部章节进度预留高度 + int reserved_bottom = renderer->get_line_height() + 10; + renderer->set_margin_bottom(reserved_bottom); parser->layout(renderer, epub); ulog_d(TAG, "After layout: %d", heap_free_size()); state.pages_in_current_section = parser->get_page_count(); @@ -104,6 +107,21 @@ void EpubReader::render() parser->render_page(state.current_page, renderer, epub); ulog_d(TAG, "rendered page %d of %d", state.current_page, parser->get_page_count()); ulog_d(TAG, "after render: %d", heap_free_size()); + // 章节进度 + if (state.pages_in_current_section > 0) + { + char buf[32]; + rt_snprintf(buf, sizeof(buf), "%d页/%d页", state.current_page + 1, state.pages_in_current_section); + int page_w = renderer->get_page_width(); + int page_h = renderer->get_page_height(); + int text_w = renderer->get_text_width(buf); + int text_h = renderer->get_line_height(); + int x = (page_w - text_w) / 2; + int reserved_bottom = renderer->get_line_height() + 4; + const int progress_up = 6; // 上抬 + int y = page_h - text_h - 10 + reserved_bottom - progress_up; + renderer->draw_text(x, y, buf, false, true); + } // 绘制半屏覆盖操作层 if (overlay_active) { diff --git a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp index c6c5061..6f08ff5 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp @@ -108,12 +108,25 @@ void EpubToc::render() renderer->draw_rect(line, ypos + PADDING / 2 + line, renderer->get_page_width() - 2 * line, cell_height - PADDING - 2 * line, 255); } } - // draw the selection box around the current selection - if (state.selected_item == i) + // 目录页:仅在非底部按钮模式时显示列表高亮;底部模式下擦除列表高亮 + if (!m_bottom_mode) { - for (int line = 0; line < 3; line++) + if (state.selected_item == i) + { + for (int line = 0; line < 3; line++) + { + renderer->draw_rect(line, ypos + PADDING / 2 + line, renderer->get_page_width() - 2 * line, cell_height - PADDING - 2 * line, 0); + } + } + } + else + { + if (state.selected_item == i) { - renderer->draw_rect(line, ypos + PADDING / 2 + line, renderer->get_page_width() - 2 * line, cell_height - PADDING - 2 * line, 0); + for (int line = 0; line < 3; line++) + { + renderer->draw_rect(line, ypos + PADDING / 2 + line, renderer->get_page_width() - 2 * line, cell_height - PADDING - 2 * line, 255); + } } } ypos += cell_height; diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index 9d17027..43f4a5a 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -120,21 +120,6 @@ SF32_TouchControls::SF32_TouchControls(Renderer *renderer, ActionCallback_t on_a void SF32_TouchControls::render(Renderer *renderer) { - renderer->set_margin_top(0); - uint16_t x_offset = 10; - uint16_t x_triangle = x_offset + 70; - // DOWN - renderer->draw_rect(x_offset, 1, ui_button_width, ui_button_height, 0); - renderer->draw_triangle(x_triangle, 20, x_triangle - 5, 6, x_triangle + 5, 6, 0); - // UP - x_offset = ui_button_width + 30; - x_triangle = x_offset + 70; - renderer->draw_rect(x_offset, 1, ui_button_width, ui_button_height, 0); - renderer->draw_triangle(x_triangle, 6, x_triangle - 5, 20, x_triangle + 5, 20, 0); - // SELECT - x_offset = ui_button_width * 2 + 60; - renderer->draw_rect(x_offset, 1, ui_button_width, ui_button_height, 0); - renderer->draw_circle(x_offset + (ui_button_width / 2) + 9, 15, 5, 0); renderer->set_margin_top(35); } @@ -160,49 +145,5 @@ void SF32_TouchControls::powerOnTouch() } void SF32_TouchControls::renderPressedState(Renderer *renderer, UIAction action, bool state) { - renderer->set_margin_top(0); - switch (action) - { - case DOWN: - { - if (state) - { - renderer->fill_triangle(80, 20, 75, 6, 85, 6, 0); - } - else - { - renderer->fill_triangle(81, 19, 76, 7, 86, 7, 255); - } - //renderer->flush_area(76, 6, 10, 15); - break; - } - case UP: - { - if (state) - { - renderer->fill_triangle(220, 6, 220 - 5, 20, 220 + 5, 20, 0); - } - else - { - renderer->fill_triangle(221, 7, 221 - 5, 19, 221 + 5, 19, 255); - } - //renderer->flush_area(195, 225, 10, 15); - } - break; - case SELECT: - { - uint16_t x_circle = (ui_button_width * 2 + 60) + (ui_button_width / 2) + 9; - renderer->fill_circle(x_circle, 15, 5, 0); - //renderer->flush_area(x_circle - 3, 12, 6, 6); - // TODO - this causes a stack overflow when select is picked - // renderPressedState(renderer, last_action, false); - } - break; - case LAST_INTERACTION: - case NONE: - break; - default: - break; - } renderer->set_margin_top(35); } \ No newline at end of file diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index fbfdc7e..b06ae54 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -1,3 +1,5 @@ + +#include "EpubList/EpubList.h" #include "epub_screen.h" #include @@ -8,6 +10,9 @@ extern "C" extern void set_part_disp_times(int val); } +// 最近一次真实打开并阅读的书本索引(由 main.cpp 维护) +extern int g_last_read_index; + // 主页面选项 typedef enum { @@ -50,24 +55,24 @@ int screen_get_full_refresh_idx() typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; static int settings_selected_idx = 0; -// 超时关机:1/3/5/7/10/不关机(0) -static const int kTimeoutOptions[] = {1, 3, 5, 7, 10, 0}; +// 超时关机:5/10/30分钟、1小时、不关机(0) +static const int kTimeoutOptions[] = {5, 10, 30, 60, 0}; // 单位:分钟,0为不关机 static const int kTimeoutOptionsCount = sizeof(kTimeoutOptions) / sizeof(kTimeoutOptions[0]); -static int timeout_shutdown_hours = 5; // 运行时关机超时(小时),0 表示不关机 -static int timeout_idx = -1; // 指向 kTimeoutOptions 的索引 +static int timeout_shutdown_minutes = 30; // 默认30分钟 +static int timeout_idx = -1; // -static int find_timeout_idx(int hours) +static int find_timeout_idx(int minutes) { for (int i = 0; i < kTimeoutOptionsCount; ++i) { - if (kTimeoutOptions[i] == hours) return i; + if (kTimeoutOptions[i] == minutes) return i; } - return 2; // 默认索引:5小时 + return 2; // 默认索引:30分钟 } static void adjust_timeout(bool increase) { - if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_minutes); if (increase) { timeout_idx = (timeout_idx + 1) % kTimeoutOptionsCount; @@ -76,19 +81,19 @@ static void adjust_timeout(bool increase) { timeout_idx = (timeout_idx - 1 + kTimeoutOptionsCount) % kTimeoutOptionsCount; } - timeout_shutdown_hours = kTimeoutOptions[timeout_idx]; + timeout_shutdown_minutes = kTimeoutOptions[timeout_idx]; } -void screen_init(int default_timeout_hours) +void screen_init(int default_timeout_minutes) { - timeout_shutdown_hours = default_timeout_hours; - timeout_idx = find_timeout_idx(timeout_shutdown_hours); + timeout_shutdown_minutes = default_timeout_minutes; + timeout_idx = find_timeout_idx(timeout_shutdown_minutes); } -int screen_get_timeout_shutdown_hours() +int screen_get_timeout_shutdown_minutes() { - if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); - return timeout_shutdown_hours; + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_minutes); + return timeout_shutdown_minutes; } int screen_get_main_selected_option() @@ -133,10 +138,14 @@ static void render_main_page(Renderer *renderer) int mid_w = right_x - margin_side - mid_x; const char *opt_text = NULL; + extern EpubListState epub_list_state; + bool has_continue_reading = (epub_list_state.num_epubs > 0 && g_last_read_index >= 0 && g_last_read_index < epub_list_state.num_epubs); switch (main_option) { case OPTION_OPEN_LIBRARY: opt_text = "打开书库"; break; - case OPTION_CONTINUE_READING: opt_text = "继续阅读"; break; + case OPTION_CONTINUE_READING: + opt_text = has_continue_reading ? "继续阅读" : "无阅读记录"; + break; case OPTION_ENTER_SETTINGS: opt_text = "进入设置"; break; } int opt_w = renderer->get_text_width(opt_text); @@ -208,6 +217,7 @@ static void render_settings_page(Renderer *renderer) // 1) 触控开关 int item_w = page_w - margin_lr * 2 - arrow_col_w * 2; // 为左右箭头列留边 int item_x = margin_lr + arrow_col_w; + if (settings_selected_idx == SET_TOUCH) { const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); @@ -237,6 +247,7 @@ static void render_settings_page(Renderer *renderer) y += item_h + gap; // 2) 超时关机 + if (settings_selected_idx == SET_TIMEOUT) { const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); @@ -252,13 +263,17 @@ static void render_settings_page(Renderer *renderer) renderer->draw_rect(item_x, y, item_w, item_h, 0); } char buf2[64]; - if (timeout_shutdown_hours == 0) + if (timeout_shutdown_minutes == 0) { rt_snprintf(buf2, sizeof(buf2), "超时关机:不关机"); } + else if (timeout_shutdown_minutes < 60) + { + rt_snprintf(buf2, sizeof(buf2), "超时关机:%d分钟", timeout_shutdown_minutes); + } else { - rt_snprintf(buf2, sizeof(buf2), "超时关机:%d 小时", timeout_shutdown_hours); + rt_snprintf(buf2, sizeof(buf2), "超时关机:%d小时", timeout_shutdown_minutes / 60); } { int t2_w = renderer->get_text_width(buf2); @@ -270,6 +285,7 @@ static void render_settings_page(Renderer *renderer) y += item_h + gap; // 3) 全刷周期 + if (settings_selected_idx == SET_FULL_REFRESH) { const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h index a1b589d..d3f1646 100644 --- a/epdiy-epub/src/epub_screen.h +++ b/epdiy-epub/src/epub_screen.h @@ -11,7 +11,7 @@ void screen_init(int default_timeout_hours); // 获取当前关机超时设置(小时;0 表示不关机) -int screen_get_timeout_shutdown_hours(); +int screen_get_timeout_shutdown_minutes(); // 获取当前主页面选中的选项(0: 打开书库, 1: 继续阅读, 2: 进入设置) int screen_get_main_selected_option(); diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 7d020f9..cd3c7ae 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -35,30 +35,28 @@ extern "C" const char *TAG = "main"; -typedef enum -{ +typedef enum { MAIN_PAGE, // 新主页面 - SELECTING_EPUB, // 电子书列表页面(书库) + SELECTING_EPUB, // 电子书列表页面(书库) SELECTING_TABLE_CONTENTS, // 电子书目录页面 - READING_EPUB, // 阅读页面 - SETTINGS_PAGE // 通用功能设置页面 -} UIState; -typedef enum -{ - MAIN_MENU, - WELCOME_PAGE, - LOW_POWER_PAGE, - CHARGING_PAGE -} UIState2; + READING_EPUB, // 阅读页面 + SETTINGS_PAGE, // 通用功能设置页面 + WELCOME_PAGE, // 欢迎页面 + LOW_POWER_PAGE, // 低电量页面 + CHARGING_PAGE, // 充电页面 + SHUTDOWN_PAGE // 关机页面 +} AppUIState; // 默认显示新主页面,而非书库页面 -UIState ui_state = MAIN_PAGE; -UIState2 lowpower_ui_state = MAIN_MENU; +AppUIState ui_state = MAIN_PAGE; // the state data for the epub list and reader EpubListState epub_list_state; // the state data for the epub index list EpubTocState epub_index_state; +// 最近一次真实打开并阅读的书本索引(-1 表示无记录) +int g_last_read_index = -1; + void handleEpub(Renderer *renderer, UIAction action); void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw); void back_to_main_page(); @@ -92,6 +90,8 @@ void handleEpub(Renderer *renderer, UIAction action) { reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); reader->load(); + // 记录最近一次进入阅读的书籍索引 + g_last_read_index = epub_list_state.selected_item; } switch (action) { @@ -165,6 +165,7 @@ void handleEpub(Renderer *renderer, UIAction action) if (sel == 9) //目录 { ui_state = SELECTING_TABLE_CONTENTS; + renderer->set_margin_bottom(0); reader->stop_overlay(); delete reader; reader = nullptr; @@ -187,6 +188,7 @@ void handleEpub(Renderer *renderer, UIAction action) else if (sel == 10) //书库 { ui_state = SELECTING_EPUB; + renderer->set_margin_bottom(0); reader->stop_overlay(); renderer->clear_screen(); delete reader; @@ -219,7 +221,6 @@ void handleEpub(Renderer *renderer, UIAction action) else { // switch back to main screen - ui_state = SELECTING_EPUB; renderer->clear_screen(); // clear the epub reader away delete reader; @@ -229,7 +230,8 @@ void handleEpub(Renderer *renderer, UIAction action) { epub_list = new EpubList(renderer, epub_list_state); } - handleEpubList(renderer, NONE, true); + renderer->set_margin_bottom(0); + back_to_main_page(); return; } @@ -358,6 +360,8 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); reader->set_state_section(contents->get_selected_toc()); reader->load(); + // 记录最近一次进入阅读的书籍索引 + g_last_read_index = epub_list_state.selected_item; delete contents; handleEpub(renderer, NONE); return; @@ -585,10 +589,21 @@ void handleUserInteraction(Renderer *renderer, UIAction ui_action, bool needs_re ui_state = SETTINGS_PAGE; (void)handleSettingsPage(renderer, NONE, true); } - else if (ui_action == SELECT && screen_get_main_selected_option() == 1) //切换到阅读页面 + else if (ui_action == SELECT && screen_get_main_selected_option() == 1) //继续阅读 { - // ui_state = READING_EPUB; - // handleEpub(renderer, NONE); + // 判断是否有继续阅读记录 + if (!(g_last_read_index >= 0 && g_last_read_index < epub_list_state.num_epubs)) { + return; // 无记录,忽略 + } + // 有记录,恢复阅读 + if (reader) { delete reader; reader = nullptr; } + int last_idx = g_last_read_index; + EpubListItem &last_item = epub_list_state.epub_list[last_idx]; + reader = new EpubReader(last_item, renderer); + reader->set_state_section(last_item.current_section); + reader->load(); + ui_state = READING_EPUB; + handleEpub(renderer, NONE); } else if (ui_action == SELECT && screen_get_main_selected_option() == 0) //切换到书库页面 { @@ -620,151 +635,154 @@ void handleUserInteraction(Renderer *renderer, UIAction ui_action, bool needs_re rt_kprintf("Renderer time=%d \r\n", rt_tick_get() - start_tick); } const char* getCurrentPageName() { - switch (lowpower_ui_state) - { - case MAIN_MENU: - return "MAIN_MENU"; - case WELCOME_PAGE: - return "WELCOME_PAGE"; - case LOW_POWER_PAGE: - return "LOW_POWER_PAGE"; - case CHARGING_PAGE: - return "CHARGING_PAGE"; - default: - return "UNKNOWN_PAGE"; - } + switch (ui_state) + { + case MAIN_PAGE: + return "MAIN_PAGE"; + case SELECTING_EPUB: + return "SELECTING_EPUB"; + case SELECTING_TABLE_CONTENTS: + return "SELECTING_TABLE_CONTENTS"; + case READING_EPUB: + return "READING_EPUB"; + case SETTINGS_PAGE: + return "SETTINGS_PAGE"; + case WELCOME_PAGE: + return "WELCOME_PAGE"; + case LOW_POWER_PAGE: + return "LOW_POWER_PAGE"; + case CHARGING_PAGE: + return "CHARGING_PAGE"; + case SHUTDOWN_PAGE: + return "SHUTDOWN_PAGE"; + default: + return "UNKNOWN_PAGE"; + } } //回到主界面接口 void back_to_main_page() -{ - if (ui_state == MAIN_PAGE) - { - rt_kprintf("已经在主页面,无需返回\n"); - return; - } - lowpower_ui_state = MAIN_MENU; - if (ui_state == SELECTING_TABLE_CONTENTS) - { - if (contents) - { - delete contents; - contents = nullptr; - } +{ + if (ui_state == MAIN_PAGE) + { + rt_kprintf("已经在主页面,无需返回\n"); + return; + } + if (ui_state == SELECTING_TABLE_CONTENTS) + { + if (contents) + { + delete contents; + contents = nullptr; } - bool hydrate_success = renderer->hydrate(); - - renderer->reset(); - renderer->set_margin_top(35); - renderer->set_margin_left(10); - renderer->set_margin_right(10); - // 返回新的主页面,不再默认进入书库页面 - ui_state = MAIN_PAGE; - handleUserInteraction(renderer, NONE, true); - - if (battery) - { - draw_charge_status(renderer, battery); - draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); - } - touch_controls->render(renderer); - renderer->flush_display(); + } + bool hydrate_success = renderer->hydrate(); + + renderer->reset(); + renderer->set_margin_top(35); + renderer->set_margin_left(10); + renderer->set_margin_right(10); + // 返回新的主页面,不再默认进入书库页面 + ui_state = MAIN_PAGE; + handleUserInteraction(renderer, NONE, true); + if (battery) + { + draw_charge_status(renderer, battery); + draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); + } + touch_controls->render(renderer); + renderer->flush_display(); } //欢迎页面 void draw_welcome_page(Battery *battery) { - if (strcmp(getCurrentPageName(), "WELCOME_PAGE") == 0) - { - return; - } - lowpower_ui_state = WELCOME_PAGE; - touch_controls->powerOffTouch(); - touch_controls->setTouchEnable(false); - // 设置黑色背景 - renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 0); - if (battery) { - renderer->set_margin_top(35); - draw_charge_status(renderer, battery); - draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); - } + if (ui_state == WELCOME_PAGE) + { + return; + } + ui_state = WELCOME_PAGE; + // 设置黑色背景 + renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 0); + if (battery) { + renderer->set_margin_top(35); + draw_charge_status(renderer, battery); + draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); + } - const int img_width = 649; - const int img_height = 150; - - int center_x = renderer->get_page_width() / 2; - int center_y = 35 + (renderer->get_page_height() - 35) / 2; - int x_pos = center_x - img_width / 2; - int y_pos = center_y - img_height / 2; - - EpdiyFrameBufferRenderer* fb_renderer = static_cast(renderer); - fb_renderer->show_img(x_pos, y_pos, img_width, img_height, welcome_map); + const int img_width = 649; + const int img_height = 150; - // 显示 - renderer->flush_display(); - + int center_x = renderer->get_page_width() / 2; + int center_y = 35 + (renderer->get_page_height() - 35) / 2; + int x_pos = center_x - img_width / 2; + int y_pos = center_y - img_height / 2; + + EpdiyFrameBufferRenderer* fb_renderer = static_cast(renderer); + fb_renderer->show_img(x_pos, y_pos, img_width, img_height, welcome_map); + + // 显示 + renderer->flush_display(); } // 低电量页面 void draw_low_power_page(Battery *battery) { - if (strcmp(getCurrentPageName(), "LOW_POWER_PAGE") == 0) - { - return; - } - lowpower_ui_state = LOW_POWER_PAGE; - - // 设置黑色背景 - renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 0); - if (battery) { - renderer->set_margin_top(35); - draw_charge_status(renderer, battery); - draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); - } + if (ui_state == LOW_POWER_PAGE) + { + return; + } + ui_state = LOW_POWER_PAGE; + // 设置黑色背景 + renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 0); + if (battery) { + renderer->set_margin_top(35); + draw_charge_status(renderer, battery); + draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); + } - const int img_width = 200; - const int img_height = 200; - - int center_x = renderer->get_page_width() / 2; - int center_y = 35 + (renderer->get_page_height() - 35) / 2; - int x_pos = center_x - img_width / 2; - int y_pos = center_y - img_height / 2; - - EpdiyFrameBufferRenderer* fb_renderer = static_cast(renderer); - fb_renderer->show_img(x_pos, y_pos, img_width, img_height, low_power_map); - // 显示 - renderer->flush_display(); - + const int img_width = 200; + const int img_height = 200; + + int center_x = renderer->get_page_width() / 2; + int center_y = 35 + (renderer->get_page_height() - 35) / 2; + int x_pos = center_x - img_width / 2; + int y_pos = center_y - img_height / 2; + + EpdiyFrameBufferRenderer* fb_renderer = static_cast(renderer); + fb_renderer->show_img(x_pos, y_pos, img_width, img_height, low_power_map); + // 显示 + renderer->flush_display(); } //充电页面 void draw_charge_page(Battery *battery) { - if (strcmp(getCurrentPageName(), "CHARGING_PAGE") == 0) - { - return; - } - lowpower_ui_state = CHARGING_PAGE; - // 设置黑色背景 - renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 0); - if (battery) { - renderer->set_margin_top(35); - draw_charge_status(renderer, battery); - draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); - } + if (ui_state == CHARGING_PAGE) + { + return; + } + ui_state = CHARGING_PAGE; + // 设置黑色背景 + renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 0); + if (battery) { + renderer->set_margin_top(35); + draw_charge_status(renderer, battery); + draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); + } - const int img_width = 200; - const int img_height = 200; - - int center_x = renderer->get_page_width() / 2; - int center_y = 35 + (renderer->get_page_height() - 35) / 2; - int x_pos = center_x - img_width / 2; - int y_pos = center_y - img_height / 2; - - EpdiyFrameBufferRenderer* fb_renderer = static_cast(renderer); - fb_renderer->show_img(x_pos, y_pos, img_width, img_height, chargeing_map); - // 显示 - renderer->flush_display(); + const int img_width = 200; + const int img_height = 200; + + int center_x = renderer->get_page_width() / 2; + int center_y = 35 + (renderer->get_page_height() - 35) / 2; + int x_pos = center_x - img_width / 2; + int y_pos = center_y - img_height / 2; + + EpdiyFrameBufferRenderer* fb_renderer = static_cast(renderer); + fb_renderer->show_img(x_pos, y_pos, img_width, img_height, chargeing_map); + // 显示 + renderer->flush_display(); } //关机页面 @@ -873,18 +891,19 @@ void main_task(void *param) // 初始化屏幕模块默认关机超时 screen_init(TIMEOUT_SHUTDOWN_TIME); - while ((screen_get_timeout_shutdown_hours() == 0) || - (rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 * screen_get_timeout_shutdown_hours())) // 按设置的小时数无操作自动关机;0为不关机 + while ((rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 * TIMEOUT_SHUTDOWN_TIME)) // 5小时 { - // 检查是否超过5分钟无操作,如果是在欢迎页面、充电页面或低电量页面则不跳转 - if (rt_tick_get_millisecond() - last_user_interaction >= 60 * 1000 *5 && - battery && battery->get_low_power_state() != 1 && - strcmp(getCurrentPageName(), "WELCOME_PAGE") != 0 && - strcmp(getCurrentPageName(), "CHARGING_PAGE") != 0 && - strcmp(getCurrentPageName(), "LOW_POWER_PAGE") != 0) + // 检查是否超过设置分钟无操作,如果是在欢迎页面、充电页面或低电量页面则不跳转 + if (rt_tick_get_millisecond() - last_user_interaction >= 60 * 1000 * screen_get_timeout_shutdown_minutes() && + battery && battery->get_low_power_state() != 1 && + ui_state != WELCOME_PAGE && + ui_state != CHARGING_PAGE && + ui_state != LOW_POWER_PAGE && + screen_get_timeout_shutdown_minutes()) { - draw_welcome_page(battery); + renderer->set_margin_bottom(0); + draw_welcome_page(battery); } uint32_t msg_data; if (rt_mq_recv(ui_queue, &msg_data, sizeof(uint32_t), rt_tick_from_millisecond(60500)) == RT_EOK) //一分钟自动刷一下 @@ -924,6 +943,7 @@ void main_task(void *param) { case MSG_DRAW_LOW_POWER_PAGE: rt_kprintf("low_power\n"); + renderer->set_margin_bottom(0); draw_low_power_page(battery); break; case MSG_DRAW_CHARGE_PAGE: @@ -946,14 +966,13 @@ void main_task(void *param) if (ui_action != NONE) { // 如果之前在欢迎页面,现在需要返回主界面 - if(strcmp(getCurrentPageName(), "WELCOME_PAGE") == 0) + if(ui_state == WELCOME_PAGE) { back_to_main_page(); - last_user_interaction = rt_tick_get_millisecond(); board->sleep_filesystem(); continue; - } + } //rt_kprintf("ui_action = %d\n", ui_action); // something happened! last_user_interaction = rt_tick_get_millisecond(); @@ -987,6 +1006,7 @@ void main_task(void *param) // turn off the filesystem board->stop_filesystem(); // get ready to go to sleep + renderer->set_margin_bottom(0); draw_shutdown_page(); board->prepare_to_sleep(); //ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup()); From c54be37ecebbe5155cee2bb38ab2d669471e6bb4 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 16 Jan 2026 14:14:53 +0800 Subject: [PATCH 07/27] =?UTF-8?q?=E5=BC=80=E5=90=AF=E4=BD=8E=E5=8A=9F?= =?UTF-8?q?=E8=80=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index cd3c7ae..24f875a 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -1023,7 +1023,7 @@ extern "C" int main() { // dump out the epub list state - rt_pm_request(PM_SLEEP_MODE_IDLE); + //rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); From 13abb373034427be4ae71818bea7347dcb07b991 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 16 Jan 2026 18:55:56 +0800 Subject: [PATCH 08/27] =?UTF-8?q?1.=E4=BF=AE=E6=94=B9=E7=B4=AF=E7=A7=AF?= =?UTF-8?q?=E8=B7=B3=E9=A1=B5=E4=BD=BF=E7=94=A8=E9=80=BB=E8=BE=91=202.?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B9=A6=E5=BA=93=E4=BB=A5=E5=8F=8A=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E9=A1=B5=E7=9A=84up=EF=BC=8Cdown=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 34 +++++++- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 9 +- epdiy-epub/src/main.cpp | 95 ++++++++++++++++----- 3 files changed, 114 insertions(+), 24 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index ca3c17b..8e0a4e5 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -103,6 +103,11 @@ void EpubReader::render() { parse_and_layout_current_section(); } + // 确保覆盖层目标页初始与当前页同步(1-based) + if (overlay_active && overlay_target_page < 1) + { + overlay_set_target_page(state.current_page + 1); + } ulog_d(TAG, "rendering page %d of %d", state.current_page, parser->get_page_count()); parser->render_page(state.current_page, renderer, epub); ulog_d(TAG, "rendered page %d of %d", state.current_page, parser->get_page_count()); @@ -178,7 +183,15 @@ void EpubReader::render_overlay() case 2: rt_snprintf(label, cap, ">"); break; case 3: rt_snprintf(label, cap, "-5"); break; case 4: rt_snprintf(label, cap, "-1"); break; - case 5: rt_snprintf(label, cap, "%d", overlay_jump_acc); break; + // 第六格显示:x/n 页 + case 5: + { + int total = state.pages_in_current_section; + if (total <= 0 && parser) total = parser->get_page_count(); + if (total <= 0) total = 1; + rt_snprintf(label, cap, "%d/%d", overlay_target_page, total); + break; + } case 6: rt_snprintf(label, cap, "+1"); break; case 7: rt_snprintf(label, cap, "+5"); break; case 8: rt_snprintf(label, cap, "确认"); break; @@ -330,4 +343,23 @@ void EpubReader::overlay_cycle_full_refresh() int EpubReader::overlay_get_full_refresh_value() const { return screen_get_full_refresh_period(); +} + +void EpubReader::overlay_set_target_page(int p) +{ + if (p < 1) p = 1; + int maxp = state.pages_in_current_section; + if (maxp <= 0 && parser) + { + maxp = parser->get_page_count(); + } + if (maxp <= 0) maxp = 1; + if (p > maxp) p = maxp; + overlay_target_page = p; +} + +void EpubReader::overlay_adjust_target_page(int d) +{ + int p = overlay_target_page + d; + overlay_set_target_page(p); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index a5a71b0..d65ef72 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -17,6 +17,8 @@ class EpubReader bool overlay_active = false; int overlay_selected = 0; // 0..10,共11个 int overlay_jump_acc = 0; // 覆盖层累积跳页值(可为负) + // 覆盖层目标页(当前章节内的页,1-based) + int overlay_target_page = 1; // 覆盖层中心属性模式:触控开关 或 全刷周期 enum OverlayCenterMode { CENTER_TOUCH = 0, CENTER_FULL_REFRESH = 1 }; OverlayCenterMode overlay_center_mode = CENTER_TOUCH; @@ -38,16 +40,19 @@ class EpubReader void render(); void set_state_section(uint16_t current_section); // 覆盖层控制 - void start_overlay() { overlay_active = true; overlay_selected = 0; overlay_jump_acc = 0; } + void start_overlay() { overlay_active = true; overlay_selected = 0; overlay_jump_acc = 0; overlay_target_page = state.current_page + 1; } void stop_overlay() { overlay_active = false; } bool is_overlay_active() const { return overlay_active; } void overlay_move_left(); void overlay_move_right(); int get_overlay_selected() const { return overlay_selected; } // 覆盖层跳页累积控制 - void overlay_add_jump(int d) { overlay_jump_acc += d; } void overlay_reset_jump() { overlay_jump_acc = 0; } int overlay_get_jump() const { return overlay_jump_acc; } + // 覆盖层目标页控制 + void overlay_set_target_page(int p); + void overlay_adjust_target_page(int d); + int overlay_get_target_page() const { return overlay_target_page; } // 覆盖层中心属性控制 void overlay_set_center_mode_touch() { overlay_center_mode = CENTER_TOUCH; } void overlay_set_center_mode_full_refresh() { overlay_center_mode = CENTER_FULL_REFRESH; } diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 24f875a..4d61b12 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -177,11 +177,11 @@ void handleEpub(Renderer *renderer, UIAction action) } else if (sel == 8) //确认:1.按第六格累积值跳页 { - int delta = reader->overlay_get_jump(); - if (delta != 0) - { - reader->jump_pages(delta); - } + // 跳转到第六格显示的目标页 + int target = reader->overlay_get_target_page(); + if (target < 1) target = 1; + extern EpubListState epub_list_state; + epub_list_state.epub_list[epub_list_state.selected_item].current_page = (uint16_t)(target - 1); reader->overlay_reset_jump(); reader->stop_overlay(); } @@ -202,19 +202,19 @@ void handleEpub(Renderer *renderer, UIAction action) } else if (sel == 3) { - reader->overlay_add_jump(-5); + reader->overlay_adjust_target_page(-5); } else if (sel == 4) { - reader->overlay_add_jump(-1); + reader->overlay_adjust_target_page(-1); } else if (sel == 6) { - reader->overlay_add_jump(1); + reader->overlay_adjust_target_page(1); } else if (sel == 7) { - reader->overlay_add_jump(5); + reader->overlay_adjust_target_page(5); } } @@ -271,15 +271,31 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red case UP: if (toc_bottom_mode) { - toc_bottom_idx = (toc_bottom_idx + 2) % 3; // 左移 + // 底部模式下:UP 向左移动;若已在最左(上一页),则返回当前页目录的最后一项 + if (toc_bottom_idx > 0) + { + toc_bottom_idx--; + } + else + { + int per_page = 6; + int start_idx = (epub_index_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + int count = contents->get_items_count(); + if (end_idx >= count) end_idx = count - 1; + toc_bottom_mode = false; + epub_index_state.selected_item = end_idx; + } } else { + // 若处于当前页第一个条目,UP 切换到底部按钮模式并选择“下一页” int per_page = 6; int start_idx = (epub_index_state.selected_item / per_page) * per_page; if (contents->get_items_count() > 0 && epub_index_state.selected_item == start_idx) { toc_bottom_mode = true; + toc_bottom_idx = 2; // 下一页 } else { @@ -290,7 +306,18 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red case DOWN: if (toc_bottom_mode) { - toc_bottom_idx = (toc_bottom_idx + 1) % 3; // 右移 + // 底部模式下:DOWN 向右移动;若已在最右(下一页),则返回当前页目录的第一项 + if (toc_bottom_idx < 2) + { + toc_bottom_idx++; + } + else + { + int per_page = 6; + int start_idx = (epub_index_state.selected_item / per_page) * per_page; + toc_bottom_mode = false; + epub_index_state.selected_item = start_idx; + } } else { @@ -299,9 +326,11 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red int end_idx = start_idx + per_page - 1; int count = contents->get_items_count(); if (end_idx >= count) end_idx = count - 1; + // 若处于当前页最后一个条目,DOWN 切换到底部按钮模式并选择“上一页” if (count > 0 && epub_index_state.selected_item == end_idx) { toc_bottom_mode = true; + toc_bottom_idx = 0; // 上一页 } else { @@ -338,7 +367,7 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red if (epub_index_state.selected_item < 0) epub_index_state.selected_item = 0; contents->set_needs_redraw(); } - toc_bottom_mode = false; + // 保持底部模式,允许连续翻页 } else if (toc_bottom_idx == 2) { @@ -350,7 +379,7 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red epub_index_state.selected_item = count - 1; contents->set_needs_redraw(); } - toc_bottom_mode = false; + // 保持底部模式,允许连续翻页 } } else @@ -403,8 +432,20 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) case UP: if (library_bottom_mode) { - // UP 表示向左选择 - library_bottom_idx = (library_bottom_idx + 2) % 3; + // 底部模式下:UP 向左移动;若已在最左(上一页),则返回当前页的列表最后一项 + if (library_bottom_idx > 0) + { + library_bottom_idx--; + } + else + { + int per_page = 4; + int start_idx = (epub_list_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; + library_bottom_mode = false; + epub_list_state.selected_item = end_idx; + } } else { @@ -414,6 +455,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == start_idx) { library_bottom_mode = true; + library_bottom_idx = 2; // 下一页 } else { @@ -424,8 +466,20 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) case DOWN: if (library_bottom_mode) { - // DOWN 表示向右选择 - library_bottom_idx = (library_bottom_idx + 1) % 3; + // 底部模式下:DOWN 向右移动;若已在最右(下一页),则返回当前页的列表第一项 + if (library_bottom_idx < 2) + { + library_bottom_idx++; + } + else + { + int per_page = 4; + int start_idx = (epub_list_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; + library_bottom_mode = false; + epub_list_state.selected_item = start_idx; + } } else { @@ -437,6 +491,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == end_idx) { library_bottom_mode = true; + library_bottom_idx = 0; // 上一页 } else { @@ -466,8 +521,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (epub_list_state.selected_item < 0) epub_list_state.selected_item = 0; epub_list->set_needs_redraw(); } - // 切回条目选择模式 - library_bottom_mode = false; + } else if (library_bottom_idx == 2) { @@ -479,8 +533,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) epub_list_state.selected_item = epub_list_state.num_epubs - 1; epub_list->set_needs_redraw(); } - // 切回条目选择模式 - library_bottom_mode = false; + } } else From 3ddc2390286737f52fc879e1e1a7bdd0615f7f7e Mon Sep 17 00:00:00 2001 From: minjiezhong Date: Tue, 20 Jan 2026 11:19:36 +0800 Subject: [PATCH 09/27] =?UTF-8?q?1=E3=80=82=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E6=89=80=E6=9C=89=E9=A1=B5=E9=9D=A2=E7=9A=84=E8=A7=A6=E6=8E=A7?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubList.cpp | 9 + epdiy-epub/lib/Epub/EpubList/EpubList.h | 1 + epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 2 +- epdiy-epub/lib/Epub/EpubList/EpubToc.cpp | 9 + epdiy-epub/lib/Epub/EpubList/EpubToc.h | 1 + epdiy-epub/lib/Epub/EpubList/State.h | 16 +- epdiy-epub/project/Kconfig.proj | 8 +- epdiy-epub/src/boards/controls/Actions.h | 3 + .../boards/controls/SF32_TouchControls.cpp | 412 +++++++++++++++--- .../src/boards/controls/SF32_TouchControls.h | 9 +- .../src/boards/controls/TouchControls.h | 2 +- epdiy-epub/src/epub_screen.cpp | 89 +++- epdiy-epub/src/epub_screen.h | 2 +- epdiy-epub/src/main.cpp | 398 ++++++++++------- epdiy-epub/src/type.h | 38 ++ 15 files changed, 753 insertions(+), 246 deletions(-) create mode 100644 epdiy-epub/src/type.h diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp index 0394e57..55f42d0 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp @@ -36,6 +36,15 @@ void EpubList::prev() state.selected_item--; } +void EpubList::switch_book(int target_index) +{ + if (state.num_epubs == 0) return; + if (target_index < 0 || target_index >= state.num_epubs) + return; + state.selected_item = target_index; +} + + bool EpubList::load(const char *path) { if (state.is_loaded) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.h b/epdiy-epub/lib/Epub/EpubList/EpubList.h index da2c910..f73eec5 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.h @@ -47,4 +47,5 @@ class EpubList void next(); void prev(); void render(); + void switch_book(int target_index); }; \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 8e0a4e5..201478f 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -337,7 +337,7 @@ void EpubReader::jump_pages(int delta) void EpubReader::overlay_cycle_full_refresh() { - screen_cycle_full_refresh_period(); + screen_cycle_full_refresh_period(true); } int EpubReader::overlay_get_full_refresh_value() const diff --git a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp index 6f08ff5..88c45d2 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp @@ -31,6 +31,15 @@ void EpubToc::prev() } state.selected_item = (state.selected_item - 1 + epub->get_toc_items_count()) % epub->get_toc_items_count(); } +void EpubToc::switch_book(int target_index) +{ + if (!epub) + { + load(); + } + state.selected_item = target_index % epub->get_toc_items_count(); + +} bool EpubToc::load() { diff --git a/epdiy-epub/lib/Epub/EpubList/EpubToc.h b/epdiy-epub/lib/Epub/EpubList/EpubToc.h index 56563f0..4fc09d9 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubToc.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubToc.h @@ -43,6 +43,7 @@ class EpubToc void next(); void prev(); void render(); + void switch_book(int target_index); void set_needs_redraw() { m_needs_redraw = true; } uint16_t get_selected_toc(); // 目录项总数 diff --git a/epdiy-epub/lib/Epub/EpubList/State.h b/epdiy-epub/lib/Epub/EpubList/State.h index d5e5999..fe8c4a0 100644 --- a/epdiy-epub/lib/Epub/EpubList/State.h +++ b/epdiy-epub/lib/Epub/EpubList/State.h @@ -9,11 +9,11 @@ const int MAX_TITLE_SIZE = 100; // nice and simple state that can be persisted easily typedef struct { - char path[MAX_PATH_SIZE]; - char title[MAX_TITLE_SIZE]; - uint16_t current_section; - uint16_t current_page; - uint16_t pages_in_current_section; + char path[MAX_PATH_SIZE];//存储 EPUB 文件的路径 + char title[MAX_TITLE_SIZE];//存储 EPUB 文件的标题 + uint16_t current_section;//记录当前阅读的章节编号(从0开始) + uint16_t current_page;//记录当前章节内的页码(从0开始) + uint16_t pages_in_current_section;//记录当前章节总共有多少页 } EpubListItem; // this is held in the RTC memory @@ -30,7 +30,7 @@ typedef struct // this is held in the RTC memory typedef struct { - int previous_rendered_page; - int previous_selected_item; - int selected_item; + int previous_rendered_page;//记录当前选中的目录项索引 + int previous_selected_item;//记录上一次选中的目录项索引 + int selected_item;//记录上次渲染的页面索引 } EpubTocState; diff --git a/epdiy-epub/project/Kconfig.proj b/epdiy-epub/project/Kconfig.proj index b18b464..271c461 100644 --- a/epdiy-epub/project/Kconfig.proj +++ b/epdiy-epub/project/Kconfig.proj @@ -48,7 +48,9 @@ if !BSP_USING_BUILT_LCD config TSC_USING_GT967 bool default n - + config TSC_USING_GT967 + bool + default n choice prompt "Custom LCD driver" @@ -63,13 +65,13 @@ if !BSP_USING_BUILT_LCD config LCD_USING_EPD_YZC085_V100 bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758) for V1.1 board" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD + select TSC_USING_GT967 if BSP_USING_TOUCHD select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT config LCD_USING_EPD_R7D005 bool "6.0 rect electronic paper display(EPD R7D005_-1.30 1448x1072)" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD + select TSC_TSC_USING_GT967USING_FT5446U_V01 if BSP_USING_TOUCHD select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT diff --git a/epdiy-epub/src/boards/controls/Actions.h b/epdiy-epub/src/boards/controls/Actions.h index 8e83835..5e22d6b 100644 --- a/epdiy-epub/src/boards/controls/Actions.h +++ b/epdiy-epub/src/boards/controls/Actions.h @@ -9,6 +9,9 @@ typedef enum DOWN, SELECT, UPGLIDE, // 长按触发的上滑操作,用于阅读页半屏操作覆盖 + PREV_OPTION, // 上一选项(用于列表选择) + NEXT_OPTION, // 下一选项(用于列表选择) + SELECT_BOX, // 选择框(用于触控选择) LAST_INTERACTION, MSG_DRAW_LOW_POWER_PAGE, MSG_DRAW_CHARGE_PAGE, diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index 43f4a5a..c8e73c8 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -1,13 +1,31 @@ - #include "SF32_TouchControls.h" #include +#include "Actions.h" #include "epd_driver.h" +#include "type.h" +#include "epub_screen.h" +#include "EpubReader.h" #ifdef BSP_USING_TOUCHD #include "drv_touch.h" #endif volatile int g_touch_last_settings_row = -1; volatile int g_touch_last_settings_dir = 0; +extern int settings_selected_idx; +extern AppUIState ui_state; +extern int book_index; +extern bool library_bottom_mode; +extern int library_bottom_idx; +extern int toc_index; +extern int toc_bottom_idx; +extern bool toc_bottom_mode;//控制目录页面中功能选项的开关 +static int last_clicked_toc_index = -1; // -1 表示没有目录项被选中 +// 添加一个变量来记录上次点击的书籍索引 +static int last_clicked_book_index = -1; // -1 表示没有书籍被选中 +static bool waiting_for_confirmation = false; // 是否正在等待确认 +extern int touch_sel; +extern EpubReader *reader; + rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { @@ -23,73 +41,362 @@ rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) y = touch_data.x; - if (TOUCH_EVENT_DOWN == touch_data.event) + // if (TOUCH_EVENT_DOWN == touch_data.event) + // rt_kprintf("Touch down [%d,%d]\r\n", x, y); + // else + // rt_kprintf("Touch up [%d,%d]\r\n", x, y); + if (TOUCH_EVENT_DOWN == touch_data.event) + { rt_kprintf("Touch down [%d,%d]\r\n", x, y); + + // 记录按下时的位置 + instance->touch_start_x = x; + instance->touch_start_y = y; + + instance->is_touch_down = true; + + // 处理其他触控逻辑... + } else - rt_kprintf("Touch up [%d,%d]\r\n", x, y); - + { + rt_kprintf("Touch up [%d,%d]\r\n", x, y); + instance->touch_current_x = x; + instance->touch_current_y = y; + + // 检查是否构成向上滑动手势 + if (instance->is_touch_down) { + int y_diff = instance->touch_start_y - touch_data.y; // 注意坐标转换 + int x_diff = abs(instance->touch_start_x - touch_data.x); + rt_kprintf("Touch up diff Y: %d, X: %d\r\n", y_diff, x_diff); + + // 检查时间间隔,防止连续触发 + rt_tick_t current_time = rt_tick_get(); + if(reader->is_overlay_active() == false) + { + if (y_diff > instance->SWIPE_THRESHOLD && y_diff > abs(x_diff)) + { + rt_kprintf("Up swipe detected! Diff: %d\n", y_diff); + + // 发送向上滑动动作 + UIAction action = UPGLIDE; + instance->last_action = action; + instance->on_action(action); + + + // 重置状态 + instance->is_touch_down = false; + return RT_EOK; + } + } + } + + // 重置触摸状态 + instance->is_touch_down = false; + } + // 只处理按下事件,忽略释放事件 + if (TOUCH_EVENT_UP == touch_data.event) { + return RT_EOK; + } UIAction action = NONE; // LOG_I("TOUCH", "Received touch event %d,%d", x, y); // 主页面底部按键区域:左"<"、右">"、中间文本框 - int page_w = instance->renderer->get_page_width(); - int page_h = instance->renderer->get_page_height(); - int margin_side = 10; - int margin_bottom = 60; - int rect_w = 80; - int rect_h = 40; - int y_bottom = page_h - rect_h - margin_bottom; - int left_x = margin_side; - int right_x = page_w - rect_w - margin_side; - int mid_x = left_x + rect_w + margin_side; - int mid_w = right_x - margin_side - mid_x; - - if (x >= left_x && x <= left_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) +switch (ui_state) +{ + case MAIN_PAGE://主页面 + if (x >= 10 && x <= 80 && y >= 950 && y <= 1000) { rt_kprintf("Touch left < \n"); - action = UP; + action = UP; // 对应 KEY3 功能 } - - else if (x >= right_x && x <= right_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) + else if (x >= 650 && x <= 750 && y >= 950 && y <= 1000) { - action = DOWN; + action = DOWN; // 对应 KEY1 功能 rt_kprintf("Touch right > \n"); } - - // 设置页面每行左右箭头触控区域(与设置页布局一致) - if (action == NONE) - { - int page_w2 = instance->renderer->get_page_width(); - int margin_lr2 = 6; - int item_h2 = 100; - int gap2 = 54; - int arrow_col_w2 = 40; - int lh2 = instance->renderer->get_line_height(); - int y_start2 = 40 + lh2 + 20; - g_touch_last_settings_row = -1; - g_touch_last_settings_dir = 0; - for (int row = 0; row < 3; ++row) - { - int ry = y_start2 + row * (item_h2 + gap2); - int left_ax = margin_lr2; - int right_ax = page_w2 - margin_lr2 - arrow_col_w2; - if (x >= left_ax && x <= left_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) - { + else if (x >= 250 && x <= 500 && y >= 950 && y <= 1000) + { + action = SELECT; // 对应 KEY2 功能 + rt_kprintf("Touch middle SELECT \n"); + } + break; + case SELECTING_EPUB://书库页面 + // 检查是否点击了功能控制按钮 + if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + { + library_bottom_mode = true; + library_bottom_idx = 0; + action = SELECT; + } + else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + { + library_bottom_mode = true; + library_bottom_idx = 1; + action = SELECT; + } + else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + { + library_bottom_mode = true; + library_bottom_idx = 2; + action = SELECT; + } + else + { + // 处理书籍选择区域 + int clicked_book_index = -1; + + if(x >= 10 && x <= 740 && y >= 60 && y <= 240) + { + clicked_book_index = 0; + } + else if(x >= 10 && x <= 740 && y >= 270 && y <= 450) + { + clicked_book_index = 1; + } + else if(x >= 10 && x <= 740 && y >= 470 && y <= 680) + { + clicked_book_index = 2; + } + else if(x >= 10 && x <= 740 && y >= 700 && y <= 900) + { + clicked_book_index = 3; + } + + // 如果点击了书籍区域 + if(clicked_book_index != -1) + { + // 判断是第一次点击还是第二次点击 + if(waiting_for_confirmation && last_clicked_book_index == clicked_book_index) + { + // 第二次点击:执行打开操作 + book_index = clicked_book_index; + library_bottom_mode = false; + rt_kprintf("Open book%d %d\n", book_index, book_index); + action = SELECT; + + // 重置状态 + waiting_for_confirmation = false; + last_clicked_book_index = -1; + } + else + { + // 第一次点击:选择书籍并等待确认 + book_index = clicked_book_index; + last_clicked_book_index = clicked_book_index; + waiting_for_confirmation = true; + action = SELECT_BOX; + rt_kprintf("Select book%d for confirmation, waiting for second click\n", book_index); + } + } + } + break; + case READING_EPUB: //阅读界面 + //翻页操作 + if(x >= 10 && x <= 200 && y >=10 && y <= 1010 && reader->is_overlay_active() == false) + { action = UP; - g_touch_last_settings_row = row; - g_touch_last_settings_dir = -1; // 左=减 - break; - } - if (x >= right_ax && x <= right_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) - { + } + else if(x >= 550 && x <= 750 && y >=10 && y <= 1010 && reader->is_overlay_active() == false) + { action = DOWN; - g_touch_last_settings_row = row; - g_touch_last_settings_dir = +1; // 右=加 - break; - } } - } + //点击正文,推出阅读设置 + if(x >= 10 && x <= 750 && y >=10 && y <= 630 && reader->is_overlay_active()) + { + touch_sel = 8; + action = SELECT; + } + + //阅读页面控制区域设置 + if(x >= 10 && x <= 250 && y >= 900 && y <= 960 && reader->is_overlay_active()) + { + touch_sel = 8; + action = SELECT; + } + else if(x >= 280 && x <= 480 && y >= 900 && y <= 960 && reader->is_overlay_active()) + { + touch_sel = 9; + action = SELECT; + } + else if(x >= 520 && x <= 750 && y >= 900 && y <= 960 && reader->is_overlay_active()) + { + touch_sel = 10; + action = SELECT; + } + else if(x >= 10 && x <= 150 && y >= 690 && y <= 750 && reader->is_overlay_active()) + { + touch_sel= 0; + rt_kprintf("Touch middle SELECT %d\n",touch_sel); + action = SELECT; + } + else if(x >= 170 && x <= 570 && y >= 690 && y <= 750 && reader->is_overlay_active()) + { + touch_sel= 1; + rt_kprintf("Touch middle SELECT %d\n",touch_sel); + action = SELECT; + } + else if(x >= 610 && x <= 750 && y >= 690 && y <= 750 && reader->is_overlay_active()) + { + touch_sel= 2; + rt_kprintf("Touch middle SELECT %d\n",touch_sel); + action = SELECT; + } + else if(x >= 10 && x <= 140 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 3;//跳转-5页 + action = SELECT; + } + else if(x >= 165 && x <=300 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 4;//跳转-1页 + action = SELECT; + } + else if(x >= 480 && x <= 570 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 6;//跳转+1页 + action = SELECT; + } + else if(x >= 620 && x <= 750 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 7;//跳转5页 + action = SELECT; + } + + break; + case SELECTING_TABLE_CONTENTS: //目录界面 + if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + { + toc_bottom_mode = true; + toc_bottom_idx = 0; + action = SELECT; + } + else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + { + toc_bottom_mode = true; + toc_bottom_idx = 1; + action = SELECT; + } + else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + { + toc_bottom_mode = true; + toc_bottom_idx = 2; + action = SELECT; + } + else// 目录项选择区域 + { + int clicked_toc_index = -1; + + if(x >= 10 && x <= 750 && y >= 20 && y <= 170) + { + clicked_toc_index = 0; + } + else if(x >= 10 && x <= 750 && y >= 180 && y <= 310) + { + clicked_toc_index = 1; + } + else if(x >= 10 && x <= 750 && y >= 330 && y <= 450) + { + clicked_toc_index = 2; + } + else if(x >= 10 && x <= 750 && y >= 470 && y <= 590) + { + clicked_toc_index = 3; + } + else if(x >= 10 && x <= 750 && y >= 620 && y <= 750) + { + clicked_toc_index = 4; + } + else if(x >= 10 && x <= 750 && y >= 770 && y <= 890) + { + clicked_toc_index = 5; + } + // 如果点击了目录项区域 + if(clicked_toc_index != -1) + { + // 判断是第一次点击还是第二次点击 + if(waiting_for_confirmation && last_clicked_toc_index == clicked_toc_index) + { + // 第二次点击:执行打开操作 + toc_index = clicked_toc_index; + library_bottom_mode = false; + rt_kprintf("Open book%d %d\n", toc_index, toc_index); + action = SELECT; + + // 重置状态 + waiting_for_confirmation = false; + last_clicked_toc_index = -1; + } + else + { + // 第一次点击:选择目录项并等待确认 + toc_index = clicked_toc_index; + last_clicked_toc_index = clicked_toc_index; + waiting_for_confirmation = true; + action = SELECT_BOX; + } + } + } + + break; + case SETTINGS_PAGE: // 设置页面 + // 设置页面每行左右箭头触控区域(与设置页布局一致) + if (x >= 100 && x <= 650 && y >= 160 && y <= 260) + { + settings_selected_idx = SET_TOUCH; + action = SELECT_BOX; + rt_kprintf("select touch switch\n"); + } + else if (x >= 100 && x <= 650 && y >= 300 && y <= 400) + { + settings_selected_idx = SET_TIMEOUT; + action = SELECT_BOX; + rt_kprintf("select timeout switch\n"); + } + else if (x >= 100 && x <= 650 && y >= 450 && y <= 540) + { + settings_selected_idx = SET_FULL_REFRESH; + action = SELECT_BOX; + rt_kprintf("select full refresh switch \n"); + } + else if (x >= 100 && x <= 650 && y >= 830 && y <= 950) + { + settings_selected_idx = SET_CONFIRM; + action = SELECT; + rt_kprintf("select touch switch\n"); + } + + if(settings_selected_idx == SET_TOUCH && 0<=x && x<= 50 && 160<=y && y<=260) + { + action = SELECT; + } + else if(settings_selected_idx == SET_TOUCH && 700<=x && x<=750 && 160<=y && y<=260) + { + action = SELECT; + } + else if(settings_selected_idx == SET_TIMEOUT && 0 <= x && x<=50 && 300 <= y && y<= 400) + { + action = PREV_OPTION; + rt_kprintf("select timeout Reduce\n"); + } + else if(settings_selected_idx == SET_TIMEOUT && 700<=x && x<=750 && 300<=y && y<= 400) + { + action = NEXT_OPTION; + rt_kprintf("select timeout increase\n"); + } + else if(settings_selected_idx == SET_FULL_REFRESH && 0 <= x && x<= 50 && 450 <= y && y<= 540) + { + action = PREV_OPTION; + } + else if(settings_selected_idx == SET_FULL_REFRESH && 700 <= x && x<= 750 && 450 <= y && y<= 540) + { + action = NEXT_OPTION; + } + break; + +} + + instance->last_action = action; if (action != NONE) @@ -133,7 +440,6 @@ void SF32_TouchControls::powerOffTouch() rt_kprintf("no touch device found\n"); } } - void SF32_TouchControls::powerOnTouch() { if (tp_device) { diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.h b/epdiy-epub/src/boards/controls/SF32_TouchControls.h index d9dfba6..1983a55 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.h +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.h @@ -14,7 +14,14 @@ class SF32_TouchControls : public TouchControls uint8_t ui_button_width = 120; uint8_t ui_button_height = 34; UIAction last_action = NONE; - + // 添加手势检测状态 + bool is_touch_down = false; // 是否正在触摸 + int touch_start_x = 0; // 按下时的 X 坐标 + int touch_start_y = 0; // 按下时的 Y 坐标 + int touch_current_x = 0; // 当前触摸 X 坐标 + int touch_current_y = 0; // 当前触摸 Y 坐标 + // 滑动检测阈值 + static const int SWIPE_THRESHOLD = 50; // 最小滑动距离阈值 public: static rt_err_t tp_rx_indicate(rt_device_t dev, rt_size_t size); diff --git a/epdiy-epub/src/boards/controls/TouchControls.h b/epdiy-epub/src/boards/controls/TouchControls.h index b0c8ba9..cc04d1f 100644 --- a/epdiy-epub/src/boards/controls/TouchControls.h +++ b/epdiy-epub/src/boards/controls/TouchControls.h @@ -8,7 +8,7 @@ class Renderer; class TouchControls { protected: - bool touch_enable = false; + bool touch_enable = 1; public: TouchControls(){}; diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index b06ae54..523b704 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -2,7 +2,7 @@ #include "EpubList/EpubList.h" #include "epub_screen.h" #include - +#include "type.h" extern TouchControls *touch_controls; extern "C" @@ -16,9 +16,9 @@ extern int g_last_read_index; // 主页面选项 typedef enum { - OPTION_OPEN_LIBRARY = 0, - OPTION_CONTINUE_READING, - OPTION_ENTER_SETTINGS + OPTION_OPEN_LIBRARY = 0, // 打开书库 + OPTION_CONTINUE_READING, // 继续阅读 + OPTION_ENTER_SETTINGS // 进入设置 } MainOption; static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” @@ -34,9 +34,18 @@ int screen_get_full_refresh_period() } // 切换全刷周期(循环) -void screen_cycle_full_refresh_period() +void screen_cycle_full_refresh_period(bool refresh) { - full_refresh_idx = (full_refresh_idx + 1) % kFullRefreshOptionsCount; // ?% 4 + if(refresh) + { + full_refresh_idx = (full_refresh_idx + 1) % kFullRefreshOptionsCount; // ?% 4 + + } + else + { + full_refresh_idx = (full_refresh_idx - 1) % kFullRefreshOptionsCount; // ?% 4 + + } } // 设置全刷周期索引 @@ -51,9 +60,8 @@ int screen_get_full_refresh_idx() return full_refresh_idx; } -// 设置页列表项 -typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; -static int settings_selected_idx = 0; + +int settings_selected_idx = 0; // 超时关机:5/10/30分钟、1小时、不关机(0) static const int kTimeoutOptions[] = {5, 10, 30, 60, 0}; // 单位:分钟,0为不关机 @@ -79,7 +87,7 @@ static void adjust_timeout(bool increase) } else { - timeout_idx = (timeout_idx - 1 + kTimeoutOptionsCount) % kTimeoutOptionsCount; + timeout_idx = (timeout_idx - 1) % kTimeoutOptionsCount; } timeout_shutdown_minutes = kTimeoutOptions[timeout_idx]; } @@ -101,7 +109,7 @@ int screen_get_main_selected_option() return (int)main_option; // 0: 打开书库, 1: 继续阅读, 2: 进入设置 } -// 主页面 +// 绘制主页面 static void render_main_page(Renderer *renderer) { renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); @@ -152,12 +160,12 @@ static void render_main_page(Renderer *renderer) int opt_h = renderer->get_line_height(); renderer->draw_text(mid_x + (mid_w - opt_w) / 2, y + (rect_h - opt_h) / 2, opt_text, false, true); } - +//主界面处理 void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) { if (needs_redraw || action == NONE) { - render_main_page(renderer); + render_main_page(renderer);//绘制主界面 return; } switch (action) @@ -195,7 +203,7 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) } // 设置页面 -static void render_settings_page(Renderer *renderer) +void render_settings_page(Renderer *renderer) { renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); @@ -334,6 +342,7 @@ static void render_settings_page(Renderer *renderer) renderer->draw_text(confirm_x + (confirm_w - c_w) / 2, confirm_y + (confirm_h - c_h) / 2, confirm, false, true); } +// 设置页面交互处理 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) { // 读取并清除一次性的触控箭头标记,避免后续硬件按键误用 @@ -376,6 +385,56 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) render_settings_page(renderer); } break; + case SELECT_BOX: + if(settings_selected_idx == SET_TOUCH) + { + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_TIMEOUT) + { + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_FULL_REFRESH) + { + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_CONFIRM) + { + render_settings_page(renderer); + return true; + } + break; + case PREV_OPTION: + if (settings_selected_idx == SET_TIMEOUT) + { + // SELECT 在超时关机项上为加操作(循环) + adjust_timeout(false); + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_FULL_REFRESH) + { + + screen_cycle_full_refresh_period(false); + set_part_disp_times(screen_get_full_refresh_period()); + render_settings_page(renderer); + } + + break; + case NEXT_OPTION: + if (settings_selected_idx == SET_TIMEOUT) + { + // SELECT 在超时关机项上为加操作(循环) + adjust_timeout(true); + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_FULL_REFRESH) + { + + screen_cycle_full_refresh_period(true); + set_part_disp_times(screen_get_full_refresh_period()); + render_settings_page(renderer); + } + break; case SELECT: if (settings_selected_idx == SET_TOUCH) { @@ -399,7 +458,7 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) if (settings_selected_idx == SET_FULL_REFRESH) { // SELECT 在全刷周期项上为加操作(循环) - screen_cycle_full_refresh_period(); + screen_cycle_full_refresh_period(true); set_part_disp_times(screen_get_full_refresh_period()); render_settings_page(renderer); break; diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h index d3f1646..148141b 100644 --- a/epdiy-epub/src/epub_screen.h +++ b/epdiy-epub/src/epub_screen.h @@ -22,6 +22,6 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw); // 设置页面交互与渲染;返回 true 表示确认并退出到主页面 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw); // 切换全刷周期(循环) -void screen_cycle_full_refresh_period(); +void screen_cycle_full_refresh_period(bool refresh); // 获取当前全刷周期值 int screen_get_full_refresh_period(); \ No newline at end of file diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 4d61b12..9f00ed6 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -5,13 +5,14 @@ #include "EpubList/EpubToc.h" #include #include "boards/Board.h" +#include "boards/controls/Actions.h" #include "boards/controls/SF32_TouchControls.h" #include "epub_screen.h" #include "boards/SF32PaperRenderer.h" #include "gui_app_pm.h" #include "bf0_pm.h" #include "epd_driver.h" - +#include "type.h" #undef LOG_TAG #undef DBG_LEVEL #define DBG_LEVEL DBG_LOG //DBG_INFO // @@ -32,20 +33,9 @@ extern "C" extern const uint8_t shutdown_map[]; } - const char *TAG = "main"; -typedef enum { - MAIN_PAGE, // 新主页面 - SELECTING_EPUB, // 电子书列表页面(书库) - SELECTING_TABLE_CONTENTS, // 电子书目录页面 - READING_EPUB, // 阅读页面 - SETTINGS_PAGE, // 通用功能设置页面 - WELCOME_PAGE, // 欢迎页面 - LOW_POWER_PAGE, // 低电量页面 - CHARGING_PAGE, // 充电页面 - SHUTDOWN_PAGE // 关机页面 -} AppUIState; + // 默认显示新主页面,而非书库页面 AppUIState ui_state = MAIN_PAGE; @@ -62,7 +52,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw); void back_to_main_page(); static EpubList *epub_list = nullptr; -static EpubReader *reader = nullptr; +EpubReader *reader = nullptr; static EpubToc *contents = nullptr; static bool charge_full = false; Battery *battery = nullptr; @@ -71,9 +61,18 @@ Renderer *renderer = nullptr; TouchControls *touch_controls = nullptr; // 书库页底部按钮选择状态 -static bool library_bottom_mode = false; // 是否处于底部三按钮选择模式 -static int library_bottom_idx = 1; // 当前底部按钮索引:0上一页,1主页面,2下一页 - +bool library_bottom_mode = false; // 是否处于底部三按钮选择模式 +int library_bottom_idx = 1; // 当前底部按钮索引:0上一页,1主页面,2下一页 +int book_index;//用于记录电子书触控选择 +int current_page; // 当前页面 +int start_index; // 当前页起始索引 +// 计算全局索引 = 页起始索引 + 页内偏移 +int global_index; +bool toc_bottom_mode = false; +int toc_index;//用于记录目录触控选择 +int toc_bottom_idx = 1; // 0:上一页,1:主页面,2:下一页 +int sel; +int touch_sel; rt_mq_t ui_queue = RT_NULL; // 主页面选项 @@ -86,169 +85,178 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red void handleEpub(Renderer *renderer, UIAction action) { - if (!reader) - { - reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); - reader->load(); - // 记录最近一次进入阅读的书籍索引 - g_last_read_index = epub_list_state.selected_item; - } - switch (action) - { - case UP: - if (reader->is_overlay_active()) - { - reader->overlay_move_left(); - } - else - { - reader->prev(); - } - break; - case DOWN: - if (reader->is_overlay_active()) + if (!reader) { - reader->overlay_move_right(); - } - else - { - reader->next(); + reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); + reader->load(); + // 记录最近一次进入阅读的书籍索引 + g_last_read_index = epub_list_state.selected_item; } - break; - case SELECT: - if (reader->is_overlay_active()) + + switch (action) { - int sel = reader->get_overlay_selected(); - // 1/3:改变中心属性;2:执行当前属性(触控取反 / 全刷周期循环) - if (sel == 0) - { - if(reader->overlay_is_center_touch()) + case UP: + if (reader->is_overlay_active()) { - reader->overlay_set_center_mode_full_refresh(); + reader->overlay_move_left(); } else { - reader->overlay_set_center_mode_touch(); + reader->prev(); } - } - else if (sel == 2) - { - if(reader->overlay_is_center_touch()) + break; + case DOWN: + if (reader->is_overlay_active()) { - reader->overlay_set_center_mode_full_refresh(); + reader->overlay_move_right(); } else { - reader->overlay_set_center_mode_touch(); + reader->next(); } - - } - else if (sel == 1) - { - // 中心矩形:根据当前属性执行 - if (reader->overlay_is_center_touch()) + break; + case SELECT: + if (reader->is_overlay_active()) { - bool cur = touch_controls ? touch_controls->isTouchEnabled() : false; - if (touch_controls) - { - touch_controls->setTouchEnable(!cur); - if (!cur) touch_controls->powerOnTouch(); else touch_controls->powerOffTouch(); - } - reader->overlay_set_touch_enabled(!cur); + int sel = reader->get_overlay_selected(); + // 1/3:改变中心属性;2:执行当前属性(触控取反 / 全刷周期循环) + if(touch_sel >=0 && touch_sel <=10) + { + sel = -1; + } + if (sel == 0 || touch_sel == 0) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + } + else if (sel == 2 || touch_sel == 2) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + } + else if (sel == 1 || touch_sel == 1) + { + // 中心矩形:根据当前属性执行 + if (reader->overlay_is_center_touch()) + { + bool cur = touch_controls ? touch_controls->isTouchEnabled() : false; + if (touch_controls) + { + touch_controls->setTouchEnable(!cur); + if (!cur) touch_controls->powerOnTouch(); else touch_controls->powerOffTouch(); + } + reader->overlay_set_touch_enabled(!cur); + } + else + { + reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/每次(0) 之间循环 + set_part_disp_times(reader->overlay_get_full_refresh_value()); + } + } + if (sel == 9 || touch_sel == 9) //目录 + { + ui_state = SELECTING_TABLE_CONTENTS; + renderer->set_margin_bottom(0); + reader->stop_overlay(); + delete reader; + reader = nullptr; + contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); + contents->load(); + contents->set_needs_redraw(); + handleEpubTableContents(renderer, NONE, true); + touch_sel = -1; + return; + } + else if (sel == 8 || touch_sel == 8) //确认:1.按第六格累积值跳页 + { + // 跳转到第六格显示的目标页 + int target = reader->overlay_get_target_page(); + if (target < 1) target = 1; + extern EpubListState epub_list_state; + epub_list_state.epub_list[epub_list_state.selected_item].current_page = (uint16_t)(target - 1); + reader->overlay_reset_jump(); + reader->stop_overlay(); + } + else if (sel == 10 || touch_sel == 10) //书库 + { + ui_state = SELECTING_EPUB; + renderer->set_margin_bottom(0); + reader->stop_overlay(); + renderer->clear_screen(); + delete reader; + reader = nullptr; + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + handleEpubList(renderer, NONE, true); + touch_sel = -1; + return; + } + else if (sel == 3 || touch_sel == 3) + { + reader->overlay_adjust_target_page(-5); + } + else if (sel == 4 || touch_sel == 4) + { + reader->overlay_adjust_target_page(-1); + } + else if (sel == 6 || touch_sel == 6) + { + reader->overlay_adjust_target_page(1); + } + else if (sel == 7 || touch_sel == 7) + { + reader->overlay_adjust_target_page(5); + } + touch_sel = -1; } else { - reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/每次(0) 之间循环 - set_part_disp_times(reader->overlay_get_full_refresh_value()); + // switch back to main screen + renderer->clear_screen(); + // clear the epub reader away + delete reader; + reader = nullptr; + // force a redraw + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + renderer->set_margin_bottom(0); + back_to_main_page(); + + return; } - } - if (sel == 9) //目录 - { - ui_state = SELECTING_TABLE_CONTENTS; - renderer->set_margin_bottom(0); - reader->stop_overlay(); - delete reader; - reader = nullptr; - contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); - contents->load(); - contents->set_needs_redraw(); - handleEpubTableContents(renderer, NONE, true); - return; - } - else if (sel == 8) //确认:1.按第六格累积值跳页 - { - // 跳转到第六格显示的目标页 - int target = reader->overlay_get_target_page(); - if (target < 1) target = 1; - extern EpubListState epub_list_state; - epub_list_state.epub_list[epub_list_state.selected_item].current_page = (uint16_t)(target - 1); - reader->overlay_reset_jump(); - reader->stop_overlay(); - } - else if (sel == 10) //书库 - { - ui_state = SELECTING_EPUB; - renderer->set_margin_bottom(0); - reader->stop_overlay(); - renderer->clear_screen(); - delete reader; - reader = nullptr; - if (!epub_list) - { - epub_list = new EpubList(renderer, epub_list_state); + break; + case UPGLIDE: + // 激活阅读页下半屏覆盖操作层 + // 防止重复激活 + if (!reader->is_overlay_active()) { + reader->start_overlay(); + // 默认中心属性为触控开关,初始同步当前触控状态 + reader->overlay_set_center_mode_touch(); + if (touch_controls) + reader->overlay_set_touch_enabled(touch_controls->isTouchEnabled()); } - handleEpubList(renderer, NONE, true); - return; - } - else if (sel == 3) - { - reader->overlay_adjust_target_page(-5); - } - else if (sel == 4) - { - reader->overlay_adjust_target_page(-1); - } - else if (sel == 6) - { - reader->overlay_adjust_target_page(1); - } - else if (sel == 7) - { - reader->overlay_adjust_target_page(5); - } - - } - else - { - // switch back to main screen - renderer->clear_screen(); - // clear the epub reader away - delete reader; - reader = nullptr; - // force a redraw - if (!epub_list) - { - epub_list = new EpubList(renderer, epub_list_state); - } - renderer->set_margin_bottom(0); - back_to_main_page(); - - return; + break; + case NONE: + default: + break; } - break; - case UPGLIDE: - // 激活阅读页下半屏覆盖操作层 - reader->start_overlay(); - // 默认中心属性为触控开关,初始同步当前触控状态 - reader->overlay_set_center_mode_touch(); - if (touch_controls) - reader->overlay_set_touch_enabled(touch_controls->isTouchEnabled()); - break; - case NONE: - default: - break; - } - reader->render(); + reader->render(); } //目录页的处理 void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw) @@ -259,8 +267,7 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red contents->set_needs_redraw(); contents->load(); } - static bool toc_bottom_mode = false; - static int toc_bottom_idx = 1; // 0:上一页,1:主页面,2:下一页 + if (needs_redraw) { toc_bottom_mode = false; @@ -338,6 +345,44 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red } } break; + case SELECT_BOX: + // 计算当前页面相关信息 + current_page = epub_index_state.selected_item / 6; // 每页6个目录项 + start_index = current_page * 6; // 当前页起始索引 + // 计算全局索引 = 页起始索引 + 页内偏移 + global_index = start_index + toc_index; + // 边界检查:确保点击的目录项存在 + if (global_index < contents->get_items_count() && contents->get_items_count() > 0) + { + // 更新选中的目录项 + epub_index_state.selected_item = global_index; + + // 根据toc_index确定点击的是哪个位置的目录项(0-5) + switch(toc_index) + { + case 0: + contents->switch_book(global_index); + break; + case 1: + contents->switch_book(global_index); + break; + case 2: + contents->switch_book(global_index); + break; + case 3: + contents->switch_book(global_index); + break; + case 4: + contents->switch_book(global_index); + break; + case 5: + contents->switch_book(global_index); + break; + default: + break; + } + } + break; case SELECT: if (toc_bottom_mode) { @@ -499,6 +544,33 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } } break; + case SELECT_BOX: + current_page = epub_list_state.selected_item / 4; // 当前页面 + start_index = current_page * 4; // 当前页起始索引 + // 计算全局索引 = 页起始索引 + 页内偏移 + global_index = start_index + book_index; + // 边界检查 + if (global_index < epub_list_state.num_epubs) + { + + if(book_index == 0) + { + epub_list->switch_book(global_index); + } + else if(book_index == 1) + { + epub_list->switch_book(global_index); + } + else if(book_index == 2) + { + epub_list->switch_book(global_index); + } + else if(book_index == 3) + { + epub_list->switch_book(global_index); + } + } + break; case SELECT: if (library_bottom_mode) { @@ -1076,7 +1148,7 @@ extern "C" int main() { // dump out the epub list state - //rt_pm_request(PM_SLEEP_MODE_IDLE); + rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); diff --git a/epdiy-epub/src/type.h b/epdiy-epub/src/type.h new file mode 100644 index 0000000..820485d --- /dev/null +++ b/epdiy-epub/src/type.h @@ -0,0 +1,38 @@ +#ifndef TYPES_H +#define TYPES_H + +// typedef enum { +// MAIN_PAGE, +// SELECTING_EPUB, +// SELECTING_TABLE_CONTENTS, +// READING_EPUB, +// SETTINGS_PAGE +// } UIState; + +// typedef enum { +// MAIN_MENU, +// WELCOME_PAGE, +// LOW_POWER_PAGE, +// CHARGING_PAGE +// } UIState2; + +// 设置页列表项 +typedef enum { + SET_TOUCH = 0, + SET_TIMEOUT = 1, + SET_FULL_REFRESH = 2, + SET_CONFIRM = 3 +} SettingsItem; + +typedef enum { + MAIN_PAGE, // 新主页面 + SELECTING_EPUB, // 电子书列表页面(书库) + SELECTING_TABLE_CONTENTS, // 电子书目录页面 + READING_EPUB, // 阅读页面 + SETTINGS_PAGE, // 通用功能设置页面 + WELCOME_PAGE, // 欢迎页面 + LOW_POWER_PAGE, // 低电量页面 + CHARGING_PAGE, // 充电页面 + SHUTDOWN_PAGE // 关机页面 +} AppUIState; +#endif \ No newline at end of file From dd1035eeed6958a5b616c7e40f4dda5a00578778 Mon Sep 17 00:00:00 2001 From: minjiezhong Date: Thu, 22 Jan 2026 10:48:45 +0800 Subject: [PATCH 10/27] =?UTF-8?q?1.=E8=A7=A3=E5=86=B3=E4=BA=86=E4=B9=A6?= =?UTF-8?q?=E5=BA=93=E9=A1=B5=E9=9D=A2=E3=80=81=E7=9B=AE=E5=BD=95=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E7=82=B9=E5=87=BB=E4=B8=8B=E4=B8=80=E9=A1=B5=EF=BC=8C?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E4=B9=A6=E7=B1=8D=E5=92=8C=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E5=A4=B1=E6=95=88=E7=9A=84bug=202.=E8=A7=A3=E5=86=B3=E4=BA=86?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E9=A1=B5=E9=9D=A2=E7=82=B9=E5=87=BB=E5=8F=B3?= =?UTF-8?q?=E4=B8=8B=E8=A7=92=E4=BC=9A=E5=87=BA=E7=8E=B0=E5=94=A4=E9=86=92?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E8=AE=BE=E7=BD=AE=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boards/controls/SF32_TouchControls.cpp | 37 +++--- .../src/boards/controls/SF32_TouchControls.h | 3 - epdiy-epub/src/main.cpp | 109 +++++++++++------- 3 files changed, 89 insertions(+), 60 deletions(-) diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index c8e73c8..673c99a 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -26,12 +26,15 @@ static bool waiting_for_confirmation = false; // 是否正在等待确认 extern int touch_sel; extern EpubReader *reader; +static const int SWIPE_THRESHOLD = 100; // 最小滑动距离阈值 +static bool is_touch_started = false; // 全局或类成员变量 rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { SF32_TouchControls *instance = static_cast (dev->user_data); struct touch_message touch_data; rt_uint16_t x,y; + int i = 0;//用于记录第一次按下的情况 /*Read touch point data*/ rt_device_read(dev, 0, &touch_data, 1); @@ -50,48 +53,50 @@ rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) rt_kprintf("Touch down [%d,%d]\r\n", x, y); // 记录按下时的位置 - instance->touch_start_x = x; - instance->touch_start_y = y; + if (!is_touch_started) // 只允许第一次触发 + { + instance->touch_start_y = y; + rt_kprintf("Touch start\r\n"); + is_touch_started = true; + } instance->is_touch_down = true; - + instance->touch_current_y = 0; // 处理其他触控逻辑... } else { rt_kprintf("Touch up [%d,%d]\r\n", x, y); - instance->touch_current_x = x; instance->touch_current_y = y; // 检查是否构成向上滑动手势 - if (instance->is_touch_down) { - int y_diff = instance->touch_start_y - touch_data.y; // 注意坐标转换 - int x_diff = abs(instance->touch_start_x - touch_data.x); - rt_kprintf("Touch up diff Y: %d, X: %d\r\n", y_diff, x_diff); + if (instance->is_touch_down) + { + int y_diff = instance->touch_start_y - instance->touch_current_y; // 注意坐标转换 + rt_kprintf("Touch up diff Y: %d\r\n", y_diff); - // 检查时间间隔,防止连续触发 - rt_tick_t current_time = rt_tick_get(); if(reader->is_overlay_active() == false) { - if (y_diff > instance->SWIPE_THRESHOLD && y_diff > abs(x_diff)) + if (y_diff > SWIPE_THRESHOLD) { rt_kprintf("Up swipe detected! Diff: %d\n", y_diff); // 发送向上滑动动作 UIAction action = UPGLIDE; instance->last_action = action; - instance->on_action(action); - + instance->on_action(action); - // 重置状态 - instance->is_touch_down = false; - return RT_EOK; } } + + } + // 清空坐标值,避免下次误用 + instance->touch_start_y = 0; // 重置触摸状态 instance->is_touch_down = false; + is_touch_started = false; } // 只处理按下事件,忽略释放事件 diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.h b/epdiy-epub/src/boards/controls/SF32_TouchControls.h index 1983a55..0ad4b12 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.h +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.h @@ -16,12 +16,9 @@ class SF32_TouchControls : public TouchControls UIAction last_action = NONE; // 添加手势检测状态 bool is_touch_down = false; // 是否正在触摸 - int touch_start_x = 0; // 按下时的 X 坐标 int touch_start_y = 0; // 按下时的 Y 坐标 - int touch_current_x = 0; // 当前触摸 X 坐标 int touch_current_y = 0; // 当前触摸 Y 坐标 // 滑动检测阈值 - static const int SWIPE_THRESHOLD = 50; // 最小滑动距离阈值 public: static rt_err_t tp_rx_indicate(rt_device_t dev, rt_size_t size); diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 9f00ed6..fe453bb 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -346,6 +346,11 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red } break; case SELECT_BOX: + // 如果在底部模式,先退出底部模式 + if (toc_bottom_mode) + { + toc_bottom_mode = false; + } // 计算当前页面相关信息 current_page = epub_index_state.selected_item / 6; // 每页6个目录项 start_index = current_page * 6; // 当前页起始索引 @@ -403,28 +408,37 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red handleEpubList(renderer, NONE, true); return; } - else if (toc_bottom_idx == 0) + else if (toc_bottom_idx == 0) // 上一页 { - // 上一页 if (current_page > 0) { - epub_index_state.selected_item -= per_page; - if (epub_index_state.selected_item < 0) epub_index_state.selected_item = 0; + // 计算新页面(上一页) + int new_page = current_page - 1; + // 将选中项设置为新页面的第一项 + epub_index_state.selected_item = new_page * per_page; + if (epub_index_state.selected_item < 0) + epub_index_state.selected_item = 0; + + // 退出底部选择模式,回到列表选择状态 + toc_bottom_mode = false; contents->set_needs_redraw(); } - // 保持底部模式,允许连续翻页 } - else if (toc_bottom_idx == 2) + else if (toc_bottom_idx == 2) // 下一页 { - // 下一页 if (current_page < max_page) { - epub_index_state.selected_item += per_page; + // 计算新页面(下一页) + int new_page = current_page + 1; + // 将选中项设置为新页面的第一项 + epub_index_state.selected_item = new_page * per_page; if (epub_index_state.selected_item >= count) - epub_index_state.selected_item = count - 1; + epub_index_state.selected_item = ((count - 1) / per_page) * per_page; // 确保在最后一页的第一项 + + // 退出底部选择模式,回到列表选择状态 + toc_bottom_mode = false; contents->set_needs_redraw(); } - // 保持底部模式,允许连续翻页 } } else @@ -545,6 +559,10 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } break; case SELECT_BOX: + // 如果在底部模式,先退出底部模式 + if (library_bottom_mode) { + library_bottom_mode = false; + } current_page = epub_list_state.selected_item / 4; // 当前页面 start_index = current_page * 4; // 当前页起始索引 // 计算全局索引 = 页起始索引 + 页内偏移 @@ -572,44 +590,53 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } break; case SELECT: - if (library_bottom_mode) - { + if (library_bottom_mode) + { int per_page = 4; int current_page = epub_list_state.selected_item / per_page; int max_page = (epub_list_state.num_epubs == 0) ? 0 : ( (epub_list_state.num_epubs - 1) / per_page ); if (library_bottom_idx == 1) { - // 主页面:返回主页面 - rt_kprintf("从书库页返回主页面\n"); - back_to_main_page(); - return; + // 主页面:返回主页面 + rt_kprintf("从书库页返回主页面\n"); + back_to_main_page(); + return; } - else if (library_bottom_idx == 0) + else if (library_bottom_idx == 0) // 上一页 { - // 上一页 - if (current_page > 0) - { - epub_list_state.selected_item -= per_page; - if (epub_list_state.selected_item < 0) epub_list_state.selected_item = 0; - epub_list->set_needs_redraw(); - } - + if (current_page > 0) + { + // 计算新页面(上一页) + int new_page = current_page - 1; + // 将选中项设置为新页面的第一本书 + epub_list_state.selected_item = new_page * per_page; + if (epub_list_state.selected_item < 0) + epub_list_state.selected_item = 0; + + // 退出底部选择模式,回到列表选择状态 + library_bottom_mode = false; + epub_list->set_needs_redraw(); + } } - else if (library_bottom_idx == 2) + else if (library_bottom_idx == 2) // 下一页 { - // 下一页 - if (current_page < max_page) - { - epub_list_state.selected_item += per_page; - if (epub_list_state.selected_item >= epub_list_state.num_epubs) - epub_list_state.selected_item = epub_list_state.num_epubs - 1; - epub_list->set_needs_redraw(); - } - + if (current_page < max_page) + { + // 计算新页面(下一页) + int new_page = current_page + 1; + // 将选中项设置为新页面的第一本书 + epub_list_state.selected_item = new_page * per_page; + if (epub_list_state.selected_item >= epub_list_state.num_epubs) + epub_list_state.selected_item = ((epub_list_state.num_epubs - 1) / per_page) * per_page; // 确保在最后一页的第一本书 + + // 退出底部选择模式,回到列表选择状态 + library_bottom_mode = false; + epub_list->set_needs_redraw(); + } } - } - else - { + } + else + { // 进入目录选择页面 ui_state = SELECTING_TABLE_CONTENTS; contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); @@ -617,8 +644,8 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) contents->set_needs_redraw(); handleEpubTableContents(renderer, NONE, true); return; - } - break; + } + break; case NONE: default: // nothing to do @@ -1148,7 +1175,7 @@ extern "C" int main() { // dump out the epub list state - rt_pm_request(PM_SLEEP_MODE_IDLE); + //rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); From 6220d27fce3eefd4295b34c326f815aaececdfcd Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 23 Jan 2026 19:05:40 +0800 Subject: [PATCH 11/27] =?UTF-8?q?=E6=96=B0=E5=BB=BA=E6=9D=BF=E5=AD=90base?= =?UTF-8?q?=E4=B8=8E1.2=E7=9A=84board=EF=BC=8C1.1=E4=B8=8E1.2=E5=A4=8D?= =?UTF-8?q?=E7=94=A8base?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 0fd757db4ab38fc765c2fe01f76ef7f1b4f0a80b Mon Sep 17 00:00:00 2001 From: minjiezhong Date: Wed, 4 Feb 2026 15:55:10 +0800 Subject: [PATCH 12/27] =?UTF-8?q?1=E3=80=81=E5=B0=86=E6=AF=8F=E4=B8=AA?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=BB=98=E5=88=B6=E5=9D=90=E6=A0=87=E8=B7=9F?= =?UTF-8?q?=E8=A7=A6=E6=8E=A7=E5=8C=BA=E5=9F=9F=E8=BF=9B=E8=A1=8C=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubList.cpp | 30 +++++- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 44 ++++++++- epdiy-epub/lib/Epub/EpubList/EpubToc.cpp | 32 +++++- epdiy-epub/src/SConscript | 2 +- .../boards/controls/SF32_TouchControls.cpp | 97 +++++++++++-------- epdiy-epub/src/epub_screen.cpp | 66 ++++++++++++- epdiy-epub/src/main.cpp | 4 +- 7 files changed, 223 insertions(+), 52 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp index 55f42d0..c8ed77b 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp @@ -1,6 +1,6 @@ #include "EpubList.h" #include - +#include "UIRegionsManager.h" #ifndef UNIT_TEST @@ -134,6 +134,7 @@ bool EpubList::load(const char *path) void EpubList::render() { + //clear_areas(); ulog_d(TAG, "Rendering EPUB list"); // what page are we on? int current_page = state.selected_item / EPUBS_PER_PAGE; @@ -157,6 +158,7 @@ void EpubList::render() } for (int i = start_index; i < start_index + EPUBS_PER_PAGE && i < state.num_epubs; i++) { + // do we need to draw a new page of items? if (current_page != state.previous_rendered_page) { @@ -191,6 +193,16 @@ void EpubList::render() title_block->render(renderer, i, text_xpos, text_ypos + y_offset); y_offset += renderer->get_line_height(); } + // 计算整体区域范围 + int area_start_x = image_xpos; + int area_start_y = image_ypos; + int area_end_x = std::max(image_xpos + image_width, text_xpos + text_width); + int area_end_y = std::max(image_ypos + image_height, text_ypos + title_height); + if((i%4)<4) + { + static_add_area(area_start_x, area_start_y, area_end_x - area_start_x, area_end_y - area_start_y, (i%4)); + } + delete title_block; delete epub; } @@ -268,6 +280,22 @@ void EpubList::render() }; draw_button(btn_x0, "上一页", m_bottom_mode && m_bottom_idx == 0); + int start_up_page_x = btn_x0; + int start_up_page_y = btn_y + btn_gap * 2; + int end_up_page_x = btn_w; + int end_up_page_y = btn_h; + int start_page_x = btn_x0; + static_add_area(start_up_page_x, start_up_page_y, end_up_page_x, end_up_page_y, 4); draw_button(btn_x1, "主页面", m_bottom_mode && m_bottom_idx == 1); + int start_main_page_x = btn_x1; + int start_main_page_y = btn_y + btn_gap *2; + int end_main_page_x = btn_w; + int end_main_page_y = btn_h; + static_add_area(start_main_page_x, start_main_page_y, end_main_page_x, end_main_page_y, 5); draw_button(btn_x2, "下一页", m_bottom_mode && m_bottom_idx == 2); + int start_down_page_x = btn_x2; + int start_down_page_y = btn_y + btn_gap *2; + int end_down_page_x = btn_w; + int end_down_page_y = btn_h; + static_add_area(start_down_page_x, start_down_page_y, end_down_page_x, end_down_page_y, 6); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 201478f..34d09e2 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -13,6 +13,7 @@ #include "../Renderer/Renderer.h" #include "epub_mem.h" #include "epub_screen.h" +#include "UIRegionsManager.h" static const char *TAG = "EREADER"; extern "C" rt_uint32_t heap_free_size(void); @@ -141,18 +142,20 @@ void EpubReader::set_state_section(uint16_t current_section) { void EpubReader::render_overlay() { + clear_areas(); // 清除之前的区域记录 + int page_w = renderer->get_page_width(); int page_h = renderer->get_page_height(); int area_y = (page_h * 2) / 3; // 覆盖下方 1/3 屏幕 int area_h = page_h - area_y; - renderer->fill_rect(0, area_y, page_w, area_h, 240); + renderer->fill_rect(0, area_y, page_w, area_h, 240);//绘制灰色背景 // 三行布局:3,5,3 const int rows = 3; const int cols[rows] = {3, 5, 3}; const int gap_h = 20; // 行间距 - const int gap_w = 10; + const int gap_w = 10; // 列间距 const int row_h = 80; // 每行高度 // 纵向居中放置三行 int content_h = rows * row_h + (rows + 1) * gap_h; @@ -214,6 +217,19 @@ void EpubReader::render_overlay() int w2 = usable_w - w0 - w1; int widths[3] = { w0, w1, w2 }; int cur_x = gap_w; + //将坐标位置映射到触控中 + int first_one_x = cur_x;; + int first_one_y = y; + static_add_area(first_one_x, first_one_y, widths[0], row_h,0); + + int second_one_x = cur_x + widths[0] + gap_w; + int second_one_y = y; + static_add_area(second_one_x, second_one_y, widths[1], row_h,1); + + int third_one_x = cur_x + widths[0] + widths[1] + 2 * gap_w; + int third_one_y = y; + static_add_area(third_one_x, third_one_y, widths[2], row_h,2); + for (int i = 0; i < c; ++i) { int w = widths[i]; @@ -245,6 +261,30 @@ void EpubReader::render_overlay() { int usable_w = page_w - (c + 1) * gap_w; int btn_w = usable_w / c; + // 第二行触控区域映射(索引3-7) + if (r == 1) // 第二行 + { + for (int i = 0; i < c; ++i) // c = 5 + { + int x = gap_w + i * (btn_w + gap_w); + int y_coord = y0 + gap_h + r * (row_h + gap_h); + + // 添加触控区域(索引3-7对应按钮) + static_add_area(x, y_coord, btn_w, row_h, 3 + i); + } + } + // 第三行触控区域映射(索引8-10) + else if (r == 2) // 第三行 + { + for (int i = 0; i < c; ++i) // c = 3 + { + int x = gap_w + i * (btn_w + gap_w); + int y_coord = y0 + gap_h + r * (row_h + gap_h); + + // 添加触控区域(索引8-10对应按钮) + static_add_area(x, y_coord, btn_w, row_h, 8 + i); + } + } for (int i = 0; i < c; ++i) { int x = gap_w + i * (btn_w + gap_w); diff --git a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp index 88c45d2..1e23d1c 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp @@ -1,4 +1,5 @@ #include "EpubToc.h" +#include "UIRegionsManager.h" static const char *TAG = "PUBINDEX"; #define PADDING 14 @@ -66,6 +67,7 @@ bool EpubToc::load() // required as we're not rendering thumbnails void EpubToc::render() { + // 初始化固定区域(仅首次调用) ulog_d(TAG, "Rendering EPUB index"); // what page are we on? int current_page = state.selected_item / ITEMS_PER_PAGE; @@ -75,6 +77,7 @@ void EpubToc::render() int cell_height = (renderer->get_page_height() - bottom_area_height - bottom_margin) / ITEMS_PER_PAGE; int start_index = current_page * ITEMS_PER_PAGE; int ypos = 0; + // starting a fresh page or rendering from scratch? ulog_i(TAG, "Current page is %d, previous page %d, redraw=%d", current_page, state.previous_rendered_page, m_needs_redraw); if (current_page != state.previous_rendered_page || m_needs_redraw) @@ -108,6 +111,16 @@ void EpubToc::render() } // clean up the temporary index block delete title_block; + // 计算整体区域范围并写入 + int area_start_x = 0; + int area_start_y = ypos + PADDING / 2; + int area_end_x = renderer->get_page_width(); + int area_end_y = ypos + cell_height - PADDING / 2; + + if ((i % ITEMS_PER_PAGE) < ITEMS_PER_PAGE) + { + static_add_area(area_start_x, area_start_y, area_end_x - area_start_x, area_end_y - area_start_y, (i % ITEMS_PER_PAGE)); + } } // clear the selection box around the previous selected item if (state.previous_selected_item == i) @@ -155,7 +168,7 @@ void EpubToc::render() int btn_h = 80; int btn_y = area_y + (bottom_area_height - btn_h) / 2; int btn_x0 = btn_gap; // 上一页 - int btn_x1 = btn_gap * 2 + btn_w; // 主页面 + int btn_x1 = btn_gap * 2 + btn_w; // 书库 int btn_x2 = btn_gap * 3 + btn_w * 2; // 下一页 auto draw_button = [&](int x, const char* text, bool selected) @@ -181,8 +194,25 @@ void EpubToc::render() }; draw_button(btn_x0, "上一页", m_bottom_mode && m_bottom_idx == 0); + int start_up_page_x = btn_x0; + int start_up_page_y = btn_y + btn_gap * 2; + int end_up_page_x = btn_w; + int end_up_page_y = btn_h; + int start_page_x = btn_x0; + static_add_area(start_up_page_x, start_up_page_y, end_up_page_x, end_up_page_y, 6); + draw_button(btn_x1, "书库", m_bottom_mode && m_bottom_idx == 1); + int start_main_page_x = btn_x1; + int start_main_page_y = btn_y + btn_gap *2; + int end_main_page_x = btn_w; + int end_main_page_y = btn_h; + static_add_area(start_main_page_x, start_main_page_y, end_main_page_x, end_main_page_y, 7); draw_button(btn_x2, "下一页", m_bottom_mode && m_bottom_idx == 2); + int start_down_page_x = btn_x2; + int start_down_page_y = btn_y + btn_gap *2; + int end_down_page_x = btn_w; + int end_down_page_y = btn_h; + static_add_area(start_down_page_x, start_down_page_y, end_down_page_x, end_down_page_y, 8); } uint16_t EpubToc::get_selected_toc() diff --git a/epdiy-epub/src/SConscript b/epdiy-epub/src/SConscript index 6c590b3..d1f0436 100644 --- a/epdiy-epub/src/SConscript +++ b/epdiy-epub/src/SConscript @@ -4,7 +4,7 @@ from building import * import rtconfig cwd = GetCurrentDir() -src = ['main.cpp','epub_screen.cpp','epub_mem.c','epub_fonts.c'] +src = ['main.cpp','UIRegionsManager.cpp','epub_screen.cpp','epub_mem.c','epub_fonts.c'] src = src + Glob('./assets/*.c') CPPPATH = [cwd] diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index 673c99a..fb4609c 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -5,6 +5,7 @@ #include "type.h" #include "epub_screen.h" #include "EpubReader.h" +#include "UIRegionsManager.h" #ifdef BSP_USING_TOUCHD #include "drv_touch.h" #endif @@ -29,6 +30,7 @@ extern EpubReader *reader; static const int SWIPE_THRESHOLD = 100; // 最小滑动距离阈值 static bool is_touch_started = false; // 全局或类成员变量 +extern AreaRect g_area_array[]; rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { SF32_TouchControls *instance = static_cast (dev->user_data); @@ -110,17 +112,17 @@ rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) switch (ui_state) { case MAIN_PAGE://主页面 - if (x >= 10 && x <= 80 && y >= 950 && y <= 1000) + if (x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) { rt_kprintf("Touch left < \n"); action = UP; // 对应 KEY3 功能 } - else if (x >= 650 && x <= 750 && y >= 950 && y <= 1000) + else if (x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) { action = DOWN; // 对应 KEY1 功能 rt_kprintf("Touch right > \n"); } - else if (x >= 250 && x <= 500 && y >= 950 && y <= 1000) + else if (x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { action = SELECT; // 对应 KEY2 功能 rt_kprintf("Touch middle SELECT \n"); @@ -128,19 +130,19 @@ switch (ui_state) break; case SELECTING_EPUB://书库页面 // 检查是否点击了功能控制按钮 - if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y) { library_bottom_mode = true; library_bottom_idx = 0; action = SELECT; } - else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + else if(x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) { library_bottom_mode = true; library_bottom_idx = 1; action = SELECT; } - else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + else if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y) { library_bottom_mode = true; library_bottom_idx = 2; @@ -151,19 +153,19 @@ switch (ui_state) // 处理书籍选择区域 int clicked_book_index = -1; - if(x >= 10 && x <= 740 && y >= 60 && y <= 240) + if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) { clicked_book_index = 0; } - else if(x >= 10 && x <= 740 && y >= 270 && y <= 450) + else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) { clicked_book_index = 1; } - else if(x >= 10 && x <= 740 && y >= 470 && y <= 680) + else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { clicked_book_index = 2; } - else if(x >= 10 && x <= 740 && y >= 700 && y <= 900) + else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y) { clicked_book_index = 3; } @@ -212,57 +214,57 @@ switch (ui_state) touch_sel = 8; action = SELECT; } - + //阅读页面控制区域设置 - if(x >= 10 && x <= 250 && y >= 900 && y <= 960 && reader->is_overlay_active()) + if(x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y && reader->is_overlay_active())//第三层 { touch_sel = 8; action = SELECT; } - else if(x >= 280 && x <= 480 && y >= 900 && y <= 960 && reader->is_overlay_active()) + else if(x >= g_area_array[9].start_x && x <= g_area_array[9].end_x && y >= g_area_array[9].start_y && y <= g_area_array[9].end_y && reader->is_overlay_active()) { touch_sel = 9; action = SELECT; } - else if(x >= 520 && x <= 750 && y >= 900 && y <= 960 && reader->is_overlay_active()) + else if(x >= g_area_array[10].start_x && x <= g_area_array[10].end_x && y >= g_area_array[10].start_y && y <= g_area_array[10].end_y && reader->is_overlay_active()) { touch_sel = 10; action = SELECT; } - else if(x >= 10 && x <= 150 && y >= 690 && y <= 750 && reader->is_overlay_active()) + else if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y && reader->is_overlay_active())//第一层 { touch_sel= 0; rt_kprintf("Touch middle SELECT %d\n",touch_sel); action = SELECT; } - else if(x >= 170 && x <= 570 && y >= 690 && y <= 750 && reader->is_overlay_active()) + else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y && reader->is_overlay_active()) { touch_sel= 1; rt_kprintf("Touch middle SELECT %d\n",touch_sel); action = SELECT; } - else if(x >= 610 && x <= 750 && y >= 690 && y <= 750 && reader->is_overlay_active()) + else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y && reader->is_overlay_active()) { touch_sel= 2; rt_kprintf("Touch middle SELECT %d\n",touch_sel); action = SELECT; } - else if(x >= 10 && x <= 140 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y && reader->is_overlay_active()) { touch_sel = 3;//跳转-5页 action = SELECT; } - else if(x >= 165 && x <=300 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y && reader->is_overlay_active()) { touch_sel = 4;//跳转-1页 action = SELECT; } - else if(x >= 480 && x <= 570 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y && reader->is_overlay_active()) { touch_sel = 6;//跳转+1页 action = SELECT; } - else if(x >= 620 && x <= 750 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[7].start_x && x <= g_area_array[7].end_x && y >= g_area_array[7].start_y && y <= g_area_array[7].end_y && reader->is_overlay_active()) { touch_sel = 7;//跳转5页 action = SELECT; @@ -270,19 +272,31 @@ switch (ui_state) break; case SELECTING_TABLE_CONTENTS: //目录界面 - if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + rt_kprintf("g_area_array[0].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[0].start_x ,g_area_array[0].end_x ,g_area_array[0].start_y ,g_area_array[0].end_y); + rt_kprintf("g_area_array[1].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[1].start_x ,g_area_array[1].end_x ,g_area_array[1].start_y ,g_area_array[1].end_y); + rt_kprintf("g_area_array[2].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[2].start_x ,g_area_array[2].end_x ,g_area_array[2].start_y ,g_area_array[2].end_y); + rt_kprintf("g_area_array[3].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[3].start_x ,g_area_array[3].end_x ,g_area_array[3].start_y ,g_area_array[3].end_y); + rt_kprintf("g_area_array[4].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[4].start_x ,g_area_array[4].end_x ,g_area_array[4].start_y ,g_area_array[4].end_y); + rt_kprintf("g_area_array[5].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[5].start_x ,g_area_array[5].end_x ,g_area_array[5].start_y ,g_area_array[5].end_y); + rt_kprintf("g_area_array[6].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[6].start_x ,g_area_array[6].end_x ,g_area_array[6].start_y ,g_area_array[6].end_y); + rt_kprintf("g_area_array[7].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[7].start_x ,g_area_array[7].end_x ,g_area_array[7].start_y ,g_area_array[7].end_y); + rt_kprintf("g_area_array[8].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[8].start_x ,g_area_array[8].end_x ,g_area_array[8].start_y ,g_area_array[8].end_y); + rt_kprintf("g_area_array[9].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[9].start_x ,g_area_array[9].end_x ,g_area_array[9].start_y ,g_area_array[9].end_y); + rt_kprintf("g_area_array[10].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[10].start_x ,g_area_array[10].end_x ,g_area_array[10].start_y ,g_area_array[10].end_y); + + if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y) { toc_bottom_mode = true; toc_bottom_idx = 0; action = SELECT; } - else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + else if(x >= g_area_array[7].start_x && x <= g_area_array[7].end_x && y >= g_area_array[7].start_y && y <= g_area_array[7].end_y) { toc_bottom_mode = true; toc_bottom_idx = 1; action = SELECT; } - else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + else if(x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y) { toc_bottom_mode = true; toc_bottom_idx = 2; @@ -292,27 +306,27 @@ switch (ui_state) { int clicked_toc_index = -1; - if(x >= 10 && x <= 750 && y >= 20 && y <= 170) + if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) { clicked_toc_index = 0; } - else if(x >= 10 && x <= 750 && y >= 180 && y <= 310) + else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) { clicked_toc_index = 1; } - else if(x >= 10 && x <= 750 && y >= 330 && y <= 450) + else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { clicked_toc_index = 2; } - else if(x >= 10 && x <= 750 && y >= 470 && y <= 590) + else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y) { clicked_toc_index = 3; } - else if(x >= 10 && x <= 750 && y >= 620 && y <= 750) + else if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y) { clicked_toc_index = 4; } - else if(x >= 10 && x <= 750 && y >= 770 && y <= 890) + else if(x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) { clicked_toc_index = 5; } @@ -346,54 +360,55 @@ switch (ui_state) break; case SETTINGS_PAGE: // 设置页面 // 设置页面每行左右箭头触控区域(与设置页布局一致) - if (x >= 100 && x <= 650 && y >= 160 && y <= 260) + if (x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { settings_selected_idx = SET_TOUCH; action = SELECT_BOX; rt_kprintf("select touch switch\n"); } - else if (x >= 100 && x <= 650 && y >= 300 && y <= 400) + else if (x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) { settings_selected_idx = SET_TIMEOUT; action = SELECT_BOX; rt_kprintf("select timeout switch\n"); } - else if (x >= 100 && x <= 650 && y >= 450 && y <= 540) + else if (x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y) { settings_selected_idx = SET_FULL_REFRESH; action = SELECT_BOX; rt_kprintf("select full refresh switch \n"); } - else if (x >= 100 && x <= 650 && y >= 830 && y <= 950) + else if (x >= g_area_array[9].start_x && x <= g_area_array[9].end_x && y >= g_area_array[9].start_y && y <= g_area_array[9].end_y) { settings_selected_idx = SET_CONFIRM; action = SELECT; - rt_kprintf("select touch switch\n"); + rt_kprintf("select confirm button\n"); } + - if(settings_selected_idx == SET_TOUCH && 0<=x && x<= 50 && 160<=y && y<=260) + if(settings_selected_idx == SET_TOUCH && g_area_array[0].start_x<=x && x<= g_area_array[0].end_x && g_area_array[0].start_y<=y && y<=g_area_array[0].end_y) { action = SELECT; } - else if(settings_selected_idx == SET_TOUCH && 700<=x && x<=750 && 160<=y && y<=260) + else if(settings_selected_idx == SET_TOUCH && g_area_array[1].start_x<=x && x<= g_area_array[1].end_x && g_area_array[1].start_y<=y && y<=g_area_array[1].end_y) { action = SELECT; } - else if(settings_selected_idx == SET_TIMEOUT && 0 <= x && x<=50 && 300 <= y && y<= 400) + else if(settings_selected_idx == SET_TIMEOUT && g_area_array[3].start_x<=x && x<= g_area_array[3].end_x && g_area_array[3].start_y<=y && y<=g_area_array[3].end_y) { action = PREV_OPTION; rt_kprintf("select timeout Reduce\n"); } - else if(settings_selected_idx == SET_TIMEOUT && 700<=x && x<=750 && 300<=y && y<= 400) + else if(settings_selected_idx == SET_TIMEOUT && g_area_array[4].start_x<=x && x<= g_area_array[4].end_x && g_area_array[4].start_y<=y && y<=g_area_array[4].end_y) { action = NEXT_OPTION; rt_kprintf("select timeout increase\n"); } - else if(settings_selected_idx == SET_FULL_REFRESH && 0 <= x && x<= 50 && 450 <= y && y<= 540) + else if(settings_selected_idx == SET_FULL_REFRESH && g_area_array[6].start_x<=x && x<= g_area_array[6].end_x && g_area_array[6].start_y<=y && y<=g_area_array[6].end_y) { action = PREV_OPTION; } - else if(settings_selected_idx == SET_FULL_REFRESH && 700 <= x && x<= 750 && 450 <= y && y<= 540) + else if(settings_selected_idx == SET_FULL_REFRESH && g_area_array[7].start_x<=x && x<= g_area_array[7].end_x && g_area_array[7].start_y<=y && y<=g_area_array[7].end_y) { action = NEXT_OPTION; } diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index 523b704..115e80a 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -3,6 +3,7 @@ #include "epub_screen.h" #include #include "type.h" +#include "UIRegionsManager.h" extern TouchControls *touch_controls; extern "C" @@ -112,6 +113,7 @@ int screen_get_main_selected_option() // 绘制主页面 static void render_main_page(Renderer *renderer) { + clear_areas(); // 清除之前的区域记录 renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); const char *title = "S I F L I"; @@ -133,12 +135,22 @@ static void render_main_page(Renderer *renderer) const char *lt = "<"; int lt_w = renderer->get_text_width(lt); int lt_h = renderer->get_line_height(); + int left_arrow_x = margin_side;//矩形的X轴起始坐标 + int left_arrow_y = y + margin_bottom;//矩形的Y轴起始坐标 + // 记录左箭头区域 + add_area(left_arrow_x, left_arrow_y, rect_w, rect_h); + renderer->draw_text(left_x + (rect_w - lt_w) / 2, y + (rect_h - lt_h) / 2, lt, false, true); // 右 ">" const char *gt = ">"; int gt_w = renderer->get_text_width(gt); int gt_h = renderer->get_line_height(); + int right_arrow_x = right_x ;//矩形的X轴起始坐标 + int right_arrow_y = y + margin_bottom;//矩形的Y轴起始坐标 + // 记录右箭头区域 + add_area(right_arrow_x, right_arrow_y, rect_w, rect_h); + renderer->draw_text(right_x + (rect_w - gt_w) / 2, y + (rect_h - gt_h) / 2, gt, false, true); // 中间选项文本 @@ -158,6 +170,11 @@ static void render_main_page(Renderer *renderer) } int opt_w = renderer->get_text_width(opt_text); int opt_h = renderer->get_line_height(); + int option_x = mid_x + (mid_w - opt_w) / 2 ; + int option_y = y + margin_bottom; + + // 记录选项区域 + add_area(option_x, option_y, opt_w, opt_h); renderer->draw_text(mid_x + (mid_w - opt_w) / 2, y + (rect_h - opt_h) / 2, opt_text, false, true); } //主界面处理 @@ -205,6 +222,7 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) // 设置页面 void render_settings_page(Renderer *renderer) { + clear_areas(); // 清除之前的区域记录 renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); // 标题 @@ -227,9 +245,17 @@ void render_settings_page(Renderer *renderer) int item_x = margin_lr + arrow_col_w; if (settings_selected_idx == SET_TOUCH) { - const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + const char *lt = "<"; + int lt_w = renderer->get_text_width(lt); + int touch_left_x = margin_lr; + int touch_left_y = y; + static_add_area(touch_left_x, touch_left_y, arrow_col_w, item_h,0); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); + const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + int touch_right_x = page_w - arrow_col_w + margin_lr; + int touch_right_y = y; + static_add_area(touch_right_x, touch_right_y, arrow_col_w, item_h,1); renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_TOUCH) @@ -250,6 +276,9 @@ void render_settings_page(Renderer *renderer) int tx = item_x + (item_w - t1_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t1_w > item_x + item_w - 4) tx = item_x + item_w - t1_w - 4; + int touch_switch_x = item_x; + int touch_switch_y = y ; + static_add_area(touch_switch_x, touch_switch_y, item_w, item_h,2); renderer->draw_text(tx, y + (item_h - lh) / 2, buf1, false, true); } y += item_h + gap; @@ -257,9 +286,18 @@ void render_settings_page(Renderer *renderer) // 2) 超时关机 if (settings_selected_idx == SET_TIMEOUT) { - const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + const char *lt = "<"; + int lt_w = renderer->get_text_width(lt); + int timeout_left_x = margin_lr; + int timeout_left_y = y; + static_add_area(timeout_left_x, timeout_left_y, arrow_col_w, item_h,3); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); - const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + + const char *gt = ">"; + int gt_w = renderer->get_text_width(gt); + int timeout_right_x = page_w - arrow_col_w + margin_lr; + int timeout_right_y = y; + static_add_area(timeout_right_x, timeout_right_y, arrow_col_w, item_h,4); renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_TIMEOUT) @@ -288,6 +326,9 @@ void render_settings_page(Renderer *renderer) int tx = item_x + (item_w - t2_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t2_w > item_x + item_w - 4) tx = item_x + item_w - t2_w - 4; + int timeout_setting_x = item_x; + int timeout_setting_y = y; + static_add_area(timeout_setting_x, timeout_setting_y, item_w, item_h,5); renderer->draw_text(tx, y + (item_h - lh) / 2, buf2, false, true); } y += item_h + gap; @@ -295,9 +336,18 @@ void render_settings_page(Renderer *renderer) // 3) 全刷周期 if (settings_selected_idx == SET_FULL_REFRESH) { - const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + const char *lt = "<"; + int lt_w = renderer->get_text_width(lt); + int full_refresh_left_x = margin_lr; + int full_refresh_left_y = y; + static_add_area(full_refresh_left_x, full_refresh_left_y, arrow_col_w, item_h,6); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); - const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + + const char *gt = ">"; + int gt_w = renderer->get_text_width(gt); + int full_refresh_right_x = page_w - arrow_col_w + margin_lr; + int full_refresh_right_y = y; + static_add_area(full_refresh_right_x, full_refresh_right_y, arrow_col_w, item_h,7); renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_FULL_REFRESH) @@ -319,6 +369,9 @@ void render_settings_page(Renderer *renderer) int tx = item_x + (item_w - t3_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t3_w > item_x + item_w - 4) tx = item_x + item_w - t3_w - 4; + int full_refresh_setting_x = item_x; + int full_refresh_setting_y = y; + static_add_area(full_refresh_setting_x, full_refresh_setting_y, item_w, item_h,8); renderer->draw_text(tx, y + (item_h - lh) / 2, buf3, false, true); } y += item_h + gap; @@ -339,6 +392,9 @@ void render_settings_page(Renderer *renderer) const char *confirm = "确认"; int c_w = renderer->get_text_width(confirm); int c_h = renderer->get_line_height(); + int confirm_button_x = confirm_x; + int confirm_button_y = confirm_y; + static_add_area(confirm_button_x, confirm_button_y, confirm_w, confirm_h,9); renderer->draw_text(confirm_x + (confirm_w - c_w) / 2, confirm_y + (confirm_h - c_h) / 2, confirm, false, true); } diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index fe453bb..2d3de64 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -13,6 +13,7 @@ #include "bf0_pm.h" #include "epd_driver.h" #include "type.h" +#include "UIRegionsManager.h" #undef LOG_TAG #undef DBG_LEVEL #define DBG_LEVEL DBG_LOG //DBG_INFO // @@ -83,6 +84,7 @@ typedef enum { } MainOption; void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw); +//阅读设置页面 void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -1175,7 +1177,7 @@ extern "C" int main() { // dump out the epub list state - //rt_pm_request(PM_SLEEP_MODE_IDLE); + rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); From 5e82316c67235546daadb706423dfb009faa818f Mon Sep 17 00:00:00 2001 From: smiling boy Date: Wed, 14 Jan 2026 10:57:46 +0800 Subject: [PATCH 13/27] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=92=8C=E4=B8=BB=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubList.cpp | 67 +-- epdiy-epub/src/SConscript | 2 +- .../boards/controls/SF32_TouchControls.cpp | 409 ++++-------------- epdiy-epub/src/epub_screen.cpp | 257 ++--------- epdiy-epub/src/epub_screen.h | 7 +- epdiy-epub/src/main.cpp | 140 ++---- 6 files changed, 178 insertions(+), 704 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp index c8ed77b..72e66ce 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp @@ -15,7 +15,7 @@ static const char *TAG = "PUBLIST"; #define PADDING 20 -#define EPUBS_PER_PAGE 4 +#define EPUBS_PER_PAGE 5 void EpubList::next() { @@ -138,10 +138,8 @@ void EpubList::render() ulog_d(TAG, "Rendering EPUB list"); // what page are we on? int current_page = state.selected_item / EPUBS_PER_PAGE; - // 计算单元格高度,并为底部按钮预留区域与底部间距 - const int bottom_area_height = 100; // 底部三按钮区域高度 - const int bottom_margin = 30; // 与屏幕底部的间距 - int cell_height = (renderer->get_page_height() - bottom_area_height - bottom_margin) / EPUBS_PER_PAGE; + // 计算单元格高度(不再预留底部区域) + int cell_height = (renderer->get_page_height()) / EPUBS_PER_PAGE; ulog_d(TAG, "Cell height is %d", cell_height); int start_index = current_page * EPUBS_PER_PAGE; int ypos = 0; @@ -241,61 +239,6 @@ void EpubList::render() } state.previous_selected_item = state.selected_item; state.previous_rendered_page = current_page; - // 绘制底部三按钮区域 - int page_w = renderer->get_page_width(); - int page_h = renderer->get_page_height(); - int area_y = page_h - bottom_area_height - bottom_margin; - // 背景 - renderer->fill_rect(0, area_y, page_w, bottom_area_height, 255); - // 三个等宽按钮 - int btn_gap = 10; - int btn_w = (page_w - btn_gap * 4) / 3; - int btn_h = 80; - int btn_y = area_y + (bottom_area_height - btn_h) / 2; - int btn_x0 = btn_gap; // 上一页 - int btn_x1 = btn_gap * 2 + btn_w; // 主页面 - int btn_x2 = btn_gap * 3 + btn_w * 2; // 下一页 - - // 高亮边框:当处于底部模式时,高亮当前选择 - auto draw_button = [&](int x, const char* text, bool selected) - { - if (selected) - { - // 加粗描边,表示选中 - for (int i = 0; i < 5; ++i) - { - renderer->draw_rect(x + i, btn_y + i, btn_w - 2 * i, btn_h - 2 * i, 0); - } - } - else - { - // 非选中用细描边 - renderer->draw_rect(x, btn_y, btn_w, btn_h, 80); - } - int t_w = renderer->get_text_width(text); - int t_h = renderer->get_line_height(); - int tx = x + (btn_w - t_w) / 2; - int ty = btn_y + (btn_h - t_h) / 2; - renderer->draw_text(tx, ty, text, false, true); - }; - - draw_button(btn_x0, "上一页", m_bottom_mode && m_bottom_idx == 0); - int start_up_page_x = btn_x0; - int start_up_page_y = btn_y + btn_gap * 2; - int end_up_page_x = btn_w; - int end_up_page_y = btn_h; - int start_page_x = btn_x0; - static_add_area(start_up_page_x, start_up_page_y, end_up_page_x, end_up_page_y, 4); - draw_button(btn_x1, "主页面", m_bottom_mode && m_bottom_idx == 1); - int start_main_page_x = btn_x1; - int start_main_page_y = btn_y + btn_gap *2; - int end_main_page_x = btn_w; - int end_main_page_y = btn_h; - static_add_area(start_main_page_x, start_main_page_y, end_main_page_x, end_main_page_y, 5); - draw_button(btn_x2, "下一页", m_bottom_mode && m_bottom_idx == 2); - int start_down_page_x = btn_x2; - int start_down_page_y = btn_y + btn_gap *2; - int end_down_page_x = btn_w; - int end_down_page_y = btn_h; - static_add_area(start_down_page_x, start_down_page_y, end_down_page_x, end_down_page_y, 6); + + // 移除书库页底部触控开关区域 } \ No newline at end of file diff --git a/epdiy-epub/src/SConscript b/epdiy-epub/src/SConscript index d1f0436..6c590b3 100644 --- a/epdiy-epub/src/SConscript +++ b/epdiy-epub/src/SConscript @@ -4,7 +4,7 @@ from building import * import rtconfig cwd = GetCurrentDir() -src = ['main.cpp','UIRegionsManager.cpp','epub_screen.cpp','epub_mem.c','epub_fonts.c'] +src = ['main.cpp','epub_screen.cpp','epub_mem.c','epub_fonts.c'] src = src + Glob('./assets/*.c') CPPPATH = [cwd] diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index fb4609c..bef4851 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -12,25 +12,7 @@ volatile int g_touch_last_settings_row = -1; volatile int g_touch_last_settings_dir = 0; -extern int settings_selected_idx; -extern AppUIState ui_state; -extern int book_index; -extern bool library_bottom_mode; -extern int library_bottom_idx; -extern int toc_index; -extern int toc_bottom_idx; -extern bool toc_bottom_mode;//控制目录页面中功能选项的开关 -static int last_clicked_toc_index = -1; // -1 表示没有目录项被选中 -// 添加一个变量来记录上次点击的书籍索引 -static int last_clicked_book_index = -1; // -1 表示没有书籍被选中 -static bool waiting_for_confirmation = false; // 是否正在等待确认 -extern int touch_sel; -extern EpubReader *reader; -static const int SWIPE_THRESHOLD = 100; // 最小滑动距离阈值 -static bool is_touch_started = false; // 全局或类成员变量 - -extern AreaRect g_area_array[]; rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { SF32_TouchControls *instance = static_cast (dev->user_data); @@ -109,314 +91,63 @@ rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) UIAction action = NONE; // LOG_I("TOUCH", "Received touch event %d,%d", x, y); // 主页面底部按键区域:左"<"、右">"、中间文本框 -switch (ui_state) -{ - case MAIN_PAGE://主页面 - if (x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) + int page_w = instance->renderer->get_page_width(); + int page_h = instance->renderer->get_page_height(); + int margin_side = 10; + int margin_bottom = 60; + int rect_w = 80; + int rect_h = 40; + int y_bottom = page_h - rect_h - margin_bottom; + int left_x = margin_side; + int right_x = page_w - rect_w - margin_side; + int mid_x = left_x + rect_w + margin_side; + int mid_w = right_x - margin_side - mid_x; + + if (x >= left_x && x <= left_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) { rt_kprintf("Touch left < \n"); - action = UP; // 对应 KEY3 功能 + action = UP; } - else if (x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) + + else if (x >= right_x && x <= right_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) { - action = DOWN; // 对应 KEY1 功能 + action = DOWN; rt_kprintf("Touch right > \n"); } - else if (x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) - { - action = SELECT; // 对应 KEY2 功能 - rt_kprintf("Touch middle SELECT \n"); - } - break; - case SELECTING_EPUB://书库页面 - // 检查是否点击了功能控制按钮 - if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y) - { - library_bottom_mode = true; - library_bottom_idx = 0; - action = SELECT; - } - else if(x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) - { - library_bottom_mode = true; - library_bottom_idx = 1; - action = SELECT; - } - else if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y) - { - library_bottom_mode = true; - library_bottom_idx = 2; - action = SELECT; - } - else - { - // 处理书籍选择区域 - int clicked_book_index = -1; - - if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) - { - clicked_book_index = 0; - } - else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) - { - clicked_book_index = 1; - } - else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) - { - clicked_book_index = 2; - } - else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y) - { - clicked_book_index = 3; - } - - // 如果点击了书籍区域 - if(clicked_book_index != -1) - { - // 判断是第一次点击还是第二次点击 - if(waiting_for_confirmation && last_clicked_book_index == clicked_book_index) - { - // 第二次点击:执行打开操作 - book_index = clicked_book_index; - library_bottom_mode = false; - rt_kprintf("Open book%d %d\n", book_index, book_index); - action = SELECT; - - // 重置状态 - waiting_for_confirmation = false; - last_clicked_book_index = -1; - } - else - { - // 第一次点击:选择书籍并等待确认 - book_index = clicked_book_index; - last_clicked_book_index = clicked_book_index; - waiting_for_confirmation = true; - action = SELECT_BOX; - rt_kprintf("Select book%d for confirmation, waiting for second click\n", book_index); - } - } - } - break; - case READING_EPUB: //阅读界面 - //翻页操作 - if(x >= 10 && x <= 200 && y >=10 && y <= 1010 && reader->is_overlay_active() == false) - { + + // 设置页面每行左右箭头触控区域(与设置页布局一致) + if (action == NONE) + { + int page_w2 = instance->renderer->get_page_width(); + int margin_lr2 = 6; + int item_h2 = 100; + int gap2 = 54; + int arrow_col_w2 = 40; + int lh2 = instance->renderer->get_line_height(); + int y_start2 = 40 + lh2 + 20; + g_touch_last_settings_row = -1; + g_touch_last_settings_dir = 0; + for (int row = 0; row < 3; ++row) + { + int ry = y_start2 + row * (item_h2 + gap2); + int left_ax = margin_lr2; + int right_ax = page_w2 - margin_lr2 - arrow_col_w2; + if (x >= left_ax && x <= left_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) + { action = UP; - } - else if(x >= 550 && x <= 750 && y >=10 && y <= 1010 && reader->is_overlay_active() == false) - { + g_touch_last_settings_row = row; + g_touch_last_settings_dir = -1; // 左=减 + break; + } + if (x >= right_ax && x <= right_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) + { action = DOWN; + g_touch_last_settings_row = row; + g_touch_last_settings_dir = +1; // 右=加 + break; + } } - //点击正文,推出阅读设置 - if(x >= 10 && x <= 750 && y >=10 && y <= 630 && reader->is_overlay_active()) - { - touch_sel = 8; - action = SELECT; - } - - //阅读页面控制区域设置 - if(x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y && reader->is_overlay_active())//第三层 - { - touch_sel = 8; - action = SELECT; - } - else if(x >= g_area_array[9].start_x && x <= g_area_array[9].end_x && y >= g_area_array[9].start_y && y <= g_area_array[9].end_y && reader->is_overlay_active()) - { - touch_sel = 9; - action = SELECT; - } - else if(x >= g_area_array[10].start_x && x <= g_area_array[10].end_x && y >= g_area_array[10].start_y && y <= g_area_array[10].end_y && reader->is_overlay_active()) - { - touch_sel = 10; - action = SELECT; - } - else if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y && reader->is_overlay_active())//第一层 - { - touch_sel= 0; - rt_kprintf("Touch middle SELECT %d\n",touch_sel); - action = SELECT; - } - else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y && reader->is_overlay_active()) - { - touch_sel= 1; - rt_kprintf("Touch middle SELECT %d\n",touch_sel); - action = SELECT; - } - else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y && reader->is_overlay_active()) - { - touch_sel= 2; - rt_kprintf("Touch middle SELECT %d\n",touch_sel); - action = SELECT; - } - else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y && reader->is_overlay_active()) - { - touch_sel = 3;//跳转-5页 - action = SELECT; - } - else if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y && reader->is_overlay_active()) - { - touch_sel = 4;//跳转-1页 - action = SELECT; - } - else if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y && reader->is_overlay_active()) - { - touch_sel = 6;//跳转+1页 - action = SELECT; - } - else if(x >= g_area_array[7].start_x && x <= g_area_array[7].end_x && y >= g_area_array[7].start_y && y <= g_area_array[7].end_y && reader->is_overlay_active()) - { - touch_sel = 7;//跳转5页 - action = SELECT; - } - - break; - case SELECTING_TABLE_CONTENTS: //目录界面 - rt_kprintf("g_area_array[0].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[0].start_x ,g_area_array[0].end_x ,g_area_array[0].start_y ,g_area_array[0].end_y); - rt_kprintf("g_area_array[1].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[1].start_x ,g_area_array[1].end_x ,g_area_array[1].start_y ,g_area_array[1].end_y); - rt_kprintf("g_area_array[2].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[2].start_x ,g_area_array[2].end_x ,g_area_array[2].start_y ,g_area_array[2].end_y); - rt_kprintf("g_area_array[3].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[3].start_x ,g_area_array[3].end_x ,g_area_array[3].start_y ,g_area_array[3].end_y); - rt_kprintf("g_area_array[4].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[4].start_x ,g_area_array[4].end_x ,g_area_array[4].start_y ,g_area_array[4].end_y); - rt_kprintf("g_area_array[5].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[5].start_x ,g_area_array[5].end_x ,g_area_array[5].start_y ,g_area_array[5].end_y); - rt_kprintf("g_area_array[6].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[6].start_x ,g_area_array[6].end_x ,g_area_array[6].start_y ,g_area_array[6].end_y); - rt_kprintf("g_area_array[7].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[7].start_x ,g_area_array[7].end_x ,g_area_array[7].start_y ,g_area_array[7].end_y); - rt_kprintf("g_area_array[8].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[8].start_x ,g_area_array[8].end_x ,g_area_array[8].start_y ,g_area_array[8].end_y); - rt_kprintf("g_area_array[9].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[9].start_x ,g_area_array[9].end_x ,g_area_array[9].start_y ,g_area_array[9].end_y); - rt_kprintf("g_area_array[10].start_x %d end_x %d start_y %d end_y %d\n",g_area_array[10].start_x ,g_area_array[10].end_x ,g_area_array[10].start_y ,g_area_array[10].end_y); - - if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y) - { - toc_bottom_mode = true; - toc_bottom_idx = 0; - action = SELECT; - } - else if(x >= g_area_array[7].start_x && x <= g_area_array[7].end_x && y >= g_area_array[7].start_y && y <= g_area_array[7].end_y) - { - toc_bottom_mode = true; - toc_bottom_idx = 1; - action = SELECT; - } - else if(x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y) - { - toc_bottom_mode = true; - toc_bottom_idx = 2; - action = SELECT; - } - else// 目录项选择区域 - { - int clicked_toc_index = -1; - - if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) - { - clicked_toc_index = 0; - } - else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) - { - clicked_toc_index = 1; - } - else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) - { - clicked_toc_index = 2; - } - else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y) - { - clicked_toc_index = 3; - } - else if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y) - { - clicked_toc_index = 4; - } - else if(x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) - { - clicked_toc_index = 5; - } - // 如果点击了目录项区域 - if(clicked_toc_index != -1) - { - // 判断是第一次点击还是第二次点击 - if(waiting_for_confirmation && last_clicked_toc_index == clicked_toc_index) - { - // 第二次点击:执行打开操作 - toc_index = clicked_toc_index; - library_bottom_mode = false; - rt_kprintf("Open book%d %d\n", toc_index, toc_index); - action = SELECT; - - // 重置状态 - waiting_for_confirmation = false; - last_clicked_toc_index = -1; - } - else - { - // 第一次点击:选择目录项并等待确认 - toc_index = clicked_toc_index; - last_clicked_toc_index = clicked_toc_index; - waiting_for_confirmation = true; - action = SELECT_BOX; - } - } - } - - break; - case SETTINGS_PAGE: // 设置页面 - // 设置页面每行左右箭头触控区域(与设置页布局一致) - if (x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) - { - settings_selected_idx = SET_TOUCH; - action = SELECT_BOX; - rt_kprintf("select touch switch\n"); - } - else if (x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) - { - settings_selected_idx = SET_TIMEOUT; - action = SELECT_BOX; - rt_kprintf("select timeout switch\n"); - } - else if (x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y) - { - settings_selected_idx = SET_FULL_REFRESH; - action = SELECT_BOX; - rt_kprintf("select full refresh switch \n"); - } - else if (x >= g_area_array[9].start_x && x <= g_area_array[9].end_x && y >= g_area_array[9].start_y && y <= g_area_array[9].end_y) - { - settings_selected_idx = SET_CONFIRM; - action = SELECT; - rt_kprintf("select confirm button\n"); - } - - - if(settings_selected_idx == SET_TOUCH && g_area_array[0].start_x<=x && x<= g_area_array[0].end_x && g_area_array[0].start_y<=y && y<=g_area_array[0].end_y) - { - action = SELECT; - } - else if(settings_selected_idx == SET_TOUCH && g_area_array[1].start_x<=x && x<= g_area_array[1].end_x && g_area_array[1].start_y<=y && y<=g_area_array[1].end_y) - { - action = SELECT; - } - else if(settings_selected_idx == SET_TIMEOUT && g_area_array[3].start_x<=x && x<= g_area_array[3].end_x && g_area_array[3].start_y<=y && y<=g_area_array[3].end_y) - { - action = PREV_OPTION; - rt_kprintf("select timeout Reduce\n"); - } - else if(settings_selected_idx == SET_TIMEOUT && g_area_array[4].start_x<=x && x<= g_area_array[4].end_x && g_area_array[4].start_y<=y && y<=g_area_array[4].end_y) - { - action = NEXT_OPTION; - rt_kprintf("select timeout increase\n"); - } - else if(settings_selected_idx == SET_FULL_REFRESH && g_area_array[6].start_x<=x && x<= g_area_array[6].end_x && g_area_array[6].start_y<=y && y<=g_area_array[6].end_y) - { - action = PREV_OPTION; - } - else if(settings_selected_idx == SET_FULL_REFRESH && g_area_array[7].start_x<=x && x<= g_area_array[7].end_x && g_area_array[7].start_y<=y && y<=g_area_array[7].end_y) - { - action = NEXT_OPTION; - } - break; - -} - - + } instance->last_action = action; if (action != NONE) @@ -471,5 +202,49 @@ void SF32_TouchControls::powerOnTouch() } void SF32_TouchControls::renderPressedState(Renderer *renderer, UIAction action, bool state) { + renderer->set_margin_top(0); + switch (action) + { + case DOWN: + { + if (state) + { + renderer->fill_triangle(80, 20, 75, 6, 85, 6, 0); + } + else + { + renderer->fill_triangle(81, 19, 76, 7, 86, 7, 255); + } + //renderer->flush_area(76, 6, 10, 15); + break; + } + case UP: + { + if (state) + { + renderer->fill_triangle(220, 6, 220 - 5, 20, 220 + 5, 20, 0); + } + else + { + renderer->fill_triangle(221, 7, 221 - 5, 19, 221 + 5, 19, 255); + } + //renderer->flush_area(195, 225, 10, 15); + } + break; + case SELECT: + { + uint16_t x_circle = (ui_button_width * 2 + 60) + (ui_button_width / 2) + 9; + renderer->fill_circle(x_circle, 15, 5, 0); + //renderer->flush_area(x_circle - 3, 12, 6, 6); + // TODO - this causes a stack overflow when select is picked + // renderPressedState(renderer, last_action, false); + } + break; + case LAST_INTERACTION: + case NONE: + break; + default: + break; + } renderer->set_margin_top(35); } \ No newline at end of file diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index 115e80a..ede9f23 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -1,108 +1,63 @@ - -#include "EpubList/EpubList.h" #include "epub_screen.h" #include -#include "type.h" -#include "UIRegionsManager.h" -extern TouchControls *touch_controls; -extern "C" -{ - extern void set_part_disp_times(int val); -} -// 最近一次真实打开并阅读的书本索引(由 main.cpp 维护) -extern int g_last_read_index; +extern TouchControls *touch_controls; // 主页面选项 typedef enum { - OPTION_OPEN_LIBRARY = 0, // 打开书库 - OPTION_CONTINUE_READING, // 继续阅读 - OPTION_ENTER_SETTINGS // 进入设置 + OPTION_OPEN_LIBRARY = 0, + OPTION_CONTINUE_READING, + OPTION_ENTER_SETTINGS } MainOption; static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” -// 全刷周期选项:5、10、20、每次(0) -static const int kFullRefreshOptions[] = {5, 10, 20, 0}; -static const int kFullRefreshOptionsCount = sizeof(kFullRefreshOptions) / sizeof(kFullRefreshOptions[0]); -static int full_refresh_idx = 1; // 默认10次 - -// 获取当前全刷周期值 -int screen_get_full_refresh_period() -{ - return kFullRefreshOptions[full_refresh_idx]; -} - -// 切换全刷周期(循环) -void screen_cycle_full_refresh_period(bool refresh) -{ - if(refresh) - { - full_refresh_idx = (full_refresh_idx + 1) % kFullRefreshOptionsCount; // ?% 4 - - } - else - { - full_refresh_idx = (full_refresh_idx - 1) % kFullRefreshOptionsCount; // ?% 4 - - } -} +static int full_refresh_period = 10; // 全刷周期次数,仅用于设置页显示 -// 设置全刷周期索引 -void screen_set_full_refresh_idx(int idx) -{ - if (idx >= 0 && idx < kFullRefreshOptionsCount) full_refresh_idx = idx; -} - -// 获取当前全刷周期索引 -int screen_get_full_refresh_idx() -{ - return full_refresh_idx; -} +// 设置页列表项 +typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; +static int settings_selected_idx = 0; - -int settings_selected_idx = 0; - -// 超时关机:5/10/30分钟、1小时、不关机(0) -static const int kTimeoutOptions[] = {5, 10, 30, 60, 0}; // 单位:分钟,0为不关机 +// 超时关机:1/3/5/7/10/不关机(0) +static const int kTimeoutOptions[] = {1, 3, 5, 7, 10, 0}; static const int kTimeoutOptionsCount = sizeof(kTimeoutOptions) / sizeof(kTimeoutOptions[0]); -static int timeout_shutdown_minutes = 30; // 默认30分钟 -static int timeout_idx = -1; // +static int timeout_shutdown_hours = 5; // 运行时关机超时(小时),0 表示不关机 +static int timeout_idx = -1; // 指向 kTimeoutOptions 的索引 -static int find_timeout_idx(int minutes) +static int find_timeout_idx(int hours) { for (int i = 0; i < kTimeoutOptionsCount; ++i) { - if (kTimeoutOptions[i] == minutes) return i; + if (kTimeoutOptions[i] == hours) return i; } - return 2; // 默认索引:30分钟 + return 2; // 默认索引:5小时 } static void adjust_timeout(bool increase) { - if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_minutes); + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); if (increase) { timeout_idx = (timeout_idx + 1) % kTimeoutOptionsCount; } else { - timeout_idx = (timeout_idx - 1) % kTimeoutOptionsCount; + timeout_idx = (timeout_idx - 1 + kTimeoutOptionsCount) % kTimeoutOptionsCount; } - timeout_shutdown_minutes = kTimeoutOptions[timeout_idx]; + timeout_shutdown_hours = kTimeoutOptions[timeout_idx]; } -void screen_init(int default_timeout_minutes) +void screen_init(int default_timeout_hours) { - timeout_shutdown_minutes = default_timeout_minutes; - timeout_idx = find_timeout_idx(timeout_shutdown_minutes); + timeout_shutdown_hours = default_timeout_hours; + timeout_idx = find_timeout_idx(timeout_shutdown_hours); } -int screen_get_timeout_shutdown_minutes() +int screen_get_timeout_shutdown_hours() { - if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_minutes); - return timeout_shutdown_minutes; + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); + return timeout_shutdown_hours; } int screen_get_main_selected_option() @@ -110,10 +65,9 @@ int screen_get_main_selected_option() return (int)main_option; // 0: 打开书库, 1: 继续阅读, 2: 进入设置 } -// 绘制主页面 +// 主页面 static void render_main_page(Renderer *renderer) { - clear_areas(); // 清除之前的区域记录 renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); const char *title = "S I F L I"; @@ -135,22 +89,12 @@ static void render_main_page(Renderer *renderer) const char *lt = "<"; int lt_w = renderer->get_text_width(lt); int lt_h = renderer->get_line_height(); - int left_arrow_x = margin_side;//矩形的X轴起始坐标 - int left_arrow_y = y + margin_bottom;//矩形的Y轴起始坐标 - // 记录左箭头区域 - add_area(left_arrow_x, left_arrow_y, rect_w, rect_h); - renderer->draw_text(left_x + (rect_w - lt_w) / 2, y + (rect_h - lt_h) / 2, lt, false, true); // 右 ">" const char *gt = ">"; int gt_w = renderer->get_text_width(gt); int gt_h = renderer->get_line_height(); - int right_arrow_x = right_x ;//矩形的X轴起始坐标 - int right_arrow_y = y + margin_bottom;//矩形的Y轴起始坐标 - // 记录右箭头区域 - add_area(right_arrow_x, right_arrow_y, rect_w, rect_h); - renderer->draw_text(right_x + (rect_w - gt_w) / 2, y + (rect_h - gt_h) / 2, gt, false, true); // 中间选项文本 @@ -158,31 +102,22 @@ static void render_main_page(Renderer *renderer) int mid_w = right_x - margin_side - mid_x; const char *opt_text = NULL; - extern EpubListState epub_list_state; - bool has_continue_reading = (epub_list_state.num_epubs > 0 && g_last_read_index >= 0 && g_last_read_index < epub_list_state.num_epubs); switch (main_option) { case OPTION_OPEN_LIBRARY: opt_text = "打开书库"; break; - case OPTION_CONTINUE_READING: - opt_text = has_continue_reading ? "继续阅读" : "无阅读记录"; - break; + case OPTION_CONTINUE_READING: opt_text = "继续阅读"; break; case OPTION_ENTER_SETTINGS: opt_text = "进入设置"; break; } int opt_w = renderer->get_text_width(opt_text); int opt_h = renderer->get_line_height(); - int option_x = mid_x + (mid_w - opt_w) / 2 ; - int option_y = y + margin_bottom; - - // 记录选项区域 - add_area(option_x, option_y, opt_w, opt_h); renderer->draw_text(mid_x + (mid_w - opt_w) / 2, y + (rect_h - opt_h) / 2, opt_text, false, true); } -//主界面处理 + void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) { if (needs_redraw || action == NONE) { - render_main_page(renderer);//绘制主界面 + render_main_page(renderer); return; } switch (action) @@ -220,9 +155,8 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) } // 设置页面 -void render_settings_page(Renderer *renderer) +static void render_settings_page(Renderer *renderer) { - clear_areas(); // 清除之前的区域记录 renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); // 标题 @@ -243,25 +177,15 @@ void render_settings_page(Renderer *renderer) // 1) 触控开关 int item_w = page_w - margin_lr * 2 - arrow_col_w * 2; // 为左右箭头列留边 int item_x = margin_lr + arrow_col_w; - if (settings_selected_idx == SET_TOUCH) { - const char *lt = "<"; - int lt_w = renderer->get_text_width(lt); - int touch_left_x = margin_lr; - int touch_left_y = y; - static_add_area(touch_left_x, touch_left_y, arrow_col_w, item_h,0); + const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); - const char *gt = ">"; int gt_w = renderer->get_text_width(gt); - int touch_right_x = page_w - arrow_col_w + margin_lr; - int touch_right_y = y; - static_add_area(touch_right_x, touch_right_y, arrow_col_w, item_h,1); renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_TOUCH) { - // 选中强化:多重描边,提高可见度 - for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { @@ -276,102 +200,65 @@ void render_settings_page(Renderer *renderer) int tx = item_x + (item_w - t1_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t1_w > item_x + item_w - 4) tx = item_x + item_w - t1_w - 4; - int touch_switch_x = item_x; - int touch_switch_y = y ; - static_add_area(touch_switch_x, touch_switch_y, item_w, item_h,2); renderer->draw_text(tx, y + (item_h - lh) / 2, buf1, false, true); } y += item_h + gap; // 2) 超时关机 - if (settings_selected_idx == SET_TIMEOUT) { - const char *lt = "<"; - int lt_w = renderer->get_text_width(lt); - int timeout_left_x = margin_lr; - int timeout_left_y = y; - static_add_area(timeout_left_x, timeout_left_y, arrow_col_w, item_h,3); + const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); - - const char *gt = ">"; - int gt_w = renderer->get_text_width(gt); - int timeout_right_x = page_w - arrow_col_w + margin_lr; - int timeout_right_y = y; - static_add_area(timeout_right_x, timeout_right_y, arrow_col_w, item_h,4); + const char *gt = ">"; int gt_w = renderer->get_text_width(gt); renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_TIMEOUT) { - for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { renderer->draw_rect(item_x, y, item_w, item_h, 0); } char buf2[64]; - if (timeout_shutdown_minutes == 0) + if (timeout_shutdown_hours == 0) { rt_snprintf(buf2, sizeof(buf2), "超时关机:不关机"); } - else if (timeout_shutdown_minutes < 60) - { - rt_snprintf(buf2, sizeof(buf2), "超时关机:%d分钟", timeout_shutdown_minutes); - } else { - rt_snprintf(buf2, sizeof(buf2), "超时关机:%d小时", timeout_shutdown_minutes / 60); + rt_snprintf(buf2, sizeof(buf2), "超时关机:%d 小时", timeout_shutdown_hours); } { int t2_w = renderer->get_text_width(buf2); int tx = item_x + (item_w - t2_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t2_w > item_x + item_w - 4) tx = item_x + item_w - t2_w - 4; - int timeout_setting_x = item_x; - int timeout_setting_y = y; - static_add_area(timeout_setting_x, timeout_setting_y, item_w, item_h,5); renderer->draw_text(tx, y + (item_h - lh) / 2, buf2, false, true); } y += item_h + gap; // 3) 全刷周期 - if (settings_selected_idx == SET_FULL_REFRESH) { - const char *lt = "<"; - int lt_w = renderer->get_text_width(lt); - int full_refresh_left_x = margin_lr; - int full_refresh_left_y = y; - static_add_area(full_refresh_left_x, full_refresh_left_y, arrow_col_w, item_h,6); + const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); - - const char *gt = ">"; - int gt_w = renderer->get_text_width(gt); - int full_refresh_right_x = page_w - arrow_col_w + margin_lr; - int full_refresh_right_y = y; - static_add_area(full_refresh_right_x, full_refresh_right_y, arrow_col_w, item_h,7); + const char *gt = ">"; int gt_w = renderer->get_text_width(gt); renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_FULL_REFRESH) { - for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { renderer->draw_rect(item_x, y, item_w, item_h, 0); } char buf3[64]; - int fr_val = screen_get_full_refresh_period(); - if (fr_val == 0) - rt_snprintf(buf3, sizeof(buf3), "全刷周期:每次"); - else - rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", fr_val); + rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", full_refresh_period); { int t3_w = renderer->get_text_width(buf3); int tx = item_x + (item_w - t3_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t3_w > item_x + item_w - 4) tx = item_x + item_w - t3_w - 4; - int full_refresh_setting_x = item_x; - int full_refresh_setting_y = y; - static_add_area(full_refresh_setting_x, full_refresh_setting_y, item_w, item_h,8); renderer->draw_text(tx, y + (item_h - lh) / 2, buf3, false, true); } y += item_h + gap; @@ -383,7 +270,7 @@ void render_settings_page(Renderer *renderer) int confirm_y = page_h - confirm_h - 60; // 距离底部位置 if (settings_selected_idx == SET_CONFIRM) { - for (int i = 0; i < 5; ++i) renderer->draw_rect(confirm_x + i, confirm_y + i, confirm_w - 2 * i, confirm_h - 2 * i, 0); + for (int i = 0; i < 2; ++i) renderer->draw_rect(confirm_x + i, confirm_y + i, confirm_w - 2 * i, confirm_h - 2 * i, 0); } else { @@ -392,13 +279,9 @@ void render_settings_page(Renderer *renderer) const char *confirm = "确认"; int c_w = renderer->get_text_width(confirm); int c_h = renderer->get_line_height(); - int confirm_button_x = confirm_x; - int confirm_button_y = confirm_y; - static_add_area(confirm_button_x, confirm_button_y, confirm_w, confirm_h,9); renderer->draw_text(confirm_x + (confirm_w - c_w) / 2, confirm_y + (confirm_h - c_h) / 2, confirm, false, true); } -// 设置页面交互处理 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) { // 读取并清除一次性的触控箭头标记,避免后续硬件按键误用 @@ -441,56 +324,6 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) render_settings_page(renderer); } break; - case SELECT_BOX: - if(settings_selected_idx == SET_TOUCH) - { - render_settings_page(renderer); - } - else if(settings_selected_idx == SET_TIMEOUT) - { - render_settings_page(renderer); - } - else if(settings_selected_idx == SET_FULL_REFRESH) - { - render_settings_page(renderer); - } - else if(settings_selected_idx == SET_CONFIRM) - { - render_settings_page(renderer); - return true; - } - break; - case PREV_OPTION: - if (settings_selected_idx == SET_TIMEOUT) - { - // SELECT 在超时关机项上为加操作(循环) - adjust_timeout(false); - render_settings_page(renderer); - } - else if(settings_selected_idx == SET_FULL_REFRESH) - { - - screen_cycle_full_refresh_period(false); - set_part_disp_times(screen_get_full_refresh_period()); - render_settings_page(renderer); - } - - break; - case NEXT_OPTION: - if (settings_selected_idx == SET_TIMEOUT) - { - // SELECT 在超时关机项上为加操作(循环) - adjust_timeout(true); - render_settings_page(renderer); - } - else if(settings_selected_idx == SET_FULL_REFRESH) - { - - screen_cycle_full_refresh_period(true); - set_part_disp_times(screen_get_full_refresh_period()); - render_settings_page(renderer); - } - break; case SELECT: if (settings_selected_idx == SET_TOUCH) { @@ -511,14 +344,6 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) render_settings_page(renderer); break; } - if (settings_selected_idx == SET_FULL_REFRESH) - { - // SELECT 在全刷周期项上为加操作(循环) - screen_cycle_full_refresh_period(true); - set_part_disp_times(screen_get_full_refresh_period()); - render_settings_page(renderer); - break; - } if (settings_selected_idx == SET_CONFIRM) { // 由上层切回主页面 diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h index 148141b..c97c3c4 100644 --- a/epdiy-epub/src/epub_screen.h +++ b/epdiy-epub/src/epub_screen.h @@ -11,7 +11,7 @@ void screen_init(int default_timeout_hours); // 获取当前关机超时设置(小时;0 表示不关机) -int screen_get_timeout_shutdown_minutes(); +int screen_get_timeout_shutdown_hours(); // 获取当前主页面选中的选项(0: 打开书库, 1: 继续阅读, 2: 进入设置) int screen_get_main_selected_option(); @@ -21,7 +21,4 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw); // 设置页面交互与渲染;返回 true 表示确认并退出到主页面 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw); -// 切换全刷周期(循环) -void screen_cycle_full_refresh_period(bool refresh); -// 获取当前全刷周期值 -int screen_get_full_refresh_period(); \ No newline at end of file + diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 2d3de64..e493331 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -36,10 +36,25 @@ extern "C" const char *TAG = "main"; - +typedef enum +{ + MAIN_PAGE, // 新主页面 + SELECTING_EPUB, + SELECTING_TABLE_CONTENTS, + READING_EPUB, + SETTINGS_PAGE // 通用功能设置页面 +} UIState; +typedef enum +{ + MAIN_MENU, + WELCOME_PAGE, + LOW_POWER_PAGE, + CHARGING_PAGE +} UIState2; // 默认显示新主页面,而非书库页面 -AppUIState ui_state = MAIN_PAGE; +UIState ui_state = MAIN_PAGE; +UIState2 lowpower_ui_state = MAIN_MENU; // the state data for the epub list and reader EpubListState epub_list_state; // the state data for the epub index list @@ -82,9 +97,7 @@ typedef enum { OPTION_CONTINUE_READING, // 继续阅读 -> 打印 2 OPTION_ENTER_SETTINGS // 进入设置 -> 打印 3 } MainOption; -void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw); -//阅读设置页面 void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -525,75 +538,9 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } break; case DOWN: - if (library_bottom_mode) - { - // 底部模式下:DOWN 向右移动;若已在最右(下一页),则返回当前页的列表第一项 - if (library_bottom_idx < 2) - { - library_bottom_idx++; - } - else - { - int per_page = 4; - int start_idx = (epub_list_state.selected_item / per_page) * per_page; - int end_idx = start_idx + per_page - 1; - if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; - library_bottom_mode = false; - epub_list_state.selected_item = start_idx; - } - } - else - { - int per_page = 4; - int start_idx = (epub_list_state.selected_item / per_page) * per_page; - int end_idx = start_idx + per_page - 1; - if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; - // 若处于当前页最后一个条目,DOWN 切换到底部按钮模式 - if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == end_idx) - { - library_bottom_mode = true; - library_bottom_idx = 0; // 上一页 - } - else - { - epub_list->next(); - } - } - break; - case SELECT_BOX: - // 如果在底部模式,先退出底部模式 - if (library_bottom_mode) { - library_bottom_mode = false; - } - current_page = epub_list_state.selected_item / 4; // 当前页面 - start_index = current_page * 4; // 当前页起始索引 - // 计算全局索引 = 页起始索引 + 页内偏移 - global_index = start_index + book_index; - // 边界检查 - if (global_index < epub_list_state.num_epubs) - { - - if(book_index == 0) - { - epub_list->switch_book(global_index); - } - else if(book_index == 1) - { - epub_list->switch_book(global_index); - } - else if(book_index == 2) - { - epub_list->switch_book(global_index); - } - else if(book_index == 3) - { - epub_list->switch_book(global_index); - } - } + epub_list->next(); break; case SELECT: - if (library_bottom_mode) - { int per_page = 4; int current_page = epub_list_state.selected_item / per_page; int max_page = (epub_list_state.num_epubs == 0) ? 0 : ( (epub_list_state.num_epubs - 1) / per_page ); @@ -636,7 +583,6 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) epub_list->set_needs_redraw(); } } - } else { // 进入目录选择页面 @@ -738,31 +684,10 @@ void handleUserInteraction(Renderer *renderer, UIAction ui_action, bool needs_re { case MAIN_PAGE: // 新主页面 handleMainPage(renderer, ui_action, needs_redraw); - if (ui_action == SELECT && screen_get_main_selected_option() == 2) //切换到设置页面 + if (ui_action == SELECT && screen_get_main_selected_option() == 2) { ui_state = SETTINGS_PAGE; - (void)handleSettingsPage(renderer, NONE, true); - } - else if (ui_action == SELECT && screen_get_main_selected_option() == 1) //继续阅读 - { - // 判断是否有继续阅读记录 - if (!(g_last_read_index >= 0 && g_last_read_index < epub_list_state.num_epubs)) { - return; // 无记录,忽略 - } - // 有记录,恢复阅读 - if (reader) { delete reader; reader = nullptr; } - int last_idx = g_last_read_index; - EpubListItem &last_item = epub_list_state.epub_list[last_idx]; - reader = new EpubReader(last_item, renderer); - reader->set_state_section(last_item.current_section); - reader->load(); - ui_state = READING_EPUB; - handleEpub(renderer, NONE); - } - else if (ui_action == SELECT && screen_get_main_selected_option() == 0) //切换到书库页面 - { - ui_state = SELECTING_EPUB; - handleEpubList(renderer, NONE, true); + (void)handleSettingsPage(renderer, NONE, true); } break; case READING_EPUB: //阅读界面 @@ -831,13 +756,21 @@ void back_to_main_page() } bool hydrate_success = renderer->hydrate(); - renderer->reset(); - renderer->set_margin_top(35); - renderer->set_margin_left(10); - renderer->set_margin_right(10); - // 返回新的主页面,不再默认进入书库页面 - ui_state = MAIN_PAGE; - handleUserInteraction(renderer, NONE, true); + renderer->reset(); + renderer->set_margin_top(35); + renderer->set_margin_left(10); + renderer->set_margin_right(10); + // 返回新的主页面,不再默认进入书库页面 + ui_state = MAIN_PAGE; + handleUserInteraction(renderer, NONE, true); + + if (battery) + { + draw_charge_status(renderer, battery); + draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); + } + touch_controls->render(renderer); + renderer->flush_display(); if (battery) { @@ -1045,7 +978,8 @@ void main_task(void *param) // 初始化屏幕模块默认关机超时 screen_init(TIMEOUT_SHUTDOWN_TIME); - while ((rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 * TIMEOUT_SHUTDOWN_TIME)) // 5小时 + while ((screen_get_timeout_shutdown_hours() == 0) || + (rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 * screen_get_timeout_shutdown_hours())) // 按设置的小时数无操作自动关机;0为不关机 { // 检查是否超过设置分钟无操作,如果是在欢迎页面、充电页面或低电量页面则不跳转 From ae9a1f7255bd72f5386d914dbc207a17c4df2852 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Wed, 14 Jan 2026 16:28:44 +0800 Subject: [PATCH 14/27] =?UTF-8?q?1.=E5=AE=8C=E5=96=84=20=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8C=E4=B9=A6=E5=BA=93=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E7=9B=AE=E5=BD=95=E9=A1=B5=E9=9D=A2=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=AF=B9=E5=BA=94=E4=B8=8B=E6=A0=8F=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=202.=E5=A2=9E=E5=8A=A0=E9=98=85=E8=AF=BB=E8=A6=86=E7=9B=96?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=88=E7=B2=97=E7=B3=99=E7=89=88=EF=BC=9A?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E5=B8=83=E5=B1=80=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E8=BF=9B=E5=85=A5=E5=92=8C=E9=80=80=E5=87=BA=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubList.cpp | 51 ++- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 239 +--------- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 27 +- epdiy-epub/lib/Epub/EpubList/EpubToc.cpp | 19 +- epdiy-epub/src/boards/controls/Actions.h | 3 - epdiy-epub/src/epub_screen.cpp | 9 +- epdiy-epub/src/main.cpp | 461 +++++++------------- 7 files changed, 230 insertions(+), 579 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp index 72e66ce..81de2fa 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubList.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubList.cpp @@ -15,7 +15,7 @@ static const char *TAG = "PUBLIST"; #define PADDING 20 -#define EPUBS_PER_PAGE 5 +#define EPUBS_PER_PAGE 4 void EpubList::next() { @@ -138,8 +138,10 @@ void EpubList::render() ulog_d(TAG, "Rendering EPUB list"); // what page are we on? int current_page = state.selected_item / EPUBS_PER_PAGE; - // 计算单元格高度(不再预留底部区域) - int cell_height = (renderer->get_page_height()) / EPUBS_PER_PAGE; + // 计算单元格高度,并为底部按钮预留区域与底部间距 + const int bottom_area_height = 100; // 底部三按钮区域高度 + const int bottom_margin = 30; // 与屏幕底部的间距 + int cell_height = (renderer->get_page_height() - bottom_area_height - bottom_margin) / EPUBS_PER_PAGE; ulog_d(TAG, "Cell height is %d", cell_height); int start_index = current_page * EPUBS_PER_PAGE; int ypos = 0; @@ -239,6 +241,45 @@ void EpubList::render() } state.previous_selected_item = state.selected_item; state.previous_rendered_page = current_page; - - // 移除书库页底部触控开关区域 + // 绘制底部三按钮区域 + int page_w = renderer->get_page_width(); + int page_h = renderer->get_page_height(); + int area_y = page_h - bottom_area_height - bottom_margin; + // 背景 + renderer->fill_rect(0, area_y, page_w, bottom_area_height, 255); + // 三个等宽按钮 + int btn_gap = 10; + int btn_w = (page_w - btn_gap * 4) / 3; + int btn_h = 80; + int btn_y = area_y + (bottom_area_height - btn_h) / 2; + int btn_x0 = btn_gap; // 上一页 + int btn_x1 = btn_gap * 2 + btn_w; // 主页面 + int btn_x2 = btn_gap * 3 + btn_w * 2; // 下一页 + + // 高亮边框:当处于底部模式时,高亮当前选择 + auto draw_button = [&](int x, const char* text, bool selected) + { + if (selected) + { + // 加粗描边,表示选中 + for (int i = 0; i < 5; ++i) + { + renderer->draw_rect(x + i, btn_y + i, btn_w - 2 * i, btn_h - 2 * i, 0); + } + } + else + { + // 非选中用细描边 + renderer->draw_rect(x, btn_y, btn_w, btn_h, 80); + } + int t_w = renderer->get_text_width(text); + int t_h = renderer->get_line_height(); + int tx = x + (btn_w - t_w) / 2; + int ty = btn_y + (btn_h - t_h) / 2; + renderer->draw_text(tx, ty, text, false, true); + }; + + draw_button(btn_x0, "上一页", m_bottom_mode && m_bottom_idx == 0); + draw_button(btn_x1, "主页面", m_bottom_mode && m_bottom_idx == 1); + draw_button(btn_x2, "下一页", m_bottom_mode && m_bottom_idx == 2); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 34d09e2..0b8cd9e 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -113,21 +113,6 @@ void EpubReader::render() parser->render_page(state.current_page, renderer, epub); ulog_d(TAG, "rendered page %d of %d", state.current_page, parser->get_page_count()); ulog_d(TAG, "after render: %d", heap_free_size()); - // 章节进度 - if (state.pages_in_current_section > 0) - { - char buf[32]; - rt_snprintf(buf, sizeof(buf), "%d页/%d页", state.current_page + 1, state.pages_in_current_section); - int page_w = renderer->get_page_width(); - int page_h = renderer->get_page_height(); - int text_w = renderer->get_text_width(buf); - int text_h = renderer->get_line_height(); - int x = (page_w - text_w) / 2; - int reserved_bottom = renderer->get_line_height() + 4; - const int progress_up = 6; // 上抬 - int y = page_h - text_h - 10 + reserved_bottom - progress_up; - renderer->draw_text(x, y, buf, false, true); - } // 绘制半屏覆盖操作层 if (overlay_active) { @@ -142,20 +127,18 @@ void EpubReader::set_state_section(uint16_t current_section) { void EpubReader::render_overlay() { - clear_areas(); // 清除之前的区域记录 - int page_w = renderer->get_page_width(); int page_h = renderer->get_page_height(); int area_y = (page_h * 2) / 3; // 覆盖下方 1/3 屏幕 int area_h = page_h - area_y; - - renderer->fill_rect(0, area_y, page_w, area_h, 240);//绘制灰色背景 + // 半透明效果不可用,使用浅灰底区分 + renderer->fill_rect(0, area_y, page_w, area_h, 240); // 三行布局:3,5,3 const int rows = 3; const int cols[rows] = {3, 5, 3}; const int gap_h = 20; // 行间距 - const int gap_w = 10; // 列间距 + const int gap_w = 10; const int row_h = 80; // 每行高度 // 纵向居中放置三行 int content_h = rows * row_h + (rows + 1) * gap_h; @@ -163,131 +146,15 @@ void EpubReader::render_overlay() if (y0 < area_y + 4) y0 = area_y + 4; int index = 0; - auto fill_label = [&](int idx, char *label, size_t cap) { - switch (idx) - { - case 0: rt_snprintf(label, cap, "<"); break; - case 1: - { - if (overlay_center_mode == CENTER_TOUCH) - { - rt_snprintf(label, cap, "触摸开关:%s", overlay_touch_enabled ? "开" : "关"); - } - else - { - int v = overlay_get_full_refresh_value(); - if (v == 0) - rt_snprintf(label, cap, "全刷周期:每次"); - else - rt_snprintf(label, cap, "全刷周期:%d次", v); - } - break; - } - case 2: rt_snprintf(label, cap, ">"); break; - case 3: rt_snprintf(label, cap, "-5"); break; - case 4: rt_snprintf(label, cap, "-1"); break; - // 第六格显示:x/n 页 - case 5: - { - int total = state.pages_in_current_section; - if (total <= 0 && parser) total = parser->get_page_count(); - if (total <= 0) total = 1; - rt_snprintf(label, cap, "%d/%d", overlay_target_page, total); - break; - } - case 6: rt_snprintf(label, cap, "+1"); break; - case 7: rt_snprintf(label, cap, "+5"); break; - case 8: rt_snprintf(label, cap, "确认"); break; - case 9: rt_snprintf(label, cap, "目录"); break; - case 10: rt_snprintf(label, cap, "书库"); break; - default: label[0] = '\0'; break; - } - }; for (int r = 0; r < rows; ++r) { int c = cols[r]; + int usable_w = page_w - (c + 1) * gap_w; + int btn_w = usable_w / c; int y = y0 + gap_h + r * (row_h + gap_h); - // 顶部第1行(3列)采用不等宽布局:1/3半宽,2双宽 - if (r == 0) + for (int i = 0; i < c; ++i) { - int usable_w = page_w - (c + 1) * gap_w; - // 宽度权重为 1:3:1(约 左20% / 中60% / 右20%) - int w0 = (usable_w * 1) / 5; - int w1 = (usable_w * 3) / 5; - int w2 = usable_w - w0 - w1; - int widths[3] = { w0, w1, w2 }; - int cur_x = gap_w; - //将坐标位置映射到触控中 - int first_one_x = cur_x;; - int first_one_y = y; - static_add_area(first_one_x, first_one_y, widths[0], row_h,0); - - int second_one_x = cur_x + widths[0] + gap_w; - int second_one_y = y; - static_add_area(second_one_x, second_one_y, widths[1], row_h,1); - - int third_one_x = cur_x + widths[0] + widths[1] + 2 * gap_w; - int third_one_y = y; - static_add_area(third_one_x, third_one_y, widths[2], row_h,2); - - for (int i = 0; i < c; ++i) - { - int w = widths[i]; - int x = cur_x; - bool selected = (index == overlay_selected); - if (selected) - { - for (int k = 0; k < 5; ++k) - { - renderer->draw_rect(x + k, y + k, w - 2 * k, row_h - 2 * k, 0); - } - } - else - { - renderer->draw_rect(x, y, w, row_h, 80); - } - char label[32]; - fill_label(index, label, sizeof(label)); - int t_w = renderer->get_text_width(label); - int t_h = renderer->get_line_height(); - int tx = x + (w - t_w) / 2; - int ty = y + (row_h - t_h) / 2; - renderer->draw_text(tx, ty, label, false, true); - index++; - cur_x = x + w + gap_w; - } - } - else - { - int usable_w = page_w - (c + 1) * gap_w; - int btn_w = usable_w / c; - // 第二行触控区域映射(索引3-7) - if (r == 1) // 第二行 - { - for (int i = 0; i < c; ++i) // c = 5 - { - int x = gap_w + i * (btn_w + gap_w); - int y_coord = y0 + gap_h + r * (row_h + gap_h); - - // 添加触控区域(索引3-7对应按钮) - static_add_area(x, y_coord, btn_w, row_h, 3 + i); - } - } - // 第三行触控区域映射(索引8-10) - else if (r == 2) // 第三行 - { - for (int i = 0; i < c; ++i) // c = 3 - { - int x = gap_w + i * (btn_w + gap_w); - int y_coord = y0 + gap_h + r * (row_h + gap_h); - - // 添加触控区域(索引8-10对应按钮) - static_add_area(x, y_coord, btn_w, row_h, 8 + i); - } - } - for (int i = 0; i < c; ++i) - { - int x = gap_w + i * (btn_w + gap_w); + int x = gap_w + i * (btn_w + gap_w); bool selected = (index == overlay_selected); if (selected) { @@ -300,15 +167,22 @@ void EpubReader::render_overlay() { renderer->draw_rect(x, y, btn_w, row_h, 80); } - char label[32]; - fill_label(index, label, sizeof(label)); + // 文本:第9个显示"确认",其余显示编号 + char label[16]; + if (index == 8) + { + rt_snprintf(label, sizeof(label), "确认"); + } + else + { + rt_snprintf(label, sizeof(label), "%d", index + 1); + } int t_w = renderer->get_text_width(label); int t_h = renderer->get_line_height(); int tx = x + (btn_w - t_w) / 2; int ty = y + (row_h - t_h) / 2; renderer->draw_text(tx, ty, label, false, true); index++; - } } } } @@ -323,83 +197,4 @@ void EpubReader::overlay_move_right() { if (!overlay_active) return; overlay_selected = (overlay_selected + 1) % 11; -} - -void EpubReader::jump_pages(int delta) -{ - if (delta == 0) return; - if (!parser) //没解析的情况下 则解析当前节 - { - parse_and_layout_current_section(); - } - int spine_count = epub ? epub->get_spine_items_count() : 0; //获取章节总数 - if (spine_count <= 0) return; - - //检查是不是第一页 - auto at_book_start = [&]() -> bool - { - return state.current_section == 0 && state.current_page == 0; - }; - //检查是不是最后一页 - auto at_book_end = [&]() -> bool - { - if (!parser) return false; - return (state.current_section == spine_count - 1) && (state.current_page >= state.pages_in_current_section - 1); - }; - // 开始实现页面跳转 - if (delta > 0) - { - for (int i = 0; i < delta; ++i) - { - if (at_book_end()) break; - next(); - // 如果跨节,parser 在 next() 时会置空;后续渲染时会自动 parse - if (!parser) - { - parse_and_layout_current_section(); - } - } - } - else // delta < 0 - { - for (int i = 0; i < -delta; ++i) - { - if (at_book_start()) break; - prev(); - if (!parser) - { - //空就解析 - parse_and_layout_current_section(); - } - } - } -} - -void EpubReader::overlay_cycle_full_refresh() -{ - screen_cycle_full_refresh_period(true); -} - -int EpubReader::overlay_get_full_refresh_value() const -{ - return screen_get_full_refresh_period(); -} - -void EpubReader::overlay_set_target_page(int p) -{ - if (p < 1) p = 1; - int maxp = state.pages_in_current_section; - if (maxp <= 0 && parser) - { - maxp = parser->get_page_count(); - } - if (maxp <= 0) maxp = 1; - if (p > maxp) p = maxp; - overlay_target_page = p; -} - -void EpubReader::overlay_adjust_target_page(int d) -{ - int p = overlay_target_page + d; - overlay_set_target_page(p); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index d65ef72..f60befd 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -16,16 +16,6 @@ class EpubReader // 阅读页半屏覆盖操作层状态 bool overlay_active = false; int overlay_selected = 0; // 0..10,共11个 - int overlay_jump_acc = 0; // 覆盖层累积跳页值(可为负) - // 覆盖层目标页(当前章节内的页,1-based) - int overlay_target_page = 1; - // 覆盖层中心属性模式:触控开关 或 全刷周期 - enum OverlayCenterMode { CENTER_TOUCH = 0, CENTER_FULL_REFRESH = 1 }; - OverlayCenterMode overlay_center_mode = CENTER_TOUCH; - // 触控开关当前状态(由上层同步) - bool overlay_touch_enabled = false; - // 全刷周期索引:0->5, 1->10, 2->20, 3->每次(0) - int overlay_fr_idx = 0; void parse_and_layout_current_section(); void render_overlay(); @@ -40,25 +30,10 @@ class EpubReader void render(); void set_state_section(uint16_t current_section); // 覆盖层控制 - void start_overlay() { overlay_active = true; overlay_selected = 0; overlay_jump_acc = 0; overlay_target_page = state.current_page + 1; } + void start_overlay() { overlay_active = true; overlay_selected = 0; } void stop_overlay() { overlay_active = false; } bool is_overlay_active() const { return overlay_active; } void overlay_move_left(); void overlay_move_right(); int get_overlay_selected() const { return overlay_selected; } - // 覆盖层跳页累积控制 - void overlay_reset_jump() { overlay_jump_acc = 0; } - int overlay_get_jump() const { return overlay_jump_acc; } - // 覆盖层目标页控制 - void overlay_set_target_page(int p); - void overlay_adjust_target_page(int d); - int overlay_get_target_page() const { return overlay_target_page; } - // 覆盖层中心属性控制 - void overlay_set_center_mode_touch() { overlay_center_mode = CENTER_TOUCH; } - void overlay_set_center_mode_full_refresh() { overlay_center_mode = CENTER_FULL_REFRESH; } - bool overlay_is_center_touch() const { return overlay_center_mode == CENTER_TOUCH; } - void overlay_set_touch_enabled(bool en) { overlay_touch_enabled = en; } - bool overlay_get_touch_enabled() const { return overlay_touch_enabled; } - void overlay_cycle_full_refresh(); - int overlay_get_full_refresh_value() const; }; \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp index 1e23d1c..d3eb34c 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubToc.cpp @@ -168,7 +168,7 @@ void EpubToc::render() int btn_h = 80; int btn_y = area_y + (bottom_area_height - btn_h) / 2; int btn_x0 = btn_gap; // 上一页 - int btn_x1 = btn_gap * 2 + btn_w; // 书库 + int btn_x1 = btn_gap * 2 + btn_w; // 主页面 int btn_x2 = btn_gap * 3 + btn_w * 2; // 下一页 auto draw_button = [&](int x, const char* text, bool selected) @@ -194,25 +194,8 @@ void EpubToc::render() }; draw_button(btn_x0, "上一页", m_bottom_mode && m_bottom_idx == 0); - int start_up_page_x = btn_x0; - int start_up_page_y = btn_y + btn_gap * 2; - int end_up_page_x = btn_w; - int end_up_page_y = btn_h; - int start_page_x = btn_x0; - static_add_area(start_up_page_x, start_up_page_y, end_up_page_x, end_up_page_y, 6); - draw_button(btn_x1, "书库", m_bottom_mode && m_bottom_idx == 1); - int start_main_page_x = btn_x1; - int start_main_page_y = btn_y + btn_gap *2; - int end_main_page_x = btn_w; - int end_main_page_y = btn_h; - static_add_area(start_main_page_x, start_main_page_y, end_main_page_x, end_main_page_y, 7); draw_button(btn_x2, "下一页", m_bottom_mode && m_bottom_idx == 2); - int start_down_page_x = btn_x2; - int start_down_page_y = btn_y + btn_gap *2; - int end_down_page_x = btn_w; - int end_down_page_y = btn_h; - static_add_area(start_down_page_x, start_down_page_y, end_down_page_x, end_down_page_y, 8); } uint16_t EpubToc::get_selected_toc() diff --git a/epdiy-epub/src/boards/controls/Actions.h b/epdiy-epub/src/boards/controls/Actions.h index 5e22d6b..8e83835 100644 --- a/epdiy-epub/src/boards/controls/Actions.h +++ b/epdiy-epub/src/boards/controls/Actions.h @@ -9,9 +9,6 @@ typedef enum DOWN, SELECT, UPGLIDE, // 长按触发的上滑操作,用于阅读页半屏操作覆盖 - PREV_OPTION, // 上一选项(用于列表选择) - NEXT_OPTION, // 下一选项(用于列表选择) - SELECT_BOX, // 选择框(用于触控选择) LAST_INTERACTION, MSG_DRAW_LOW_POWER_PAGE, MSG_DRAW_CHARGE_PAGE, diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index ede9f23..d58ca7b 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -185,7 +185,8 @@ static void render_settings_page(Renderer *renderer) } if (settings_selected_idx == SET_TOUCH) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + // 选中强化:多重描边,提高可见度 + for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { @@ -213,7 +214,7 @@ static void render_settings_page(Renderer *renderer) } if (settings_selected_idx == SET_TIMEOUT) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { @@ -246,7 +247,7 @@ static void render_settings_page(Renderer *renderer) } if (settings_selected_idx == SET_FULL_REFRESH) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); + for (int i = 0; i < 5; ++i) renderer->draw_rect(item_x + i, y + i, item_w - 2 * i, item_h - 2 * i, 0); } else { @@ -270,7 +271,7 @@ static void render_settings_page(Renderer *renderer) int confirm_y = page_h - confirm_h - 60; // 距离底部位置 if (settings_selected_idx == SET_CONFIRM) { - for (int i = 0; i < 2; ++i) renderer->draw_rect(confirm_x + i, confirm_y + i, confirm_w - 2 * i, confirm_h - 2 * i, 0); + for (int i = 0; i < 5; ++i) renderer->draw_rect(confirm_x + i, confirm_y + i, confirm_w - 2 * i, confirm_h - 2 * i, 0); } else { diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index e493331..fde1109 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -39,9 +39,9 @@ const char *TAG = "main"; typedef enum { MAIN_PAGE, // 新主页面 - SELECTING_EPUB, - SELECTING_TABLE_CONTENTS, - READING_EPUB, + SELECTING_EPUB, // 电子书列表页面(书库) + SELECTING_TABLE_CONTENTS, // 电子书目录页面 + READING_EPUB, // 阅读页面 SETTINGS_PAGE // 通用功能设置页面 } UIState; typedef enum @@ -77,18 +77,9 @@ Renderer *renderer = nullptr; TouchControls *touch_controls = nullptr; // 书库页底部按钮选择状态 -bool library_bottom_mode = false; // 是否处于底部三按钮选择模式 -int library_bottom_idx = 1; // 当前底部按钮索引:0上一页,1主页面,2下一页 -int book_index;//用于记录电子书触控选择 -int current_page; // 当前页面 -int start_index; // 当前页起始索引 -// 计算全局索引 = 页起始索引 + 页内偏移 -int global_index; -bool toc_bottom_mode = false; -int toc_index;//用于记录目录触控选择 -int toc_bottom_idx = 1; // 0:上一页,1:主页面,2:下一页 -int sel; -int touch_sel; +static bool library_bottom_mode = false; // 是否处于底部三按钮选择模式 +static int library_bottom_idx = 1; // 当前底部按钮索引:0上一页,1主页面,2下一页 + rt_mq_t ui_queue = RT_NULL; // 主页面选项 @@ -100,178 +91,70 @@ typedef enum { void handleEpub(Renderer *renderer, UIAction action) { - if (!reader) + if (!reader) + { + reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); + reader->load(); + } + switch (action) + { + case UP: + if (reader->is_overlay_active()) { - reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); - reader->load(); - // 记录最近一次进入阅读的书籍索引 - g_last_read_index = epub_list_state.selected_item; + reader->overlay_move_left(); } - - switch (action) + else { - case UP: - if (reader->is_overlay_active()) - { - reader->overlay_move_left(); - } - else - { - reader->prev(); - } - break; - case DOWN: - if (reader->is_overlay_active()) - { - reader->overlay_move_right(); - } - else - { - reader->next(); - } - break; - case SELECT: - if (reader->is_overlay_active()) - { - int sel = reader->get_overlay_selected(); - // 1/3:改变中心属性;2:执行当前属性(触控取反 / 全刷周期循环) - if(touch_sel >=0 && touch_sel <=10) - { - sel = -1; - } - if (sel == 0 || touch_sel == 0) - { - if(reader->overlay_is_center_touch()) - { - reader->overlay_set_center_mode_full_refresh(); - } - else - { - reader->overlay_set_center_mode_touch(); - } - } - else if (sel == 2 || touch_sel == 2) - { - if(reader->overlay_is_center_touch()) - { - reader->overlay_set_center_mode_full_refresh(); - } - else - { - reader->overlay_set_center_mode_touch(); - } - } - else if (sel == 1 || touch_sel == 1) - { - // 中心矩形:根据当前属性执行 - if (reader->overlay_is_center_touch()) - { - bool cur = touch_controls ? touch_controls->isTouchEnabled() : false; - if (touch_controls) - { - touch_controls->setTouchEnable(!cur); - if (!cur) touch_controls->powerOnTouch(); else touch_controls->powerOffTouch(); - } - reader->overlay_set_touch_enabled(!cur); - } - else - { - reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/每次(0) 之间循环 - set_part_disp_times(reader->overlay_get_full_refresh_value()); - } - } - if (sel == 9 || touch_sel == 9) //目录 - { - ui_state = SELECTING_TABLE_CONTENTS; - renderer->set_margin_bottom(0); - reader->stop_overlay(); - delete reader; - reader = nullptr; - contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); - contents->load(); - contents->set_needs_redraw(); - handleEpubTableContents(renderer, NONE, true); - touch_sel = -1; - return; - } - else if (sel == 8 || touch_sel == 8) //确认:1.按第六格累积值跳页 - { - // 跳转到第六格显示的目标页 - int target = reader->overlay_get_target_page(); - if (target < 1) target = 1; - extern EpubListState epub_list_state; - epub_list_state.epub_list[epub_list_state.selected_item].current_page = (uint16_t)(target - 1); - reader->overlay_reset_jump(); - reader->stop_overlay(); - } - else if (sel == 10 || touch_sel == 10) //书库 - { - ui_state = SELECTING_EPUB; - renderer->set_margin_bottom(0); - reader->stop_overlay(); - renderer->clear_screen(); - delete reader; - reader = nullptr; - if (!epub_list) - { - epub_list = new EpubList(renderer, epub_list_state); - } - handleEpubList(renderer, NONE, true); - touch_sel = -1; - return; - } - else if (sel == 3 || touch_sel == 3) - { - reader->overlay_adjust_target_page(-5); - } - else if (sel == 4 || touch_sel == 4) - { - reader->overlay_adjust_target_page(-1); - } - else if (sel == 6 || touch_sel == 6) - { - reader->overlay_adjust_target_page(1); - } - else if (sel == 7 || touch_sel == 7) - { - reader->overlay_adjust_target_page(5); - } - touch_sel = -1; - } - else - { - // switch back to main screen - renderer->clear_screen(); - // clear the epub reader away - delete reader; - reader = nullptr; - // force a redraw - if (!epub_list) - { - epub_list = new EpubList(renderer, epub_list_state); - } - renderer->set_margin_bottom(0); - back_to_main_page(); + reader->prev(); + } + break; + case DOWN: + if (reader->is_overlay_active()) + { + reader->overlay_move_right(); + } + else + { + reader->next(); + } + break; + case SELECT: + if (reader->is_overlay_active()) + { + // 在覆盖层中,SELECT仅作用于覆盖区域:当选中"确认"时关闭覆盖层 + if (reader->get_overlay_selected() == 8) + { + reader->stop_overlay(); + } + // 非“确认”暂不执行其他操作 + } + else + { + // switch back to main screen + ui_state = SELECTING_EPUB; + renderer->clear_screen(); + // clear the epub reader away + delete reader; + reader = nullptr; + // force a redraw + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + handleEpubList(renderer, NONE, true); - return; - } - break; - case UPGLIDE: - // 激活阅读页下半屏覆盖操作层 - // 防止重复激活 - if (!reader->is_overlay_active()) { - reader->start_overlay(); - // 默认中心属性为触控开关,初始同步当前触控状态 - reader->overlay_set_center_mode_touch(); - if (touch_controls) - reader->overlay_set_touch_enabled(touch_controls->isTouchEnabled()); - } - break; - case NONE: - default: - break; + return; } - reader->render(); + break; + case UPGLIDE: + // 激活阅读页下半屏覆盖操作层 + reader->start_overlay(); + break; + case NONE: + default: + break; + } + reader->render(); } //目录页的处理 void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw) @@ -282,7 +165,8 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red contents->set_needs_redraw(); contents->load(); } - + static bool toc_bottom_mode = false; + static int toc_bottom_idx = 1; // 0:上一页,1:主页面,2:下一页 if (needs_redraw) { toc_bottom_mode = false; @@ -293,31 +177,15 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red case UP: if (toc_bottom_mode) { - // 底部模式下:UP 向左移动;若已在最左(上一页),则返回当前页目录的最后一项 - if (toc_bottom_idx > 0) - { - toc_bottom_idx--; - } - else - { - int per_page = 6; - int start_idx = (epub_index_state.selected_item / per_page) * per_page; - int end_idx = start_idx + per_page - 1; - int count = contents->get_items_count(); - if (end_idx >= count) end_idx = count - 1; - toc_bottom_mode = false; - epub_index_state.selected_item = end_idx; - } + toc_bottom_idx = (toc_bottom_idx + 2) % 3; // 左移 } else { - // 若处于当前页第一个条目,UP 切换到底部按钮模式并选择“下一页” int per_page = 6; int start_idx = (epub_index_state.selected_item / per_page) * per_page; if (contents->get_items_count() > 0 && epub_index_state.selected_item == start_idx) { toc_bottom_mode = true; - toc_bottom_idx = 2; // 下一页 } else { @@ -328,18 +196,7 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red case DOWN: if (toc_bottom_mode) { - // 底部模式下:DOWN 向右移动;若已在最右(下一页),则返回当前页目录的第一项 - if (toc_bottom_idx < 2) - { - toc_bottom_idx++; - } - else - { - int per_page = 6; - int start_idx = (epub_index_state.selected_item / per_page) * per_page; - toc_bottom_mode = false; - epub_index_state.selected_item = start_idx; - } + toc_bottom_idx = (toc_bottom_idx + 1) % 3; // 右移 } else { @@ -348,11 +205,9 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red int end_idx = start_idx + per_page - 1; int count = contents->get_items_count(); if (end_idx >= count) end_idx = count - 1; - // 若处于当前页最后一个条目,DOWN 切换到底部按钮模式并选择“上一页” if (count > 0 && epub_index_state.selected_item == end_idx) { toc_bottom_mode = true; - toc_bottom_idx = 0; // 上一页 } else { @@ -423,37 +278,28 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red handleEpubList(renderer, NONE, true); return; } - else if (toc_bottom_idx == 0) // 上一页 + else if (toc_bottom_idx == 0) { + // 上一页 if (current_page > 0) { - // 计算新页面(上一页) - int new_page = current_page - 1; - // 将选中项设置为新页面的第一项 - epub_index_state.selected_item = new_page * per_page; - if (epub_index_state.selected_item < 0) - epub_index_state.selected_item = 0; - - // 退出底部选择模式,回到列表选择状态 - toc_bottom_mode = false; + epub_index_state.selected_item -= per_page; + if (epub_index_state.selected_item < 0) epub_index_state.selected_item = 0; contents->set_needs_redraw(); } + toc_bottom_mode = false; } - else if (toc_bottom_idx == 2) // 下一页 + else if (toc_bottom_idx == 2) { + // 下一页 if (current_page < max_page) { - // 计算新页面(下一页) - int new_page = current_page + 1; - // 将选中项设置为新页面的第一项 - epub_index_state.selected_item = new_page * per_page; + epub_index_state.selected_item += per_page; if (epub_index_state.selected_item >= count) - epub_index_state.selected_item = ((count - 1) / per_page) * per_page; // 确保在最后一页的第一项 - - // 退出底部选择模式,回到列表选择状态 - toc_bottom_mode = false; + epub_index_state.selected_item = count - 1; contents->set_needs_redraw(); } + toc_bottom_mode = false; } } else @@ -463,8 +309,6 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); reader->set_state_section(contents->get_selected_toc()); reader->load(); - // 记录最近一次进入阅读的书籍索引 - g_last_read_index = epub_list_state.selected_item; delete contents; handleEpub(renderer, NONE); return; @@ -506,20 +350,8 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) case UP: if (library_bottom_mode) { - // 底部模式下:UP 向左移动;若已在最左(上一页),则返回当前页的列表最后一项 - if (library_bottom_idx > 0) - { - library_bottom_idx--; - } - else - { - int per_page = 4; - int start_idx = (epub_list_state.selected_item / per_page) * per_page; - int end_idx = start_idx + per_page - 1; - if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; - library_bottom_mode = false; - epub_list_state.selected_item = end_idx; - } + // UP 表示向左选择 + library_bottom_idx = (library_bottom_idx + 2) % 3; } else { @@ -529,7 +361,6 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == start_idx) { library_bottom_mode = true; - library_bottom_idx = 2; // 下一页 } else { @@ -538,53 +369,69 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } break; case DOWN: - epub_list->next(); + if (library_bottom_mode) + { + // DOWN 表示向右选择 + library_bottom_idx = (library_bottom_idx + 1) % 3; + } + else + { + int per_page = 4; + int start_idx = (epub_list_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; + // 若处于当前页最后一个条目,DOWN 切换到底部按钮模式 + if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == end_idx) + { + library_bottom_mode = true; + } + else + { + epub_list->next(); + } + } break; case SELECT: + if (library_bottom_mode) + { int per_page = 4; int current_page = epub_list_state.selected_item / per_page; int max_page = (epub_list_state.num_epubs == 0) ? 0 : ( (epub_list_state.num_epubs - 1) / per_page ); if (library_bottom_idx == 1) { - // 主页面:返回主页面 - rt_kprintf("从书库页返回主页面\n"); - back_to_main_page(); - return; + // 主页面:返回主页面 + rt_kprintf("从书库页返回主页面\n"); + back_to_main_page(); + return; } - else if (library_bottom_idx == 0) // 上一页 + else if (library_bottom_idx == 0) { - if (current_page > 0) - { - // 计算新页面(上一页) - int new_page = current_page - 1; - // 将选中项设置为新页面的第一本书 - epub_list_state.selected_item = new_page * per_page; - if (epub_list_state.selected_item < 0) - epub_list_state.selected_item = 0; - - // 退出底部选择模式,回到列表选择状态 - library_bottom_mode = false; - epub_list->set_needs_redraw(); - } + // 上一页 + if (current_page > 0) + { + epub_list_state.selected_item -= per_page; + if (epub_list_state.selected_item < 0) epub_list_state.selected_item = 0; + epub_list->set_needs_redraw(); + } + // 切回条目选择模式 + library_bottom_mode = false; } - else if (library_bottom_idx == 2) // 下一页 + else if (library_bottom_idx == 2) { - if (current_page < max_page) - { - // 计算新页面(下一页) - int new_page = current_page + 1; - // 将选中项设置为新页面的第一本书 - epub_list_state.selected_item = new_page * per_page; - if (epub_list_state.selected_item >= epub_list_state.num_epubs) - epub_list_state.selected_item = ((epub_list_state.num_epubs - 1) / per_page) * per_page; // 确保在最后一页的第一本书 - - // 退出底部选择模式,回到列表选择状态 - library_bottom_mode = false; - epub_list->set_needs_redraw(); - } + // 下一页 + if (current_page < max_page) + { + epub_list_state.selected_item += per_page; + if (epub_list_state.selected_item >= epub_list_state.num_epubs) + epub_list_state.selected_item = epub_list_state.num_epubs - 1; + epub_list->set_needs_redraw(); + } + // 切回条目选择模式 + library_bottom_mode = false; } - else - { + } + else + { // 进入目录选择页面 ui_state = SELECTING_TABLE_CONTENTS; contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); @@ -592,8 +439,8 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) contents->set_needs_redraw(); handleEpubTableContents(renderer, NONE, true); return; - } - break; + } + break; case NONE: default: // nothing to do @@ -684,10 +531,20 @@ void handleUserInteraction(Renderer *renderer, UIAction ui_action, bool needs_re { case MAIN_PAGE: // 新主页面 handleMainPage(renderer, ui_action, needs_redraw); - if (ui_action == SELECT && screen_get_main_selected_option() == 2) + if (ui_action == SELECT && screen_get_main_selected_option() == 2) //切换到设置页面 { ui_state = SETTINGS_PAGE; - (void)handleSettingsPage(renderer, NONE, true); + (void)handleSettingsPage(renderer, NONE, true); + } + else if (ui_action == SELECT && screen_get_main_selected_option() == 1) //切换到阅读页面 + { + // ui_state = READING_EPUB; + // handleEpub(renderer, NONE); + } + else if (ui_action == SELECT && screen_get_main_selected_option() == 0) //切换到书库页面 + { + ui_state = SELECTING_EPUB; + handleEpubList(renderer, NONE, true); } break; case READING_EPUB: //阅读界面 @@ -740,18 +597,20 @@ const char* getCurrentPageName() { } //回到主界面接口 void back_to_main_page() -{ - if (ui_state == MAIN_PAGE) - { - rt_kprintf("已经在主页面,无需返回\n"); - return; - } - if (ui_state == SELECTING_TABLE_CONTENTS) - { - if (contents) - { - delete contents; - contents = nullptr; +{ + if (ui_state == MAIN_PAGE) + { + rt_kprintf("已经在主页面,无需返回\n"); + return; + } + lowpower_ui_state = MAIN_MENU; + if (ui_state == SELECTING_TABLE_CONTENTS) + { + if (contents) + { + delete contents; + contents = nullptr; + } } } bool hydrate_success = renderer->hydrate(); From 15e2e85e52cc3e3ce98ffe77246a9ccd06c23dd9 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Wed, 14 Jan 2026 17:58:27 +0800 Subject: [PATCH 15/27] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=98=85=E8=AF=BB?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2=EF=BC=9A1.=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20=E7=9B=AE=E5=BD=95=E9=A1=B5=E9=9D=A2=20=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=20=E4=B9=A6=E5=BA=93=E9=A1=B5=E9=9D=A2=E7=9A=84?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=8A=9F=E8=83=BD=202.=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=B4=AF=E7=A7=AF=E8=B7=B3=E8=BD=AC=E9=A1=B5=E9=9D=A2=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 70 ++++++++++++++++++--- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 7 ++- epdiy-epub/src/main.cpp | 56 +++++++++++++++-- 3 files changed, 121 insertions(+), 12 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 0b8cd9e..0b02a1d 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -167,15 +167,24 @@ void EpubReader::render_overlay() { renderer->draw_rect(x, y, btn_w, row_h, 80); } - // 文本:第9个显示"确认",其余显示编号 + // 文本映射: + // 1:"<" 2:保留原编号 3:">" 4:"-5" 5:"-1" 6:"acc" 7:"+1" 8:"+5" 9:"确认" 10:"目录" 11:"书库" char label[16]; - if (index == 8) + switch (index) { - rt_snprintf(label, sizeof(label), "确认"); - } - else - { - rt_snprintf(label, sizeof(label), "%d", index + 1); + case 0: rt_snprintf(label, sizeof(label), "<"); break; + case 1: rt_snprintf(label, sizeof(label), "2"); break; + case 2: rt_snprintf(label, sizeof(label), ">"); break; + case 3: rt_snprintf(label, sizeof(label), "-5"); break; + case 4: rt_snprintf(label, sizeof(label), "-1"); break; + case 5: rt_snprintf(label, sizeof(label), "%d", overlay_jump_acc); break; + case 6: rt_snprintf(label, sizeof(label), "+1"); break; + case 7: rt_snprintf(label, sizeof(label), "+5"); break; + case 8: rt_snprintf(label, sizeof(label), "确认"); break; + case 9: rt_snprintf(label, sizeof(label), "目录"); break; + case 10: rt_snprintf(label, sizeof(label), "书库"); break; + default: + break; } int t_w = renderer->get_text_width(label); int t_h = renderer->get_line_height(); @@ -197,4 +206,51 @@ void EpubReader::overlay_move_right() { if (!overlay_active) return; overlay_selected = (overlay_selected + 1) % 11; +} + +void EpubReader::jump_pages(int delta) +{ + if (delta == 0) return; + if (!parser) //没解析的情况下 则解析当前节 + { + parse_and_layout_current_section(); + } + int spine_count = epub ? epub->get_spine_items_count() : 0; //获取章节总数 + if (spine_count <= 0) return; + + auto at_book_start = [&]() -> bool { + return state.current_section == 0 && state.current_page == 0; + }; + auto at_book_end = [&]() -> bool { + // 需要知道当前节页数;parser 非空时有效 + if (!parser) return false; + return (state.current_section == spine_count - 1) && (state.current_page >= state.pages_in_current_section - 1); + }; + // 开始实现页面跳转 + if (delta > 0) + { + for (int i = 0; i < delta; ++i) + { + if (at_book_end()) break; + next(); + // 如果跨节,parser 在 next() 时会置空;后续渲染时会自动 parse + if (!parser) + { + parse_and_layout_current_section(); + } + } + } + else // delta < 0 + { + for (int i = 0; i < -delta; ++i) + { + if (at_book_start()) break; + prev(); + if (!parser) + { + //空则解析 + parse_and_layout_current_section(); + } + } + } } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index f60befd..1ceebe8 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -16,6 +16,7 @@ class EpubReader // 阅读页半屏覆盖操作层状态 bool overlay_active = false; int overlay_selected = 0; // 0..10,共11个 + int overlay_jump_acc = 0; // 覆盖层累积跳页值(可为负) void parse_and_layout_current_section(); void render_overlay(); @@ -30,10 +31,14 @@ class EpubReader void render(); void set_state_section(uint16_t current_section); // 覆盖层控制 - void start_overlay() { overlay_active = true; overlay_selected = 0; } + void start_overlay() { overlay_active = true; overlay_selected = 0; overlay_jump_acc = 0; } void stop_overlay() { overlay_active = false; } bool is_overlay_active() const { return overlay_active; } void overlay_move_left(); void overlay_move_right(); int get_overlay_selected() const { return overlay_selected; } + // 覆盖层跳页累积控制 + void overlay_add_jump(int d) { overlay_jump_acc += d; } + void overlay_reset_jump() { overlay_jump_acc = 0; } + int overlay_get_jump() const { return overlay_jump_acc; } }; \ No newline at end of file diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index fde1109..651945d 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -88,7 +88,7 @@ typedef enum { OPTION_CONTINUE_READING, // 继续阅读 -> 打印 2 OPTION_ENTER_SETTINGS // 进入设置 -> 打印 3 } MainOption; - +void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw); void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -121,12 +121,60 @@ void handleEpub(Renderer *renderer, UIAction action) case SELECT: if (reader->is_overlay_active()) { - // 在覆盖层中,SELECT仅作用于覆盖区域:当选中"确认"时关闭覆盖层 - if (reader->get_overlay_selected() == 8) + int sel = reader->get_overlay_selected(); + if (sel == 9) //目录 { + ui_state = SELECTING_TABLE_CONTENTS; reader->stop_overlay(); + delete reader; + reader = nullptr; + contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); + contents->load(); + contents->set_needs_redraw(); + handleEpubTableContents(renderer, NONE, true); + return; } - // 非“确认”暂不执行其他操作 + else if (sel == 8) //确认:1.按第六格累积值跳页 + { + int delta = reader->overlay_get_jump(); + if (delta != 0) + { + reader->jump_pages(delta); + } + reader->overlay_reset_jump(); + reader->stop_overlay(); + } + else if (sel == 10) //书库 + { + ui_state = SELECTING_EPUB; + reader->stop_overlay(); + renderer->clear_screen(); + delete reader; + reader = nullptr; + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + handleEpubList(renderer, NONE, true); + return; + } + else if (sel == 3) + { + reader->overlay_add_jump(-5); + } + else if (sel == 4) + { + reader->overlay_add_jump(-1); + } + else if (sel == 6) + { + reader->overlay_add_jump(1); + } + else if (sel == 7) + { + reader->overlay_add_jump(5); + } + } else { From 5bc614309671e7c435f2347165007c850b882ff7 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Thu, 15 Jan 2026 11:22:33 +0800 Subject: [PATCH 16/27] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=98=85=E8=AF=BB?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E9=A1=B5=EF=BC=9A1=EF=BC=8C2=EF=BC=8C3?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E7=9F=A9=E5=BD=A2=E5=AE=9E=E7=8E=B0=20?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E8=A7=A6=E6=8E=A7=20=E4=B8=8E=20=E5=85=A8?= =?UTF-8?q?=E5=88=B7=E5=91=A8=E6=9C=9F=E6=AC=A1=E6=95=B0=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=8A=9F=E8=83=BD=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2=EF=BC=9A=E5=85=A8=E5=88=B7?= =?UTF-8?q?=E5=91=A8=E6=9C=9F=E6=AC=A1=E6=95=B0=E5=8A=A8=E6=80=81=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 125 +++++++++++++++----- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 15 +++ epdiy-epub/src/epub_screen.cpp | 42 ++++++- epdiy-epub/src/epub_screen.h | 5 +- epdiy-epub/src/main.cpp | 46 +++++++ 5 files changed, 201 insertions(+), 32 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 0b02a1d..fa87498 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -13,7 +13,6 @@ #include "../Renderer/Renderer.h" #include "epub_mem.h" #include "epub_screen.h" -#include "UIRegionsManager.h" static const char *TAG = "EREADER"; extern "C" rt_uint32_t heap_free_size(void); @@ -131,7 +130,7 @@ void EpubReader::render_overlay() int page_h = renderer->get_page_height(); int area_y = (page_h * 2) / 3; // 覆盖下方 1/3 屏幕 int area_h = page_h - area_y; - // 半透明效果不可用,使用浅灰底区分 + renderer->fill_rect(0, area_y, page_w, area_h, 240); // 三行布局:3,5,3 @@ -146,15 +145,86 @@ void EpubReader::render_overlay() if (y0 < area_y + 4) y0 = area_y + 4; int index = 0; + auto fill_label = [&](int idx, char *label, size_t cap) { + switch (idx) + { + case 0: rt_snprintf(label, cap, "<"); break; + case 1: + { + if (overlay_center_mode == CENTER_TOUCH) + { + rt_snprintf(label, cap, "触摸开关:%s", overlay_touch_enabled ? "开" : "关"); + } + else + { + int v = overlay_get_full_refresh_value(); + if (v == 0) + rt_snprintf(label, cap, "全刷周期:不刷新"); + else + rt_snprintf(label, cap, "全刷周期:%d次", v); + } + break; + } + case 2: rt_snprintf(label, cap, ">"); break; + case 3: rt_snprintf(label, cap, "-5"); break; + case 4: rt_snprintf(label, cap, "-1"); break; + case 5: rt_snprintf(label, cap, "%d", overlay_jump_acc); break; + case 6: rt_snprintf(label, cap, "+1"); break; + case 7: rt_snprintf(label, cap, "+5"); break; + case 8: rt_snprintf(label, cap, "确认"); break; + case 9: rt_snprintf(label, cap, "目录"); break; + case 10: rt_snprintf(label, cap, "书库"); break; + default: label[0] = '\0'; break; + } + }; for (int r = 0; r < rows; ++r) { int c = cols[r]; - int usable_w = page_w - (c + 1) * gap_w; - int btn_w = usable_w / c; int y = y0 + gap_h + r * (row_h + gap_h); - for (int i = 0; i < c; ++i) + // 顶部第1行(3列)采用不等宽布局:1/3半宽,2双宽 + if (r == 0) { - int x = gap_w + i * (btn_w + gap_w); + int usable_w = page_w - (c + 1) * gap_w; + // 宽度权重为 1:3:1(约 左20% / 中60% / 右20%) + int w0 = (usable_w * 1) / 5; + int w1 = (usable_w * 3) / 5; + int w2 = usable_w - w0 - w1; + int widths[3] = { w0, w1, w2 }; + int cur_x = gap_w; + for (int i = 0; i < c; ++i) + { + int w = widths[i]; + int x = cur_x; + bool selected = (index == overlay_selected); + if (selected) + { + for (int k = 0; k < 5; ++k) + { + renderer->draw_rect(x + k, y + k, w - 2 * k, row_h - 2 * k, 0); + } + } + else + { + renderer->draw_rect(x, y, w, row_h, 80); + } + char label[32]; + fill_label(index, label, sizeof(label)); + int t_w = renderer->get_text_width(label); + int t_h = renderer->get_line_height(); + int tx = x + (w - t_w) / 2; + int ty = y + (row_h - t_h) / 2; + renderer->draw_text(tx, ty, label, false, true); + index++; + cur_x = x + w + gap_w; + } + } + else + { + int usable_w = page_w - (c + 1) * gap_w; + int btn_w = usable_w / c; + for (int i = 0; i < c; ++i) + { + int x = gap_w + i * (btn_w + gap_w); bool selected = (index == overlay_selected); if (selected) { @@ -167,31 +237,15 @@ void EpubReader::render_overlay() { renderer->draw_rect(x, y, btn_w, row_h, 80); } - // 文本映射: - // 1:"<" 2:保留原编号 3:">" 4:"-5" 5:"-1" 6:"acc" 7:"+1" 8:"+5" 9:"确认" 10:"目录" 11:"书库" - char label[16]; - switch (index) - { - case 0: rt_snprintf(label, sizeof(label), "<"); break; - case 1: rt_snprintf(label, sizeof(label), "2"); break; - case 2: rt_snprintf(label, sizeof(label), ">"); break; - case 3: rt_snprintf(label, sizeof(label), "-5"); break; - case 4: rt_snprintf(label, sizeof(label), "-1"); break; - case 5: rt_snprintf(label, sizeof(label), "%d", overlay_jump_acc); break; - case 6: rt_snprintf(label, sizeof(label), "+1"); break; - case 7: rt_snprintf(label, sizeof(label), "+5"); break; - case 8: rt_snprintf(label, sizeof(label), "确认"); break; - case 9: rt_snprintf(label, sizeof(label), "目录"); break; - case 10: rt_snprintf(label, sizeof(label), "书库"); break; - default: - break; - } + char label[32]; + fill_label(index, label, sizeof(label)); int t_w = renderer->get_text_width(label); int t_h = renderer->get_line_height(); int tx = x + (btn_w - t_w) / 2; int ty = y + (row_h - t_h) / 2; renderer->draw_text(tx, ty, label, false, true); index++; + } } } } @@ -218,11 +272,14 @@ void EpubReader::jump_pages(int delta) int spine_count = epub ? epub->get_spine_items_count() : 0; //获取章节总数 if (spine_count <= 0) return; - auto at_book_start = [&]() -> bool { + //检查是不是第一页 + auto at_book_start = [&]() -> bool + { return state.current_section == 0 && state.current_page == 0; }; - auto at_book_end = [&]() -> bool { - // 需要知道当前节页数;parser 非空时有效 + //检查是不是最后一页 + auto at_book_end = [&]() -> bool + { if (!parser) return false; return (state.current_section == spine_count - 1) && (state.current_page >= state.pages_in_current_section - 1); }; @@ -248,9 +305,19 @@ void EpubReader::jump_pages(int delta) prev(); if (!parser) { - //空则解析 + //空就解析 parse_and_layout_current_section(); } } } +} + +void EpubReader::overlay_cycle_full_refresh() +{ + screen_cycle_full_refresh_period(); +} + +int EpubReader::overlay_get_full_refresh_value() const +{ + return screen_get_full_refresh_period(); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index 1ceebe8..355278f 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -17,6 +17,13 @@ class EpubReader bool overlay_active = false; int overlay_selected = 0; // 0..10,共11个 int overlay_jump_acc = 0; // 覆盖层累积跳页值(可为负) + // 覆盖层中心属性模式:触控开关 或 全刷周期 + enum OverlayCenterMode { CENTER_TOUCH = 0, CENTER_FULL_REFRESH = 1 }; + OverlayCenterMode overlay_center_mode = CENTER_TOUCH; + // 触控开关当前状态(由上层同步) + bool overlay_touch_enabled = false; + // 全刷周期索引:0->5, 1->10, 2->20, 3->不刷新(0) + int overlay_fr_idx = 0; void parse_and_layout_current_section(); void render_overlay(); @@ -41,4 +48,12 @@ class EpubReader void overlay_add_jump(int d) { overlay_jump_acc += d; } void overlay_reset_jump() { overlay_jump_acc = 0; } int overlay_get_jump() const { return overlay_jump_acc; } + // 覆盖层中心属性控制 + void overlay_set_center_mode_touch() { overlay_center_mode = CENTER_TOUCH; } + void overlay_set_center_mode_full_refresh() { overlay_center_mode = CENTER_FULL_REFRESH; } + bool overlay_is_center_touch() const { return overlay_center_mode == CENTER_TOUCH; } + void overlay_set_touch_enabled(bool en) { overlay_touch_enabled = en; } + bool overlay_get_touch_enabled() const { return overlay_touch_enabled; } + void overlay_cycle_full_refresh(); + int overlay_get_full_refresh_value() const; }; \ No newline at end of file diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index d58ca7b..1750d5d 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -13,7 +13,34 @@ typedef enum } MainOption; static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” -static int full_refresh_period = 10; // 全刷周期次数,仅用于设置页显示 +// 全刷周期选项:5、10、20、不刷新(0) +static const int kFullRefreshOptions[] = {5, 10, 20, 0}; +static const int kFullRefreshOptionsCount = sizeof(kFullRefreshOptions) / sizeof(kFullRefreshOptions[0]); +static int full_refresh_idx = 1; // 默认10次 + +// 获取当前全刷周期值 +int screen_get_full_refresh_period() +{ + return kFullRefreshOptions[full_refresh_idx]; +} + +// 切换全刷周期(循环) +void screen_cycle_full_refresh_period() +{ + full_refresh_idx = (full_refresh_idx + 1) % kFullRefreshOptionsCount; // ?% 4 +} + +// 设置全刷周期索引 +void screen_set_full_refresh_idx(int idx) +{ + if (idx >= 0 && idx < kFullRefreshOptionsCount) full_refresh_idx = idx; +} + +// 获取当前全刷周期索引 +int screen_get_full_refresh_idx() +{ + return full_refresh_idx; +} // 设置页列表项 typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; @@ -254,7 +281,11 @@ static void render_settings_page(Renderer *renderer) renderer->draw_rect(item_x, y, item_w, item_h, 0); } char buf3[64]; - rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", full_refresh_period); + int fr_val = screen_get_full_refresh_period(); + if (fr_val == 0) + rt_snprintf(buf3, sizeof(buf3), "全刷周期:不刷新"); + else + rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", fr_val); { int t3_w = renderer->get_text_width(buf3); int tx = item_x + (item_w - t3_w) / 2; @@ -345,6 +376,13 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) render_settings_page(renderer); break; } + if (settings_selected_idx == SET_FULL_REFRESH) + { + // SELECT 在全刷周期项上为加操作(循环) + screen_cycle_full_refresh_period(); + render_settings_page(renderer); + break; + } if (settings_selected_idx == SET_CONFIRM) { // 由上层切回主页面 diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h index c97c3c4..a1b589d 100644 --- a/epdiy-epub/src/epub_screen.h +++ b/epdiy-epub/src/epub_screen.h @@ -21,4 +21,7 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw); // 设置页面交互与渲染;返回 true 表示确认并退出到主页面 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw); - +// 切换全刷周期(循环) +void screen_cycle_full_refresh_period(); +// 获取当前全刷周期值 +int screen_get_full_refresh_period(); \ No newline at end of file diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 651945d..fc534fc 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -122,6 +122,48 @@ void handleEpub(Renderer *renderer, UIAction action) if (reader->is_overlay_active()) { int sel = reader->get_overlay_selected(); + // 1/3:改变中心属性;2:执行当前属性(触控取反 / 全刷周期循环) + if (sel == 0) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + } + else if (sel == 2) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + + } + else if (sel == 1) + { + // 中心矩形:根据当前属性执行 + if (reader->overlay_is_center_touch()) + { + bool cur = touch_controls ? touch_controls->isTouchEnabled() : false; + if (touch_controls) + { + touch_controls->setTouchEnable(!cur); + if (!cur) touch_controls->powerOnTouch(); else touch_controls->powerOffTouch(); + } + reader->overlay_set_touch_enabled(!cur); + } + else + { + reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/不刷新 之间循环 + } + } if (sel == 9) //目录 { ui_state = SELECTING_TABLE_CONTENTS; @@ -197,6 +239,10 @@ void handleEpub(Renderer *renderer, UIAction action) case UPGLIDE: // 激活阅读页下半屏覆盖操作层 reader->start_overlay(); + // 默认中心属性为触控开关,初始同步当前触控状态 + reader->overlay_set_center_mode_touch(); + if (touch_controls) + reader->overlay_set_touch_enabled(touch_controls->isTouchEnabled()); break; case NONE: default: From 019e58e2f555dad201ef3dc8593757d54e0d0b8c Mon Sep 17 00:00:00 2001 From: smiling boy Date: Thu, 15 Jan 2026 16:33:03 +0800 Subject: [PATCH 17/27] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=85=A8=E5=88=B7=E5=91=A8=E6=9C=9F=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 2 +- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 2 +- epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c | 2 +- epdiy-epub/src/boards/display_dbi/epd_display.c | 9 +-------- epdiy-epub/src/epub_screen.cpp | 9 +++++++-- epdiy-epub/src/main.cpp | 4 +++- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index fa87498..f5e572c 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -159,7 +159,7 @@ void EpubReader::render_overlay() { int v = overlay_get_full_refresh_value(); if (v == 0) - rt_snprintf(label, cap, "全刷周期:不刷新"); + rt_snprintf(label, cap, "全刷周期:每次"); else rt_snprintf(label, cap, "全刷周期:%d次", v); } diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index 355278f..a5a71b0 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -22,7 +22,7 @@ class EpubReader OverlayCenterMode overlay_center_mode = CENTER_TOUCH; // 触控开关当前状态(由上层同步) bool overlay_touch_enabled = false; - // 全刷周期索引:0->5, 1->10, 2->20, 3->不刷新(0) + // 全刷周期索引:0->5, 1->10, 2->20, 3->每次(0) int overlay_fr_idx = 0; void parse_and_layout_current_section(); diff --git a/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c b/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c index 0d75d1d..eb28fd1 100644 --- a/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c +++ b/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c @@ -2,7 +2,7 @@ #include "epd_configs.h" #include "mem_section.h" #include "string.h" -#if defined(LCD_USING_OPM060D) +#if defined(LCD_USING_EPD_YZC085_V100) || defined(LCD_USING_EPD_YZC146_V100) #ifndef EPD_WAVEFORM_USE_BIN // 8bit lookup table for the current frame (high 4 bits: old data, low 4 bits: new data). diff --git a/epdiy-epub/src/boards/display_dbi/epd_display.c b/epdiy-epub/src/boards/display_dbi/epd_display.c index cd32c84..445ecd1 100644 --- a/epdiy-epub/src/boards/display_dbi/epd_display.c +++ b/epdiy-epub/src/boards/display_dbi/epd_display.c @@ -583,15 +583,8 @@ L1_RET_CODE_SECT(epd_codes, static void LCD_WriteMultiplePixels(LCDC_HandleTypeD mode = EPD_DRAW_MODE_PARTIAL; } - if (reflesh_times % PART_DISP_TIMES == 0) { - frame_times = epd_wave_table_get_frames(temperature, EPD_DRAW_MODE_FULL); - reflesh_times = 0; - } else { - frame_times = epd_wave_table_get_frames(temperature, EPD_DRAW_MODE_PARTIAL); - } - reflesh_times++; + frame_times = epd_wave_table_get_frames(temperature, mode); - CopyToMixedGrayBuffer(hlcdc, RGBCode, Xpos0, Ypos0, Xpos1, Ypos1); LOG_I("Convert layer data take=%d(ms) \r\n", rt_tick_get() - start_tick); diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index 1750d5d..fbfdc7e 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -3,6 +3,10 @@ extern TouchControls *touch_controls; +extern "C" +{ + extern void set_part_disp_times(int val); +} // 主页面选项 typedef enum @@ -13,7 +17,7 @@ typedef enum } MainOption; static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” -// 全刷周期选项:5、10、20、不刷新(0) +// 全刷周期选项:5、10、20、每次(0) static const int kFullRefreshOptions[] = {5, 10, 20, 0}; static const int kFullRefreshOptionsCount = sizeof(kFullRefreshOptions) / sizeof(kFullRefreshOptions[0]); static int full_refresh_idx = 1; // 默认10次 @@ -283,7 +287,7 @@ static void render_settings_page(Renderer *renderer) char buf3[64]; int fr_val = screen_get_full_refresh_period(); if (fr_val == 0) - rt_snprintf(buf3, sizeof(buf3), "全刷周期:不刷新"); + rt_snprintf(buf3, sizeof(buf3), "全刷周期:每次"); else rt_snprintf(buf3, sizeof(buf3), "全刷周期:%d 次", fr_val); { @@ -380,6 +384,7 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) { // SELECT 在全刷周期项上为加操作(循环) screen_cycle_full_refresh_period(); + set_part_disp_times(screen_get_full_refresh_period()); render_settings_page(renderer); break; } diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index fc534fc..618e3c7 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -89,6 +89,7 @@ typedef enum { OPTION_ENTER_SETTINGS // 进入设置 -> 打印 3 } MainOption; void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw); + void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -161,7 +162,8 @@ void handleEpub(Renderer *renderer, UIAction action) } else { - reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/不刷新 之间循环 + reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/每次(0) 之间循环 + set_part_disp_times(reader->overlay_get_full_refresh_value()); } } if (sel == 9) //目录 From fb83ba5c4b8a18b4b28ccf4e35caa00a3b17dddc Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 16 Jan 2026 14:05:04 +0800 Subject: [PATCH 18/27] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=EF=BC=9A=20=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E9=98=85=E8=AF=BB=E8=BF=9B=E5=BA=A6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=A1=B5=E9=9D=A2=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E7=BC=BA=E9=99=B7=EF=BC=8C=E5=AE=8C=E5=96=84=E7=BB=A7=E7=BB=AD?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 15 +++ .../boards/controls/SF32_TouchControls.cpp | 44 -------- epdiy-epub/src/epub_screen.cpp | 52 ++++++--- epdiy-epub/src/epub_screen.h | 2 +- epdiy-epub/src/main.cpp | 103 +++++++++--------- 5 files changed, 102 insertions(+), 114 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index f5e572c..65b2037 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -112,6 +112,21 @@ void EpubReader::render() parser->render_page(state.current_page, renderer, epub); ulog_d(TAG, "rendered page %d of %d", state.current_page, parser->get_page_count()); ulog_d(TAG, "after render: %d", heap_free_size()); + // 章节进度 + if (state.pages_in_current_section > 0) + { + char buf[32]; + rt_snprintf(buf, sizeof(buf), "%d页/%d页", state.current_page + 1, state.pages_in_current_section); + int page_w = renderer->get_page_width(); + int page_h = renderer->get_page_height(); + int text_w = renderer->get_text_width(buf); + int text_h = renderer->get_line_height(); + int x = (page_w - text_w) / 2; + int reserved_bottom = renderer->get_line_height() + 4; + const int progress_up = 6; // 上抬 + int y = page_h - text_h - 10 + reserved_bottom - progress_up; + renderer->draw_text(x, y, buf, false, true); + } // 绘制半屏覆盖操作层 if (overlay_active) { diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index bef4851..e1011bb 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -202,49 +202,5 @@ void SF32_TouchControls::powerOnTouch() } void SF32_TouchControls::renderPressedState(Renderer *renderer, UIAction action, bool state) { - renderer->set_margin_top(0); - switch (action) - { - case DOWN: - { - if (state) - { - renderer->fill_triangle(80, 20, 75, 6, 85, 6, 0); - } - else - { - renderer->fill_triangle(81, 19, 76, 7, 86, 7, 255); - } - //renderer->flush_area(76, 6, 10, 15); - break; - } - case UP: - { - if (state) - { - renderer->fill_triangle(220, 6, 220 - 5, 20, 220 + 5, 20, 0); - } - else - { - renderer->fill_triangle(221, 7, 221 - 5, 19, 221 + 5, 19, 255); - } - //renderer->flush_area(195, 225, 10, 15); - } - break; - case SELECT: - { - uint16_t x_circle = (ui_button_width * 2 + 60) + (ui_button_width / 2) + 9; - renderer->fill_circle(x_circle, 15, 5, 0); - //renderer->flush_area(x_circle - 3, 12, 6, 6); - // TODO - this causes a stack overflow when select is picked - // renderPressedState(renderer, last_action, false); - } - break; - case LAST_INTERACTION: - case NONE: - break; - default: - break; - } renderer->set_margin_top(35); } \ No newline at end of file diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index fbfdc7e..b06ae54 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -1,3 +1,5 @@ + +#include "EpubList/EpubList.h" #include "epub_screen.h" #include @@ -8,6 +10,9 @@ extern "C" extern void set_part_disp_times(int val); } +// 最近一次真实打开并阅读的书本索引(由 main.cpp 维护) +extern int g_last_read_index; + // 主页面选项 typedef enum { @@ -50,24 +55,24 @@ int screen_get_full_refresh_idx() typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; static int settings_selected_idx = 0; -// 超时关机:1/3/5/7/10/不关机(0) -static const int kTimeoutOptions[] = {1, 3, 5, 7, 10, 0}; +// 超时关机:5/10/30分钟、1小时、不关机(0) +static const int kTimeoutOptions[] = {5, 10, 30, 60, 0}; // 单位:分钟,0为不关机 static const int kTimeoutOptionsCount = sizeof(kTimeoutOptions) / sizeof(kTimeoutOptions[0]); -static int timeout_shutdown_hours = 5; // 运行时关机超时(小时),0 表示不关机 -static int timeout_idx = -1; // 指向 kTimeoutOptions 的索引 +static int timeout_shutdown_minutes = 30; // 默认30分钟 +static int timeout_idx = -1; // -static int find_timeout_idx(int hours) +static int find_timeout_idx(int minutes) { for (int i = 0; i < kTimeoutOptionsCount; ++i) { - if (kTimeoutOptions[i] == hours) return i; + if (kTimeoutOptions[i] == minutes) return i; } - return 2; // 默认索引:5小时 + return 2; // 默认索引:30分钟 } static void adjust_timeout(bool increase) { - if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_minutes); if (increase) { timeout_idx = (timeout_idx + 1) % kTimeoutOptionsCount; @@ -76,19 +81,19 @@ static void adjust_timeout(bool increase) { timeout_idx = (timeout_idx - 1 + kTimeoutOptionsCount) % kTimeoutOptionsCount; } - timeout_shutdown_hours = kTimeoutOptions[timeout_idx]; + timeout_shutdown_minutes = kTimeoutOptions[timeout_idx]; } -void screen_init(int default_timeout_hours) +void screen_init(int default_timeout_minutes) { - timeout_shutdown_hours = default_timeout_hours; - timeout_idx = find_timeout_idx(timeout_shutdown_hours); + timeout_shutdown_minutes = default_timeout_minutes; + timeout_idx = find_timeout_idx(timeout_shutdown_minutes); } -int screen_get_timeout_shutdown_hours() +int screen_get_timeout_shutdown_minutes() { - if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_hours); - return timeout_shutdown_hours; + if (timeout_idx < 0) timeout_idx = find_timeout_idx(timeout_shutdown_minutes); + return timeout_shutdown_minutes; } int screen_get_main_selected_option() @@ -133,10 +138,14 @@ static void render_main_page(Renderer *renderer) int mid_w = right_x - margin_side - mid_x; const char *opt_text = NULL; + extern EpubListState epub_list_state; + bool has_continue_reading = (epub_list_state.num_epubs > 0 && g_last_read_index >= 0 && g_last_read_index < epub_list_state.num_epubs); switch (main_option) { case OPTION_OPEN_LIBRARY: opt_text = "打开书库"; break; - case OPTION_CONTINUE_READING: opt_text = "继续阅读"; break; + case OPTION_CONTINUE_READING: + opt_text = has_continue_reading ? "继续阅读" : "无阅读记录"; + break; case OPTION_ENTER_SETTINGS: opt_text = "进入设置"; break; } int opt_w = renderer->get_text_width(opt_text); @@ -208,6 +217,7 @@ static void render_settings_page(Renderer *renderer) // 1) 触控开关 int item_w = page_w - margin_lr * 2 - arrow_col_w * 2; // 为左右箭头列留边 int item_x = margin_lr + arrow_col_w; + if (settings_selected_idx == SET_TOUCH) { const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); @@ -237,6 +247,7 @@ static void render_settings_page(Renderer *renderer) y += item_h + gap; // 2) 超时关机 + if (settings_selected_idx == SET_TIMEOUT) { const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); @@ -252,13 +263,17 @@ static void render_settings_page(Renderer *renderer) renderer->draw_rect(item_x, y, item_w, item_h, 0); } char buf2[64]; - if (timeout_shutdown_hours == 0) + if (timeout_shutdown_minutes == 0) { rt_snprintf(buf2, sizeof(buf2), "超时关机:不关机"); } + else if (timeout_shutdown_minutes < 60) + { + rt_snprintf(buf2, sizeof(buf2), "超时关机:%d分钟", timeout_shutdown_minutes); + } else { - rt_snprintf(buf2, sizeof(buf2), "超时关机:%d 小时", timeout_shutdown_hours); + rt_snprintf(buf2, sizeof(buf2), "超时关机:%d小时", timeout_shutdown_minutes / 60); } { int t2_w = renderer->get_text_width(buf2); @@ -270,6 +285,7 @@ static void render_settings_page(Renderer *renderer) y += item_h + gap; // 3) 全刷周期 + if (settings_selected_idx == SET_FULL_REFRESH) { const char *lt = "<"; int lt_w = renderer->get_text_width(lt); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h index a1b589d..d3f1646 100644 --- a/epdiy-epub/src/epub_screen.h +++ b/epdiy-epub/src/epub_screen.h @@ -11,7 +11,7 @@ void screen_init(int default_timeout_hours); // 获取当前关机超时设置(小时;0 表示不关机) -int screen_get_timeout_shutdown_hours(); +int screen_get_timeout_shutdown_minutes(); // 获取当前主页面选中的选项(0: 打开书库, 1: 继续阅读, 2: 进入设置) int screen_get_main_selected_option(); diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 618e3c7..56971ce 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -36,25 +36,20 @@ extern "C" const char *TAG = "main"; -typedef enum -{ +typedef enum { MAIN_PAGE, // 新主页面 - SELECTING_EPUB, // 电子书列表页面(书库) + SELECTING_EPUB, // 电子书列表页面(书库) SELECTING_TABLE_CONTENTS, // 电子书目录页面 - READING_EPUB, // 阅读页面 - SETTINGS_PAGE // 通用功能设置页面 -} UIState; -typedef enum -{ - MAIN_MENU, - WELCOME_PAGE, - LOW_POWER_PAGE, - CHARGING_PAGE -} UIState2; + READING_EPUB, // 阅读页面 + SETTINGS_PAGE, // 通用功能设置页面 + WELCOME_PAGE, // 欢迎页面 + LOW_POWER_PAGE, // 低电量页面 + CHARGING_PAGE, // 充电页面 + SHUTDOWN_PAGE // 关机页面 +} AppUIState; // 默认显示新主页面,而非书库页面 -UIState ui_state = MAIN_PAGE; -UIState2 lowpower_ui_state = MAIN_MENU; +AppUIState ui_state = MAIN_PAGE; // the state data for the epub list and reader EpubListState epub_list_state; // the state data for the epub index list @@ -96,6 +91,8 @@ void handleEpub(Renderer *renderer, UIAction action) { reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); reader->load(); + // 记录最近一次进入阅读的书籍索引 + g_last_read_index = epub_list_state.selected_item; } switch (action) { @@ -169,6 +166,7 @@ void handleEpub(Renderer *renderer, UIAction action) if (sel == 9) //目录 { ui_state = SELECTING_TABLE_CONTENTS; + renderer->set_margin_bottom(0); reader->stop_overlay(); delete reader; reader = nullptr; @@ -191,6 +189,7 @@ void handleEpub(Renderer *renderer, UIAction action) else if (sel == 10) //书库 { ui_state = SELECTING_EPUB; + renderer->set_margin_bottom(0); reader->stop_overlay(); renderer->clear_screen(); delete reader; @@ -223,7 +222,6 @@ void handleEpub(Renderer *renderer, UIAction action) else { // switch back to main screen - ui_state = SELECTING_EPUB; renderer->clear_screen(); // clear the epub reader away delete reader; @@ -233,7 +231,8 @@ void handleEpub(Renderer *renderer, UIAction action) { epub_list = new EpubList(renderer, epub_list_state); } - handleEpubList(renderer, NONE, true); + renderer->set_margin_bottom(0); + back_to_main_page(); return; } @@ -405,6 +404,8 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); reader->set_state_section(contents->get_selected_toc()); reader->load(); + // 记录最近一次进入阅读的书籍索引 + g_last_read_index = epub_list_state.selected_item; delete contents; handleEpub(renderer, NONE); return; @@ -632,10 +633,21 @@ void handleUserInteraction(Renderer *renderer, UIAction ui_action, bool needs_re ui_state = SETTINGS_PAGE; (void)handleSettingsPage(renderer, NONE, true); } - else if (ui_action == SELECT && screen_get_main_selected_option() == 1) //切换到阅读页面 + else if (ui_action == SELECT && screen_get_main_selected_option() == 1) //继续阅读 { - // ui_state = READING_EPUB; - // handleEpub(renderer, NONE); + // 判断是否有继续阅读记录 + if (!(g_last_read_index >= 0 && g_last_read_index < epub_list_state.num_epubs)) { + return; // 无记录,忽略 + } + // 有记录,恢复阅读 + if (reader) { delete reader; reader = nullptr; } + int last_idx = g_last_read_index; + EpubListItem &last_item = epub_list_state.epub_list[last_idx]; + reader = new EpubReader(last_item, renderer); + reader->set_state_section(last_item.current_section); + reader->load(); + ui_state = READING_EPUB; + handleEpub(renderer, NONE); } else if (ui_action == SELECT && screen_get_main_selected_option() == 0) //切换到书库页面 { @@ -693,39 +705,29 @@ const char* getCurrentPageName() { } //回到主界面接口 void back_to_main_page() -{ - if (ui_state == MAIN_PAGE) - { - rt_kprintf("已经在主页面,无需返回\n"); - return; - } - lowpower_ui_state = MAIN_MENU; - if (ui_state == SELECTING_TABLE_CONTENTS) - { - if (contents) - { - delete contents; - contents = nullptr; - } +{ + if (ui_state == MAIN_PAGE) + { + rt_kprintf("已经在主页面,无需返回\n"); + return; + } + if (ui_state == SELECTING_TABLE_CONTENTS) + { + if (contents) + { + delete contents; + contents = nullptr; } } bool hydrate_success = renderer->hydrate(); - renderer->reset(); - renderer->set_margin_top(35); - renderer->set_margin_left(10); - renderer->set_margin_right(10); - // 返回新的主页面,不再默认进入书库页面 - ui_state = MAIN_PAGE; - handleUserInteraction(renderer, NONE, true); - - if (battery) - { - draw_charge_status(renderer, battery); - draw_battery_level(renderer, battery->get_voltage(), battery->get_percentage()); - } - touch_controls->render(renderer); - renderer->flush_display(); + renderer->reset(); + renderer->set_margin_top(35); + renderer->set_margin_left(10); + renderer->set_margin_right(10); + // 返回新的主页面,不再默认进入书库页面 + ui_state = MAIN_PAGE; + handleUserInteraction(renderer, NONE, true); if (battery) { @@ -933,8 +935,7 @@ void main_task(void *param) // 初始化屏幕模块默认关机超时 screen_init(TIMEOUT_SHUTDOWN_TIME); - while ((screen_get_timeout_shutdown_hours() == 0) || - (rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 * screen_get_timeout_shutdown_hours())) // 按设置的小时数无操作自动关机;0为不关机 + while ((rt_tick_get_millisecond() - last_user_interaction < 60 * 1000 * 60 * TIMEOUT_SHUTDOWN_TIME)) // 5小时 { // 检查是否超过设置分钟无操作,如果是在欢迎页面、充电页面或低电量页面则不跳转 From a63be2f7ce07ed57eb0beb920d1fab7c622bf144 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 16 Jan 2026 14:14:53 +0800 Subject: [PATCH 19/27] =?UTF-8?q?=E5=BC=80=E5=90=AF=E4=BD=8E=E5=8A=9F?= =?UTF-8?q?=E8=80=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 56971ce..b517b4e 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -1067,7 +1067,7 @@ extern "C" int main() { // dump out the epub list state - rt_pm_request(PM_SLEEP_MODE_IDLE); + //rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); From 63d71f88ed25c2bf4f9384f2b28cb61973fa6eae Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 16 Jan 2026 18:55:56 +0800 Subject: [PATCH 20/27] =?UTF-8?q?1.=E4=BF=AE=E6=94=B9=E7=B4=AF=E7=A7=AF?= =?UTF-8?q?=E8=B7=B3=E9=A1=B5=E4=BD=BF=E7=94=A8=E9=80=BB=E8=BE=91=202.?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B9=A6=E5=BA=93=E4=BB=A5=E5=8F=8A=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E9=A1=B5=E7=9A=84up=EF=BC=8Cdown=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 29 ++++++- epdiy-epub/lib/Epub/EpubList/EpubReader.h | 9 +- epdiy-epub/src/main.cpp | 95 ++++++++++++++++----- 3 files changed, 109 insertions(+), 24 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 65b2037..8e0a4e5 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -183,7 +183,15 @@ void EpubReader::render_overlay() case 2: rt_snprintf(label, cap, ">"); break; case 3: rt_snprintf(label, cap, "-5"); break; case 4: rt_snprintf(label, cap, "-1"); break; - case 5: rt_snprintf(label, cap, "%d", overlay_jump_acc); break; + // 第六格显示:x/n 页 + case 5: + { + int total = state.pages_in_current_section; + if (total <= 0 && parser) total = parser->get_page_count(); + if (total <= 0) total = 1; + rt_snprintf(label, cap, "%d/%d", overlay_target_page, total); + break; + } case 6: rt_snprintf(label, cap, "+1"); break; case 7: rt_snprintf(label, cap, "+5"); break; case 8: rt_snprintf(label, cap, "确认"); break; @@ -335,4 +343,23 @@ void EpubReader::overlay_cycle_full_refresh() int EpubReader::overlay_get_full_refresh_value() const { return screen_get_full_refresh_period(); +} + +void EpubReader::overlay_set_target_page(int p) +{ + if (p < 1) p = 1; + int maxp = state.pages_in_current_section; + if (maxp <= 0 && parser) + { + maxp = parser->get_page_count(); + } + if (maxp <= 0) maxp = 1; + if (p > maxp) p = maxp; + overlay_target_page = p; +} + +void EpubReader::overlay_adjust_target_page(int d) +{ + int p = overlay_target_page + d; + overlay_set_target_page(p); } \ No newline at end of file diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.h b/epdiy-epub/lib/Epub/EpubList/EpubReader.h index a5a71b0..d65ef72 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.h +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.h @@ -17,6 +17,8 @@ class EpubReader bool overlay_active = false; int overlay_selected = 0; // 0..10,共11个 int overlay_jump_acc = 0; // 覆盖层累积跳页值(可为负) + // 覆盖层目标页(当前章节内的页,1-based) + int overlay_target_page = 1; // 覆盖层中心属性模式:触控开关 或 全刷周期 enum OverlayCenterMode { CENTER_TOUCH = 0, CENTER_FULL_REFRESH = 1 }; OverlayCenterMode overlay_center_mode = CENTER_TOUCH; @@ -38,16 +40,19 @@ class EpubReader void render(); void set_state_section(uint16_t current_section); // 覆盖层控制 - void start_overlay() { overlay_active = true; overlay_selected = 0; overlay_jump_acc = 0; } + void start_overlay() { overlay_active = true; overlay_selected = 0; overlay_jump_acc = 0; overlay_target_page = state.current_page + 1; } void stop_overlay() { overlay_active = false; } bool is_overlay_active() const { return overlay_active; } void overlay_move_left(); void overlay_move_right(); int get_overlay_selected() const { return overlay_selected; } // 覆盖层跳页累积控制 - void overlay_add_jump(int d) { overlay_jump_acc += d; } void overlay_reset_jump() { overlay_jump_acc = 0; } int overlay_get_jump() const { return overlay_jump_acc; } + // 覆盖层目标页控制 + void overlay_set_target_page(int p); + void overlay_adjust_target_page(int d); + int overlay_get_target_page() const { return overlay_target_page; } // 覆盖层中心属性控制 void overlay_set_center_mode_touch() { overlay_center_mode = CENTER_TOUCH; } void overlay_set_center_mode_full_refresh() { overlay_center_mode = CENTER_FULL_REFRESH; } diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index b517b4e..c7031be 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -178,11 +178,11 @@ void handleEpub(Renderer *renderer, UIAction action) } else if (sel == 8) //确认:1.按第六格累积值跳页 { - int delta = reader->overlay_get_jump(); - if (delta != 0) - { - reader->jump_pages(delta); - } + // 跳转到第六格显示的目标页 + int target = reader->overlay_get_target_page(); + if (target < 1) target = 1; + extern EpubListState epub_list_state; + epub_list_state.epub_list[epub_list_state.selected_item].current_page = (uint16_t)(target - 1); reader->overlay_reset_jump(); reader->stop_overlay(); } @@ -203,19 +203,19 @@ void handleEpub(Renderer *renderer, UIAction action) } else if (sel == 3) { - reader->overlay_add_jump(-5); + reader->overlay_adjust_target_page(-5); } else if (sel == 4) { - reader->overlay_add_jump(-1); + reader->overlay_adjust_target_page(-1); } else if (sel == 6) { - reader->overlay_add_jump(1); + reader->overlay_adjust_target_page(1); } else if (sel == 7) { - reader->overlay_add_jump(5); + reader->overlay_adjust_target_page(5); } } @@ -272,15 +272,31 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red case UP: if (toc_bottom_mode) { - toc_bottom_idx = (toc_bottom_idx + 2) % 3; // 左移 + // 底部模式下:UP 向左移动;若已在最左(上一页),则返回当前页目录的最后一项 + if (toc_bottom_idx > 0) + { + toc_bottom_idx--; + } + else + { + int per_page = 6; + int start_idx = (epub_index_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + int count = contents->get_items_count(); + if (end_idx >= count) end_idx = count - 1; + toc_bottom_mode = false; + epub_index_state.selected_item = end_idx; + } } else { + // 若处于当前页第一个条目,UP 切换到底部按钮模式并选择“下一页” int per_page = 6; int start_idx = (epub_index_state.selected_item / per_page) * per_page; if (contents->get_items_count() > 0 && epub_index_state.selected_item == start_idx) { toc_bottom_mode = true; + toc_bottom_idx = 2; // 下一页 } else { @@ -291,7 +307,18 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red case DOWN: if (toc_bottom_mode) { - toc_bottom_idx = (toc_bottom_idx + 1) % 3; // 右移 + // 底部模式下:DOWN 向右移动;若已在最右(下一页),则返回当前页目录的第一项 + if (toc_bottom_idx < 2) + { + toc_bottom_idx++; + } + else + { + int per_page = 6; + int start_idx = (epub_index_state.selected_item / per_page) * per_page; + toc_bottom_mode = false; + epub_index_state.selected_item = start_idx; + } } else { @@ -300,9 +327,11 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red int end_idx = start_idx + per_page - 1; int count = contents->get_items_count(); if (end_idx >= count) end_idx = count - 1; + // 若处于当前页最后一个条目,DOWN 切换到底部按钮模式并选择“上一页” if (count > 0 && epub_index_state.selected_item == end_idx) { toc_bottom_mode = true; + toc_bottom_idx = 0; // 上一页 } else { @@ -382,7 +411,7 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red if (epub_index_state.selected_item < 0) epub_index_state.selected_item = 0; contents->set_needs_redraw(); } - toc_bottom_mode = false; + // 保持底部模式,允许连续翻页 } else if (toc_bottom_idx == 2) { @@ -394,7 +423,7 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red epub_index_state.selected_item = count - 1; contents->set_needs_redraw(); } - toc_bottom_mode = false; + // 保持底部模式,允许连续翻页 } } else @@ -447,8 +476,20 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) case UP: if (library_bottom_mode) { - // UP 表示向左选择 - library_bottom_idx = (library_bottom_idx + 2) % 3; + // 底部模式下:UP 向左移动;若已在最左(上一页),则返回当前页的列表最后一项 + if (library_bottom_idx > 0) + { + library_bottom_idx--; + } + else + { + int per_page = 4; + int start_idx = (epub_list_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; + library_bottom_mode = false; + epub_list_state.selected_item = end_idx; + } } else { @@ -458,6 +499,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == start_idx) { library_bottom_mode = true; + library_bottom_idx = 2; // 下一页 } else { @@ -468,8 +510,20 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) case DOWN: if (library_bottom_mode) { - // DOWN 表示向右选择 - library_bottom_idx = (library_bottom_idx + 1) % 3; + // 底部模式下:DOWN 向右移动;若已在最右(下一页),则返回当前页的列表第一项 + if (library_bottom_idx < 2) + { + library_bottom_idx++; + } + else + { + int per_page = 4; + int start_idx = (epub_list_state.selected_item / per_page) * per_page; + int end_idx = start_idx + per_page - 1; + if (end_idx >= epub_list_state.num_epubs) end_idx = epub_list_state.num_epubs - 1; + library_bottom_mode = false; + epub_list_state.selected_item = start_idx; + } } else { @@ -481,6 +535,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (epub_list_state.num_epubs > 0 && epub_list_state.selected_item == end_idx) { library_bottom_mode = true; + library_bottom_idx = 0; // 上一页 } else { @@ -510,8 +565,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) if (epub_list_state.selected_item < 0) epub_list_state.selected_item = 0; epub_list->set_needs_redraw(); } - // 切回条目选择模式 - library_bottom_mode = false; + } else if (library_bottom_idx == 2) { @@ -523,8 +577,7 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) epub_list_state.selected_item = epub_list_state.num_epubs - 1; epub_list->set_needs_redraw(); } - // 切回条目选择模式 - library_bottom_mode = false; + } } else From 0b7499bb44187239798e725cf483e42868f620d2 Mon Sep 17 00:00:00 2001 From: minjiezhong Date: Tue, 20 Jan 2026 11:19:36 +0800 Subject: [PATCH 21/27] =?UTF-8?q?1=E3=80=82=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E6=89=80=E6=9C=89=E9=A1=B5=E9=9D=A2=E7=9A=84=E8=A7=A6=E6=8E=A7?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/lib/Epub/EpubList/EpubReader.cpp | 2 +- epdiy-epub/project/Kconfig.proj | 4 +- epdiy-epub/src/boards/controls/Actions.h | 3 + .../boards/controls/SF32_TouchControls.cpp | 349 ++++++++++++++--- .../src/boards/controls/SF32_TouchControls.h | 3 + epdiy-epub/src/epub_screen.cpp | 89 ++++- epdiy-epub/src/epub_screen.h | 2 +- epdiy-epub/src/main.cpp | 359 ++++++++++-------- 8 files changed, 580 insertions(+), 231 deletions(-) diff --git a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp index 8e0a4e5..201478f 100644 --- a/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp +++ b/epdiy-epub/lib/Epub/EpubList/EpubReader.cpp @@ -337,7 +337,7 @@ void EpubReader::jump_pages(int delta) void EpubReader::overlay_cycle_full_refresh() { - screen_cycle_full_refresh_period(); + screen_cycle_full_refresh_period(true); } int EpubReader::overlay_get_full_refresh_value() const diff --git a/epdiy-epub/project/Kconfig.proj b/epdiy-epub/project/Kconfig.proj index 271c461..3a0e844 100644 --- a/epdiy-epub/project/Kconfig.proj +++ b/epdiy-epub/project/Kconfig.proj @@ -51,7 +51,9 @@ if !BSP_USING_BUILT_LCD config TSC_USING_GT967 bool default n - + config TSC_USING_GT967 + bool + default n choice prompt "Custom LCD driver" default LCD_USING_EPD_YZC085_V100 if BSP_USING_BOARD_SF32_OED_EPD_V11 diff --git a/epdiy-epub/src/boards/controls/Actions.h b/epdiy-epub/src/boards/controls/Actions.h index 8e83835..5e22d6b 100644 --- a/epdiy-epub/src/boards/controls/Actions.h +++ b/epdiy-epub/src/boards/controls/Actions.h @@ -9,6 +9,9 @@ typedef enum DOWN, SELECT, UPGLIDE, // 长按触发的上滑操作,用于阅读页半屏操作覆盖 + PREV_OPTION, // 上一选项(用于列表选择) + NEXT_OPTION, // 下一选项(用于列表选择) + SELECT_BOX, // 选择框(用于触控选择) LAST_INTERACTION, MSG_DRAW_LOW_POWER_PAGE, MSG_DRAW_CHARGE_PAGE, diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index e1011bb..c2a0f15 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -12,6 +12,21 @@ volatile int g_touch_last_settings_row = -1; volatile int g_touch_last_settings_dir = 0; +extern int settings_selected_idx; +extern AppUIState ui_state; +extern int book_index; +extern bool library_bottom_mode; +extern int library_bottom_idx; +extern int toc_index; +extern int toc_bottom_idx; +extern bool toc_bottom_mode;//控制目录页面中功能选项的开关 +static int last_clicked_toc_index = -1; // -1 表示没有目录项被选中 +// 添加一个变量来记录上次点击的书籍索引 +static int last_clicked_book_index = -1; // -1 表示没有书籍被选中 +static bool waiting_for_confirmation = false; // 是否正在等待确认 +extern int touch_sel; +extern EpubReader *reader; + rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { @@ -91,63 +106,301 @@ rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) UIAction action = NONE; // LOG_I("TOUCH", "Received touch event %d,%d", x, y); // 主页面底部按键区域:左"<"、右">"、中间文本框 - int page_w = instance->renderer->get_page_width(); - int page_h = instance->renderer->get_page_height(); - int margin_side = 10; - int margin_bottom = 60; - int rect_w = 80; - int rect_h = 40; - int y_bottom = page_h - rect_h - margin_bottom; - int left_x = margin_side; - int right_x = page_w - rect_w - margin_side; - int mid_x = left_x + rect_w + margin_side; - int mid_w = right_x - margin_side - mid_x; - - if (x >= left_x && x <= left_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) +switch (ui_state) +{ + case MAIN_PAGE://主页面 + if (x >= 10 && x <= 80 && y >= 950 && y <= 1000) { rt_kprintf("Touch left < \n"); - action = UP; + action = UP; // 对应 KEY3 功能 } - - else if (x >= right_x && x <= right_x + rect_w && y >= y_bottom && y <= y_bottom + rect_h) + else if (x >= 650 && x <= 750 && y >= 950 && y <= 1000) { - action = DOWN; + action = DOWN; // 对应 KEY1 功能 rt_kprintf("Touch right > \n"); } - - // 设置页面每行左右箭头触控区域(与设置页布局一致) - if (action == NONE) - { - int page_w2 = instance->renderer->get_page_width(); - int margin_lr2 = 6; - int item_h2 = 100; - int gap2 = 54; - int arrow_col_w2 = 40; - int lh2 = instance->renderer->get_line_height(); - int y_start2 = 40 + lh2 + 20; - g_touch_last_settings_row = -1; - g_touch_last_settings_dir = 0; - for (int row = 0; row < 3; ++row) - { - int ry = y_start2 + row * (item_h2 + gap2); - int left_ax = margin_lr2; - int right_ax = page_w2 - margin_lr2 - arrow_col_w2; - if (x >= left_ax && x <= left_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) - { + else if (x >= 250 && x <= 500 && y >= 950 && y <= 1000) + { + action = SELECT; // 对应 KEY2 功能 + rt_kprintf("Touch middle SELECT \n"); + } + break; + case SELECTING_EPUB://书库页面 + // 检查是否点击了功能控制按钮 + if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + { + library_bottom_mode = true; + library_bottom_idx = 0; + action = SELECT; + } + else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + { + library_bottom_mode = true; + library_bottom_idx = 1; + action = SELECT; + } + else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + { + library_bottom_mode = true; + library_bottom_idx = 2; + action = SELECT; + } + else + { + // 处理书籍选择区域 + int clicked_book_index = -1; + + if(x >= 10 && x <= 740 && y >= 60 && y <= 240) + { + clicked_book_index = 0; + } + else if(x >= 10 && x <= 740 && y >= 270 && y <= 450) + { + clicked_book_index = 1; + } + else if(x >= 10 && x <= 740 && y >= 470 && y <= 680) + { + clicked_book_index = 2; + } + else if(x >= 10 && x <= 740 && y >= 700 && y <= 900) + { + clicked_book_index = 3; + } + + // 如果点击了书籍区域 + if(clicked_book_index != -1) + { + // 判断是第一次点击还是第二次点击 + if(waiting_for_confirmation && last_clicked_book_index == clicked_book_index) + { + // 第二次点击:执行打开操作 + book_index = clicked_book_index; + library_bottom_mode = false; + rt_kprintf("Open book%d %d\n", book_index, book_index); + action = SELECT; + + // 重置状态 + waiting_for_confirmation = false; + last_clicked_book_index = -1; + } + else + { + // 第一次点击:选择书籍并等待确认 + book_index = clicked_book_index; + last_clicked_book_index = clicked_book_index; + waiting_for_confirmation = true; + action = SELECT_BOX; + rt_kprintf("Select book%d for confirmation, waiting for second click\n", book_index); + } + } + } + break; + case READING_EPUB: //阅读界面 + //翻页操作 + if(x >= 10 && x <= 200 && y >=10 && y <= 1010 && reader->is_overlay_active() == false) + { action = UP; - g_touch_last_settings_row = row; - g_touch_last_settings_dir = -1; // 左=减 - break; - } - if (x >= right_ax && x <= right_ax + arrow_col_w2 && y >= ry && y <= ry + item_h2) - { + } + else if(x >= 550 && x <= 750 && y >=10 && y <= 1010 && reader->is_overlay_active() == false) + { action = DOWN; - g_touch_last_settings_row = row; - g_touch_last_settings_dir = +1; // 右=加 - break; - } } - } + //点击正文,推出阅读设置 + if(x >= 10 && x <= 750 && y >=10 && y <= 630 && reader->is_overlay_active()) + { + touch_sel = 8; + action = SELECT; + } + + //阅读页面控制区域设置 + if(x >= 10 && x <= 250 && y >= 900 && y <= 960 && reader->is_overlay_active()) + { + touch_sel = 8; + action = SELECT; + } + else if(x >= 280 && x <= 480 && y >= 900 && y <= 960 && reader->is_overlay_active()) + { + touch_sel = 9; + action = SELECT; + } + else if(x >= 520 && x <= 750 && y >= 900 && y <= 960 && reader->is_overlay_active()) + { + touch_sel = 10; + action = SELECT; + } + else if(x >= 10 && x <= 150 && y >= 690 && y <= 750 && reader->is_overlay_active()) + { + touch_sel= 0; + rt_kprintf("Touch middle SELECT %d\n",touch_sel); + action = SELECT; + } + else if(x >= 170 && x <= 570 && y >= 690 && y <= 750 && reader->is_overlay_active()) + { + touch_sel= 1; + rt_kprintf("Touch middle SELECT %d\n",touch_sel); + action = SELECT; + } + else if(x >= 610 && x <= 750 && y >= 690 && y <= 750 && reader->is_overlay_active()) + { + touch_sel= 2; + rt_kprintf("Touch middle SELECT %d\n",touch_sel); + action = SELECT; + } + else if(x >= 10 && x <= 140 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 3;//跳转-5页 + action = SELECT; + } + else if(x >= 165 && x <=300 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 4;//跳转-1页 + action = SELECT; + } + else if(x >= 480 && x <= 570 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 6;//跳转+1页 + action = SELECT; + } + else if(x >= 620 && x <= 750 && y >= 790 && y <= 850 && reader->is_overlay_active()) + { + touch_sel = 7;//跳转5页 + action = SELECT; + } + + break; + case SELECTING_TABLE_CONTENTS: //目录界面 + if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + { + toc_bottom_mode = true; + toc_bottom_idx = 0; + action = SELECT; + } + else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + { + toc_bottom_mode = true; + toc_bottom_idx = 1; + action = SELECT; + } + else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + { + toc_bottom_mode = true; + toc_bottom_idx = 2; + action = SELECT; + } + else// 目录项选择区域 + { + int clicked_toc_index = -1; + + if(x >= 10 && x <= 750 && y >= 20 && y <= 170) + { + clicked_toc_index = 0; + } + else if(x >= 10 && x <= 750 && y >= 180 && y <= 310) + { + clicked_toc_index = 1; + } + else if(x >= 10 && x <= 750 && y >= 330 && y <= 450) + { + clicked_toc_index = 2; + } + else if(x >= 10 && x <= 750 && y >= 470 && y <= 590) + { + clicked_toc_index = 3; + } + else if(x >= 10 && x <= 750 && y >= 620 && y <= 750) + { + clicked_toc_index = 4; + } + else if(x >= 10 && x <= 750 && y >= 770 && y <= 890) + { + clicked_toc_index = 5; + } + // 如果点击了目录项区域 + if(clicked_toc_index != -1) + { + // 判断是第一次点击还是第二次点击 + if(waiting_for_confirmation && last_clicked_toc_index == clicked_toc_index) + { + // 第二次点击:执行打开操作 + toc_index = clicked_toc_index; + library_bottom_mode = false; + rt_kprintf("Open book%d %d\n", toc_index, toc_index); + action = SELECT; + + // 重置状态 + waiting_for_confirmation = false; + last_clicked_toc_index = -1; + } + else + { + // 第一次点击:选择目录项并等待确认 + toc_index = clicked_toc_index; + last_clicked_toc_index = clicked_toc_index; + waiting_for_confirmation = true; + action = SELECT_BOX; + } + } + } + + break; + case SETTINGS_PAGE: // 设置页面 + // 设置页面每行左右箭头触控区域(与设置页布局一致) + if (x >= 100 && x <= 650 && y >= 160 && y <= 260) + { + settings_selected_idx = SET_TOUCH; + action = SELECT_BOX; + rt_kprintf("select touch switch\n"); + } + else if (x >= 100 && x <= 650 && y >= 300 && y <= 400) + { + settings_selected_idx = SET_TIMEOUT; + action = SELECT_BOX; + rt_kprintf("select timeout switch\n"); + } + else if (x >= 100 && x <= 650 && y >= 450 && y <= 540) + { + settings_selected_idx = SET_FULL_REFRESH; + action = SELECT_BOX; + rt_kprintf("select full refresh switch \n"); + } + else if (x >= 100 && x <= 650 && y >= 830 && y <= 950) + { + settings_selected_idx = SET_CONFIRM; + action = SELECT; + rt_kprintf("select touch switch\n"); + } + + if(settings_selected_idx == SET_TOUCH && 0<=x && x<= 50 && 160<=y && y<=260) + { + action = SELECT; + } + else if(settings_selected_idx == SET_TOUCH && 700<=x && x<=750 && 160<=y && y<=260) + { + action = SELECT; + } + else if(settings_selected_idx == SET_TIMEOUT && 0 <= x && x<=50 && 300 <= y && y<= 400) + { + action = PREV_OPTION; + rt_kprintf("select timeout Reduce\n"); + } + else if(settings_selected_idx == SET_TIMEOUT && 700<=x && x<=750 && 300<=y && y<= 400) + { + action = NEXT_OPTION; + rt_kprintf("select timeout increase\n"); + } + else if(settings_selected_idx == SET_FULL_REFRESH && 0 <= x && x<= 50 && 450 <= y && y<= 540) + { + action = PREV_OPTION; + } + else if(settings_selected_idx == SET_FULL_REFRESH && 700 <= x && x<= 750 && 450 <= y && y<= 540) + { + action = NEXT_OPTION; + } + break; + +} + + instance->last_action = action; if (action != NONE) diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.h b/epdiy-epub/src/boards/controls/SF32_TouchControls.h index 0ad4b12..1983a55 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.h +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.h @@ -16,9 +16,12 @@ class SF32_TouchControls : public TouchControls UIAction last_action = NONE; // 添加手势检测状态 bool is_touch_down = false; // 是否正在触摸 + int touch_start_x = 0; // 按下时的 X 坐标 int touch_start_y = 0; // 按下时的 Y 坐标 + int touch_current_x = 0; // 当前触摸 X 坐标 int touch_current_y = 0; // 当前触摸 Y 坐标 // 滑动检测阈值 + static const int SWIPE_THRESHOLD = 50; // 最小滑动距离阈值 public: static rt_err_t tp_rx_indicate(rt_device_t dev, rt_size_t size); diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index b06ae54..523b704 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -2,7 +2,7 @@ #include "EpubList/EpubList.h" #include "epub_screen.h" #include - +#include "type.h" extern TouchControls *touch_controls; extern "C" @@ -16,9 +16,9 @@ extern int g_last_read_index; // 主页面选项 typedef enum { - OPTION_OPEN_LIBRARY = 0, - OPTION_CONTINUE_READING, - OPTION_ENTER_SETTINGS + OPTION_OPEN_LIBRARY = 0, // 打开书库 + OPTION_CONTINUE_READING, // 继续阅读 + OPTION_ENTER_SETTINGS // 进入设置 } MainOption; static MainOption main_option = OPTION_OPEN_LIBRARY; // 默认“打开书库” @@ -34,9 +34,18 @@ int screen_get_full_refresh_period() } // 切换全刷周期(循环) -void screen_cycle_full_refresh_period() +void screen_cycle_full_refresh_period(bool refresh) { - full_refresh_idx = (full_refresh_idx + 1) % kFullRefreshOptionsCount; // ?% 4 + if(refresh) + { + full_refresh_idx = (full_refresh_idx + 1) % kFullRefreshOptionsCount; // ?% 4 + + } + else + { + full_refresh_idx = (full_refresh_idx - 1) % kFullRefreshOptionsCount; // ?% 4 + + } } // 设置全刷周期索引 @@ -51,9 +60,8 @@ int screen_get_full_refresh_idx() return full_refresh_idx; } -// 设置页列表项 -typedef enum { SET_TOUCH = 0, SET_TIMEOUT = 1, SET_FULL_REFRESH = 2, SET_CONFIRM = 3 } SettingsItem; -static int settings_selected_idx = 0; + +int settings_selected_idx = 0; // 超时关机:5/10/30分钟、1小时、不关机(0) static const int kTimeoutOptions[] = {5, 10, 30, 60, 0}; // 单位:分钟,0为不关机 @@ -79,7 +87,7 @@ static void adjust_timeout(bool increase) } else { - timeout_idx = (timeout_idx - 1 + kTimeoutOptionsCount) % kTimeoutOptionsCount; + timeout_idx = (timeout_idx - 1) % kTimeoutOptionsCount; } timeout_shutdown_minutes = kTimeoutOptions[timeout_idx]; } @@ -101,7 +109,7 @@ int screen_get_main_selected_option() return (int)main_option; // 0: 打开书库, 1: 继续阅读, 2: 进入设置 } -// 主页面 +// 绘制主页面 static void render_main_page(Renderer *renderer) { renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); @@ -152,12 +160,12 @@ static void render_main_page(Renderer *renderer) int opt_h = renderer->get_line_height(); renderer->draw_text(mid_x + (mid_w - opt_w) / 2, y + (rect_h - opt_h) / 2, opt_text, false, true); } - +//主界面处理 void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) { if (needs_redraw || action == NONE) { - render_main_page(renderer); + render_main_page(renderer);//绘制主界面 return; } switch (action) @@ -195,7 +203,7 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) } // 设置页面 -static void render_settings_page(Renderer *renderer) +void render_settings_page(Renderer *renderer) { renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); @@ -334,6 +342,7 @@ static void render_settings_page(Renderer *renderer) renderer->draw_text(confirm_x + (confirm_w - c_w) / 2, confirm_y + (confirm_h - c_h) / 2, confirm, false, true); } +// 设置页面交互处理 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) { // 读取并清除一次性的触控箭头标记,避免后续硬件按键误用 @@ -376,6 +385,56 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) render_settings_page(renderer); } break; + case SELECT_BOX: + if(settings_selected_idx == SET_TOUCH) + { + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_TIMEOUT) + { + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_FULL_REFRESH) + { + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_CONFIRM) + { + render_settings_page(renderer); + return true; + } + break; + case PREV_OPTION: + if (settings_selected_idx == SET_TIMEOUT) + { + // SELECT 在超时关机项上为加操作(循环) + adjust_timeout(false); + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_FULL_REFRESH) + { + + screen_cycle_full_refresh_period(false); + set_part_disp_times(screen_get_full_refresh_period()); + render_settings_page(renderer); + } + + break; + case NEXT_OPTION: + if (settings_selected_idx == SET_TIMEOUT) + { + // SELECT 在超时关机项上为加操作(循环) + adjust_timeout(true); + render_settings_page(renderer); + } + else if(settings_selected_idx == SET_FULL_REFRESH) + { + + screen_cycle_full_refresh_period(true); + set_part_disp_times(screen_get_full_refresh_period()); + render_settings_page(renderer); + } + break; case SELECT: if (settings_selected_idx == SET_TOUCH) { @@ -399,7 +458,7 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) if (settings_selected_idx == SET_FULL_REFRESH) { // SELECT 在全刷周期项上为加操作(循环) - screen_cycle_full_refresh_period(); + screen_cycle_full_refresh_period(true); set_part_disp_times(screen_get_full_refresh_period()); render_settings_page(renderer); break; diff --git a/epdiy-epub/src/epub_screen.h b/epdiy-epub/src/epub_screen.h index d3f1646..148141b 100644 --- a/epdiy-epub/src/epub_screen.h +++ b/epdiy-epub/src/epub_screen.h @@ -22,6 +22,6 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw); // 设置页面交互与渲染;返回 true 表示确认并退出到主页面 bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw); // 切换全刷周期(循环) -void screen_cycle_full_refresh_period(); +void screen_cycle_full_refresh_period(bool refresh); // 获取当前全刷周期值 int screen_get_full_refresh_period(); \ No newline at end of file diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index c7031be..e69a241 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -36,17 +36,7 @@ extern "C" const char *TAG = "main"; -typedef enum { - MAIN_PAGE, // 新主页面 - SELECTING_EPUB, // 电子书列表页面(书库) - SELECTING_TABLE_CONTENTS, // 电子书目录页面 - READING_EPUB, // 阅读页面 - SETTINGS_PAGE, // 通用功能设置页面 - WELCOME_PAGE, // 欢迎页面 - LOW_POWER_PAGE, // 低电量页面 - CHARGING_PAGE, // 充电页面 - SHUTDOWN_PAGE // 关机页面 -} AppUIState; + // 默认显示新主页面,而非书库页面 AppUIState ui_state = MAIN_PAGE; @@ -72,9 +62,18 @@ Renderer *renderer = nullptr; TouchControls *touch_controls = nullptr; // 书库页底部按钮选择状态 -static bool library_bottom_mode = false; // 是否处于底部三按钮选择模式 -static int library_bottom_idx = 1; // 当前底部按钮索引:0上一页,1主页面,2下一页 - +bool library_bottom_mode = false; // 是否处于底部三按钮选择模式 +int library_bottom_idx = 1; // 当前底部按钮索引:0上一页,1主页面,2下一页 +int book_index;//用于记录电子书触控选择 +int current_page; // 当前页面 +int start_index; // 当前页起始索引 +// 计算全局索引 = 页起始索引 + 页内偏移 +int global_index; +bool toc_bottom_mode = false; +int toc_index;//用于记录目录触控选择 +int toc_bottom_idx = 1; // 0:上一页,1:主页面,2:下一页 +int sel; +int touch_sel; rt_mq_t ui_queue = RT_NULL; // 主页面选项 @@ -87,169 +86,178 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red void handleEpub(Renderer *renderer, UIAction action) { - if (!reader) - { - reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); - reader->load(); - // 记录最近一次进入阅读的书籍索引 - g_last_read_index = epub_list_state.selected_item; - } - switch (action) - { - case UP: - if (reader->is_overlay_active()) - { - reader->overlay_move_left(); - } - else - { - reader->prev(); - } - break; - case DOWN: - if (reader->is_overlay_active()) + if (!reader) { - reader->overlay_move_right(); - } - else - { - reader->next(); + reader = new EpubReader(epub_list_state.epub_list[epub_list_state.selected_item], renderer); + reader->load(); + // 记录最近一次进入阅读的书籍索引 + g_last_read_index = epub_list_state.selected_item; } - break; - case SELECT: - if (reader->is_overlay_active()) + + switch (action) { - int sel = reader->get_overlay_selected(); - // 1/3:改变中心属性;2:执行当前属性(触控取反 / 全刷周期循环) - if (sel == 0) - { - if(reader->overlay_is_center_touch()) + case UP: + if (reader->is_overlay_active()) { - reader->overlay_set_center_mode_full_refresh(); + reader->overlay_move_left(); } else { - reader->overlay_set_center_mode_touch(); + reader->prev(); } - } - else if (sel == 2) - { - if(reader->overlay_is_center_touch()) + break; + case DOWN: + if (reader->is_overlay_active()) { - reader->overlay_set_center_mode_full_refresh(); + reader->overlay_move_right(); } else { - reader->overlay_set_center_mode_touch(); + reader->next(); } - - } - else if (sel == 1) - { - // 中心矩形:根据当前属性执行 - if (reader->overlay_is_center_touch()) + break; + case SELECT: + if (reader->is_overlay_active()) { - bool cur = touch_controls ? touch_controls->isTouchEnabled() : false; - if (touch_controls) - { - touch_controls->setTouchEnable(!cur); - if (!cur) touch_controls->powerOnTouch(); else touch_controls->powerOffTouch(); - } - reader->overlay_set_touch_enabled(!cur); + int sel = reader->get_overlay_selected(); + // 1/3:改变中心属性;2:执行当前属性(触控取反 / 全刷周期循环) + if(touch_sel >=0 && touch_sel <=10) + { + sel = -1; + } + if (sel == 0 || touch_sel == 0) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + } + else if (sel == 2 || touch_sel == 2) + { + if(reader->overlay_is_center_touch()) + { + reader->overlay_set_center_mode_full_refresh(); + } + else + { + reader->overlay_set_center_mode_touch(); + } + } + else if (sel == 1 || touch_sel == 1) + { + // 中心矩形:根据当前属性执行 + if (reader->overlay_is_center_touch()) + { + bool cur = touch_controls ? touch_controls->isTouchEnabled() : false; + if (touch_controls) + { + touch_controls->setTouchEnable(!cur); + if (!cur) touch_controls->powerOnTouch(); else touch_controls->powerOffTouch(); + } + reader->overlay_set_touch_enabled(!cur); + } + else + { + reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/每次(0) 之间循环 + set_part_disp_times(reader->overlay_get_full_refresh_value()); + } + } + if (sel == 9 || touch_sel == 9) //目录 + { + ui_state = SELECTING_TABLE_CONTENTS; + renderer->set_margin_bottom(0); + reader->stop_overlay(); + delete reader; + reader = nullptr; + contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); + contents->load(); + contents->set_needs_redraw(); + handleEpubTableContents(renderer, NONE, true); + touch_sel = -1; + return; + } + else if (sel == 8 || touch_sel == 8) //确认:1.按第六格累积值跳页 + { + // 跳转到第六格显示的目标页 + int target = reader->overlay_get_target_page(); + if (target < 1) target = 1; + extern EpubListState epub_list_state; + epub_list_state.epub_list[epub_list_state.selected_item].current_page = (uint16_t)(target - 1); + reader->overlay_reset_jump(); + reader->stop_overlay(); + } + else if (sel == 10 || touch_sel == 10) //书库 + { + ui_state = SELECTING_EPUB; + renderer->set_margin_bottom(0); + reader->stop_overlay(); + renderer->clear_screen(); + delete reader; + reader = nullptr; + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + handleEpubList(renderer, NONE, true); + touch_sel = -1; + return; + } + else if (sel == 3 || touch_sel == 3) + { + reader->overlay_adjust_target_page(-5); + } + else if (sel == 4 || touch_sel == 4) + { + reader->overlay_adjust_target_page(-1); + } + else if (sel == 6 || touch_sel == 6) + { + reader->overlay_adjust_target_page(1); + } + else if (sel == 7 || touch_sel == 7) + { + reader->overlay_adjust_target_page(5); + } + touch_sel = -1; } else { - reader->overlay_cycle_full_refresh(); //设置全刷周期,在 5/10/20/每次(0) 之间循环 - set_part_disp_times(reader->overlay_get_full_refresh_value()); + // switch back to main screen + renderer->clear_screen(); + // clear the epub reader away + delete reader; + reader = nullptr; + // force a redraw + if (!epub_list) + { + epub_list = new EpubList(renderer, epub_list_state); + } + renderer->set_margin_bottom(0); + back_to_main_page(); + + return; } - } - if (sel == 9) //目录 - { - ui_state = SELECTING_TABLE_CONTENTS; - renderer->set_margin_bottom(0); - reader->stop_overlay(); - delete reader; - reader = nullptr; - contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); - contents->load(); - contents->set_needs_redraw(); - handleEpubTableContents(renderer, NONE, true); - return; - } - else if (sel == 8) //确认:1.按第六格累积值跳页 - { - // 跳转到第六格显示的目标页 - int target = reader->overlay_get_target_page(); - if (target < 1) target = 1; - extern EpubListState epub_list_state; - epub_list_state.epub_list[epub_list_state.selected_item].current_page = (uint16_t)(target - 1); - reader->overlay_reset_jump(); - reader->stop_overlay(); - } - else if (sel == 10) //书库 - { - ui_state = SELECTING_EPUB; - renderer->set_margin_bottom(0); - reader->stop_overlay(); - renderer->clear_screen(); - delete reader; - reader = nullptr; - if (!epub_list) - { - epub_list = new EpubList(renderer, epub_list_state); + break; + case UPGLIDE: + // 激活阅读页下半屏覆盖操作层 + // 防止重复激活 + if (!reader->is_overlay_active()) { + reader->start_overlay(); + // 默认中心属性为触控开关,初始同步当前触控状态 + reader->overlay_set_center_mode_touch(); + if (touch_controls) + reader->overlay_set_touch_enabled(touch_controls->isTouchEnabled()); } - handleEpubList(renderer, NONE, true); - return; - } - else if (sel == 3) - { - reader->overlay_adjust_target_page(-5); - } - else if (sel == 4) - { - reader->overlay_adjust_target_page(-1); - } - else if (sel == 6) - { - reader->overlay_adjust_target_page(1); - } - else if (sel == 7) - { - reader->overlay_adjust_target_page(5); - } - - } - else - { - // switch back to main screen - renderer->clear_screen(); - // clear the epub reader away - delete reader; - reader = nullptr; - // force a redraw - if (!epub_list) - { - epub_list = new EpubList(renderer, epub_list_state); - } - renderer->set_margin_bottom(0); - back_to_main_page(); - - return; + break; + case NONE: + default: + break; } - break; - case UPGLIDE: - // 激活阅读页下半屏覆盖操作层 - reader->start_overlay(); - // 默认中心属性为触控开关,初始同步当前触控状态 - reader->overlay_set_center_mode_touch(); - if (touch_controls) - reader->overlay_set_touch_enabled(touch_controls->isTouchEnabled()); - break; - case NONE: - default: - break; - } - reader->render(); + reader->render(); } //目录页的处理 void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw) @@ -260,8 +268,7 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red contents->set_needs_redraw(); contents->load(); } - static bool toc_bottom_mode = false; - static int toc_bottom_idx = 1; // 0:上一页,1:主页面,2:下一页 + if (needs_redraw) { toc_bottom_mode = false; @@ -340,11 +347,6 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red } break; case SELECT_BOX: - // 如果在底部模式,先退出底部模式 - if (toc_bottom_mode) - { - toc_bottom_mode = false; - } // 计算当前页面相关信息 current_page = epub_index_state.selected_item / 6; // 每页6个目录项 start_index = current_page * 6; // 当前页起始索引 @@ -543,6 +545,33 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } } break; + case SELECT_BOX: + current_page = epub_list_state.selected_item / 4; // 当前页面 + start_index = current_page * 4; // 当前页起始索引 + // 计算全局索引 = 页起始索引 + 页内偏移 + global_index = start_index + book_index; + // 边界检查 + if (global_index < epub_list_state.num_epubs) + { + + if(book_index == 0) + { + epub_list->switch_book(global_index); + } + else if(book_index == 1) + { + epub_list->switch_book(global_index); + } + else if(book_index == 2) + { + epub_list->switch_book(global_index); + } + else if(book_index == 3) + { + epub_list->switch_book(global_index); + } + } + break; case SELECT: if (library_bottom_mode) { @@ -1120,7 +1149,7 @@ extern "C" int main() { // dump out the epub list state - //rt_pm_request(PM_SLEEP_MODE_IDLE); + rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); From ecb4a8097fee61ca2a28393dfef9f4ccc9b9bdde Mon Sep 17 00:00:00 2001 From: minjiezhong Date: Thu, 22 Jan 2026 10:48:45 +0800 Subject: [PATCH 22/27] =?UTF-8?q?1.=E8=A7=A3=E5=86=B3=E4=BA=86=E4=B9=A6?= =?UTF-8?q?=E5=BA=93=E9=A1=B5=E9=9D=A2=E3=80=81=E7=9B=AE=E5=BD=95=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E7=82=B9=E5=87=BB=E4=B8=8B=E4=B8=80=E9=A1=B5=EF=BC=8C?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E4=B9=A6=E7=B1=8D=E5=92=8C=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E5=A4=B1=E6=95=88=E7=9A=84bug=202.=E8=A7=A3=E5=86=B3=E4=BA=86?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E9=A1=B5=E9=9D=A2=E7=82=B9=E5=87=BB=E5=8F=B3?= =?UTF-8?q?=E4=B8=8B=E8=A7=92=E4=BC=9A=E5=87=BA=E7=8E=B0=E5=94=A4=E9=86=92?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E8=AE=BE=E7=BD=AE=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boards/controls/SF32_TouchControls.cpp | 2 + .../src/boards/controls/SF32_TouchControls.h | 3 - epdiy-epub/src/main.cpp | 109 +++++++++++------- 3 files changed, 70 insertions(+), 44 deletions(-) diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index c2a0f15..81a2497 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -27,6 +27,8 @@ static bool waiting_for_confirmation = false; // 是否正在等待确认 extern int touch_sel; extern EpubReader *reader; +static const int SWIPE_THRESHOLD = 100; // 最小滑动距离阈值 +static bool is_touch_started = false; // 全局或类成员变量 rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.h b/epdiy-epub/src/boards/controls/SF32_TouchControls.h index 1983a55..0ad4b12 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.h +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.h @@ -16,12 +16,9 @@ class SF32_TouchControls : public TouchControls UIAction last_action = NONE; // 添加手势检测状态 bool is_touch_down = false; // 是否正在触摸 - int touch_start_x = 0; // 按下时的 X 坐标 int touch_start_y = 0; // 按下时的 Y 坐标 - int touch_current_x = 0; // 当前触摸 X 坐标 int touch_current_y = 0; // 当前触摸 Y 坐标 // 滑动检测阈值 - static const int SWIPE_THRESHOLD = 50; // 最小滑动距离阈值 public: static rt_err_t tp_rx_indicate(rt_device_t dev, rt_size_t size); diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index e69a241..49cbbd6 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -347,6 +347,11 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red } break; case SELECT_BOX: + // 如果在底部模式,先退出底部模式 + if (toc_bottom_mode) + { + toc_bottom_mode = false; + } // 计算当前页面相关信息 current_page = epub_index_state.selected_item / 6; // 每页6个目录项 start_index = current_page * 6; // 当前页起始索引 @@ -404,28 +409,37 @@ void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_red handleEpubList(renderer, NONE, true); return; } - else if (toc_bottom_idx == 0) + else if (toc_bottom_idx == 0) // 上一页 { - // 上一页 if (current_page > 0) { - epub_index_state.selected_item -= per_page; - if (epub_index_state.selected_item < 0) epub_index_state.selected_item = 0; + // 计算新页面(上一页) + int new_page = current_page - 1; + // 将选中项设置为新页面的第一项 + epub_index_state.selected_item = new_page * per_page; + if (epub_index_state.selected_item < 0) + epub_index_state.selected_item = 0; + + // 退出底部选择模式,回到列表选择状态 + toc_bottom_mode = false; contents->set_needs_redraw(); } - // 保持底部模式,允许连续翻页 } - else if (toc_bottom_idx == 2) + else if (toc_bottom_idx == 2) // 下一页 { - // 下一页 if (current_page < max_page) { - epub_index_state.selected_item += per_page; + // 计算新页面(下一页) + int new_page = current_page + 1; + // 将选中项设置为新页面的第一项 + epub_index_state.selected_item = new_page * per_page; if (epub_index_state.selected_item >= count) - epub_index_state.selected_item = count - 1; + epub_index_state.selected_item = ((count - 1) / per_page) * per_page; // 确保在最后一页的第一项 + + // 退出底部选择模式,回到列表选择状态 + toc_bottom_mode = false; contents->set_needs_redraw(); } - // 保持底部模式,允许连续翻页 } } else @@ -546,6 +560,10 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } break; case SELECT_BOX: + // 如果在底部模式,先退出底部模式 + if (library_bottom_mode) { + library_bottom_mode = false; + } current_page = epub_list_state.selected_item / 4; // 当前页面 start_index = current_page * 4; // 当前页起始索引 // 计算全局索引 = 页起始索引 + 页内偏移 @@ -573,44 +591,53 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) } break; case SELECT: - if (library_bottom_mode) - { + if (library_bottom_mode) + { int per_page = 4; int current_page = epub_list_state.selected_item / per_page; int max_page = (epub_list_state.num_epubs == 0) ? 0 : ( (epub_list_state.num_epubs - 1) / per_page ); if (library_bottom_idx == 1) { - // 主页面:返回主页面 - rt_kprintf("从书库页返回主页面\n"); - back_to_main_page(); - return; + // 主页面:返回主页面 + rt_kprintf("从书库页返回主页面\n"); + back_to_main_page(); + return; } - else if (library_bottom_idx == 0) + else if (library_bottom_idx == 0) // 上一页 { - // 上一页 - if (current_page > 0) - { - epub_list_state.selected_item -= per_page; - if (epub_list_state.selected_item < 0) epub_list_state.selected_item = 0; - epub_list->set_needs_redraw(); - } - + if (current_page > 0) + { + // 计算新页面(上一页) + int new_page = current_page - 1; + // 将选中项设置为新页面的第一本书 + epub_list_state.selected_item = new_page * per_page; + if (epub_list_state.selected_item < 0) + epub_list_state.selected_item = 0; + + // 退出底部选择模式,回到列表选择状态 + library_bottom_mode = false; + epub_list->set_needs_redraw(); + } } - else if (library_bottom_idx == 2) + else if (library_bottom_idx == 2) // 下一页 { - // 下一页 - if (current_page < max_page) - { - epub_list_state.selected_item += per_page; - if (epub_list_state.selected_item >= epub_list_state.num_epubs) - epub_list_state.selected_item = epub_list_state.num_epubs - 1; - epub_list->set_needs_redraw(); - } - + if (current_page < max_page) + { + // 计算新页面(下一页) + int new_page = current_page + 1; + // 将选中项设置为新页面的第一本书 + epub_list_state.selected_item = new_page * per_page; + if (epub_list_state.selected_item >= epub_list_state.num_epubs) + epub_list_state.selected_item = ((epub_list_state.num_epubs - 1) / per_page) * per_page; // 确保在最后一页的第一本书 + + // 退出底部选择模式,回到列表选择状态 + library_bottom_mode = false; + epub_list->set_needs_redraw(); + } } - } - else - { + } + else + { // 进入目录选择页面 ui_state = SELECTING_TABLE_CONTENTS; contents = new EpubToc(epub_list_state.epub_list[epub_list_state.selected_item], epub_index_state, renderer); @@ -618,8 +645,8 @@ void handleEpubList(Renderer *renderer, UIAction action, bool needs_redraw) contents->set_needs_redraw(); handleEpubTableContents(renderer, NONE, true); return; - } - break; + } + break; case NONE: default: // nothing to do @@ -1149,7 +1176,7 @@ extern "C" int main() { // dump out the epub list state - rt_pm_request(PM_SLEEP_MODE_IDLE); + //rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); From 8c82c2cf8fa55d7095307344afbe49970af1b1c6 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Fri, 23 Jan 2026 19:05:40 +0800 Subject: [PATCH 23/27] =?UTF-8?q?=E6=96=B0=E5=BB=BA=E6=9D=BF=E5=AD=90base?= =?UTF-8?q?=E4=B8=8E1.2=E7=9A=84board=EF=BC=8C1.1=E4=B8=8E1.2=E5=A4=8D?= =?UTF-8?q?=E7=94=A8base?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 2bd416f7df87c01d449a4f7d87745e5a53e61257 Mon Sep 17 00:00:00 2001 From: smiling boy Date: Mon, 26 Jan 2026 11:19:51 +0800 Subject: [PATCH 24/27] =?UTF-8?q?=E8=A7=A6=E6=8E=A7=E5=B1=8F=E9=A9=B1?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=9D=BF=E5=AD=90=E8=BF=9B=E8=A1=8C=E5=8C=BA?= =?UTF-8?q?=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/project/Kconfig.proj | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/epdiy-epub/project/Kconfig.proj b/epdiy-epub/project/Kconfig.proj index 3a0e844..c599eec 100644 --- a/epdiy-epub/project/Kconfig.proj +++ b/epdiy-epub/project/Kconfig.proj @@ -61,19 +61,22 @@ if !BSP_USING_BUILT_LCD config LCD_USING_EPD_YZC085_V100_V12 bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758) for V1.2 board" - select TSC_USING_GT967 if BSP_USING_TOUCHD + select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V11 + select TSC_USING_GT967 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V12 select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT config LCD_USING_EPD_YZC085_V100 bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758) for V1.1 board" - select TSC_USING_GT967 if BSP_USING_TOUCHD + select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V11 + select TSC_USING_GT967 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V12 select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT config LCD_USING_EPD_R7D005 bool "6.0 rect electronic paper display(EPD R7D005_-1.30 1448x1072)" - select TSC_TSC_USING_GT967USING_FT5446U_V01 if BSP_USING_TOUCHD + select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V11 + select TSC_USING_GT967 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V12 select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT From c2f2932a687baad59da7b708f083e0e20557447b Mon Sep 17 00:00:00 2001 From: smiling boy Date: Tue, 27 Jan 2026 14:48:45 +0800 Subject: [PATCH 25/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A01.2=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=E6=A8=A1=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/project/Kconfig.proj | 15 +++++++++------ .../src/boards/display_dbi/epd_configs_opm060d.c | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/epdiy-epub/project/Kconfig.proj b/epdiy-epub/project/Kconfig.proj index c599eec..a9d32a3 100644 --- a/epdiy-epub/project/Kconfig.proj +++ b/epdiy-epub/project/Kconfig.proj @@ -61,22 +61,25 @@ if !BSP_USING_BUILT_LCD config LCD_USING_EPD_YZC085_V100_V12 bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758) for V1.2 board" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V11 - select TSC_USING_GT967 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V12 + select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT + config LCD_USING_EPD_YZC085_V100_V12 + bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758)" + select TSC_USING_GT967 if BSP_USING_TOUCHD + select LCD_USING_YZC085_V100 + select BSP_LCDC_USING_EPD_8BIT + config LCD_USING_EPD_YZC085_V100 bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758) for V1.1 board" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V11 - select TSC_USING_GT967 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V12 + select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT config LCD_USING_EPD_R7D005 bool "6.0 rect electronic paper display(EPD R7D005_-1.30 1448x1072)" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V11 - select TSC_USING_GT967 if BSP_USING_TOUCHD && BSP_USING_BOARD_SF32_OED_EPD_V12 + select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD select LCD_USING_OPM060D select BSP_LCDC_USING_EPD_8BIT diff --git a/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c b/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c index eb28fd1..0f39beb 100644 --- a/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c +++ b/epdiy-epub/src/boards/display_dbi/epd_configs_opm060d.c @@ -2,7 +2,7 @@ #include "epd_configs.h" #include "mem_section.h" #include "string.h" -#if defined(LCD_USING_EPD_YZC085_V100) || defined(LCD_USING_EPD_YZC146_V100) +#if defined(LCD_USING_EPD_YZC085_V100) || defined(LCD_USING_EPD_YZC146_V100) || defined(LCD_USING_EPD_YZC085_V100_V12) #ifndef EPD_WAVEFORM_USE_BIN // 8bit lookup table for the current frame (high 4 bits: old data, low 4 bits: new data). From 86e0aac06f43f206630ecc9b4532f0428fb5e86f Mon Sep 17 00:00:00 2001 From: minjiezhong Date: Wed, 18 Mar 2026 17:28:48 +0800 Subject: [PATCH 26/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=B5=E5=AD=90?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epdiy-epub/project/Kconfig.proj | 75 ++++++--------- epdiy-epub/src/SConscript | 7 +- epdiy-epub/src/boards/controls/Actions.h | 2 +- .../boards/controls/SF32_TouchControls.cpp | 93 ++++++++++-------- .../src/boards/display_dbi/epd_display.c | 2 - epdiy-epub/src/epub_mem.c | 2 +- epdiy-epub/src/epub_screen.cpp | 94 +++++++++++++++++-- epdiy-epub/src/main.cpp | 9 +- 8 files changed, 184 insertions(+), 100 deletions(-) diff --git a/epdiy-epub/project/Kconfig.proj b/epdiy-epub/project/Kconfig.proj index a9d32a3..2180d7c 100644 --- a/epdiy-epub/project/Kconfig.proj +++ b/epdiy-epub/project/Kconfig.proj @@ -22,74 +22,61 @@ if !BSP_USING_BUILT_LCD #define the EPD connection type config LCD_USING_EPD_SPI bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V12_SPI default n config BSP_LCDC_USING_EPD_8BIT - def_bool n + bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V11 || BSP_USING_BOARD_SF32_OED_EPD_V12 + default n #define the EPD module name config LCD_USING_OPM060D bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V11 || BSP_USING_BOARD_SF32_OED_EPD_V12 default n - config LCD_USING_OPM060D - bool + config LCD_USING_EPD_YZC085_V100 + bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V11 default n + select BSP_LCDC_USING_EPD_8BIT + select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD + config LCD_USING_EPD_YZC085_V100_V12 + bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V12 + default n + select BSP_LCDC_USING_EPD_8BIT + select TSC_USING_GT967 if BSP_USING_TOUCHD -#define the touch controller name - config TSC_USING_FT5446U_V01 + config LCD_USING_EPD_OPMO37A3 bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V12_SPI default n + select LCD_USING_EPD_SPI + select TSC_USING_FT6336U if BSP_USING_TOUCHD - config TSC_USING_FT6336U + config LCD_USING_EPD_R7D005 bool default n - config TSC_USING_GT967 + +#define the touch controller name + config TSC_USING_FT5446U_V01 bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V11 default n - config TSC_USING_GT967 + + config TSC_USING_FT6336U bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V12_SPI default n + config TSC_USING_GT967 bool + default y if BSP_USING_BOARD_SF32_OED_EPD_V12 default n - choice - prompt "Custom LCD driver" - default LCD_USING_EPD_YZC085_V100 if BSP_USING_BOARD_SF32_OED_EPD_V11 - default LCD_USING_EPD_YZC085_V100_V12 if BSP_USING_BOARD_SF32_OED_EPD_V12 - - config LCD_USING_EPD_YZC085_V100_V12 - bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758) for V1.2 board" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD - select LCD_USING_OPM060D - select BSP_LCDC_USING_EPD_8BIT - - config LCD_USING_EPD_YZC085_V100_V12 - bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758)" - select TSC_USING_GT967 if BSP_USING_TOUCHD - select LCD_USING_YZC085_V100 - select BSP_LCDC_USING_EPD_8BIT - - config LCD_USING_EPD_YZC085_V100 - bool "6.0 rect electronic paper display(EPD YZC085_V1.05 1032x758) for V1.1 board" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD - select LCD_USING_OPM060D - select BSP_LCDC_USING_EPD_8BIT - - config LCD_USING_EPD_R7D005 - bool "6.0 rect electronic paper display(EPD R7D005_-1.30 1448x1072)" - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD - select LCD_USING_OPM060D - select BSP_LCDC_USING_EPD_8BIT - - config LCD_USING_EPD_OPMO37A3 - bool "3.7 rect electronic paper display SPI (OPM037A3 240x416)" - select TSC_USING_FT6336U if BSP_USING_TOUCHD - select LCD_USING_EPD_SPI - - endchoice - + config EPD_WAVEFORM_USE_BIN bool "OPM060D use binary waveform" diff --git a/epdiy-epub/src/SConscript b/epdiy-epub/src/SConscript index 6c590b3..f19fa4b 100644 --- a/epdiy-epub/src/SConscript +++ b/epdiy-epub/src/SConscript @@ -4,7 +4,9 @@ from building import * import rtconfig cwd = GetCurrentDir() -src = ['main.cpp','epub_screen.cpp','epub_mem.c','epub_fonts.c'] + +src = ['main.cpp','UIRegionsManager.cpp','epub_screen.cpp','epub_mem.c','epub_fonts.c'] + src = src + Glob('./assets/*.c') CPPPATH = [cwd] @@ -20,5 +22,4 @@ for d in list: objs = objs + SConscript(os.path.join(cwd, '../waveform/SConscript')) -Return('objs') - +Return('objs') \ No newline at end of file diff --git a/epdiy-epub/src/boards/controls/Actions.h b/epdiy-epub/src/boards/controls/Actions.h index 5e22d6b..0f38751 100644 --- a/epdiy-epub/src/boards/controls/Actions.h +++ b/epdiy-epub/src/boards/controls/Actions.h @@ -19,4 +19,4 @@ typedef enum MSG_UPDATE_CHARGE_STATUS } UIAction; -typedef std::function ActionCallback_t; +typedef std::function ActionCallback_t; \ No newline at end of file diff --git a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp index 81a2497..81ff267 100644 --- a/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp +++ b/epdiy-epub/src/boards/controls/SF32_TouchControls.cpp @@ -5,7 +5,9 @@ #include "type.h" #include "epub_screen.h" #include "EpubReader.h" + #include "UIRegionsManager.h" + #ifdef BSP_USING_TOUCHD #include "drv_touch.h" #endif @@ -30,6 +32,9 @@ extern EpubReader *reader; static const int SWIPE_THRESHOLD = 100; // 最小滑动距离阈值 static bool is_touch_started = false; // 全局或类成员变量 + +extern AreaRect g_area_array[]; + rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) { SF32_TouchControls *instance = static_cast (dev->user_data); @@ -111,17 +116,18 @@ rt_err_t SF32_TouchControls::tp_rx_indicate(rt_device_t dev, rt_size_t size) switch (ui_state) { case MAIN_PAGE://主页面 - if (x >= 10 && x <= 80 && y >= 950 && y <= 1000) + + if (x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) { rt_kprintf("Touch left < \n"); action = UP; // 对应 KEY3 功能 } - else if (x >= 650 && x <= 750 && y >= 950 && y <= 1000) + else if (x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) { action = DOWN; // 对应 KEY1 功能 rt_kprintf("Touch right > \n"); } - else if (x >= 250 && x <= 500 && y >= 950 && y <= 1000) + else if (x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { action = SELECT; // 对应 KEY2 功能 rt_kprintf("Touch middle SELECT \n"); @@ -129,19 +135,19 @@ switch (ui_state) break; case SELECTING_EPUB://书库页面 // 检查是否点击了功能控制按钮 - if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y) { library_bottom_mode = true; library_bottom_idx = 0; action = SELECT; } - else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + else if(x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) { library_bottom_mode = true; library_bottom_idx = 1; action = SELECT; } - else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + else if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y) { library_bottom_mode = true; library_bottom_idx = 2; @@ -152,19 +158,20 @@ switch (ui_state) // 处理书籍选择区域 int clicked_book_index = -1; - if(x >= 10 && x <= 740 && y >= 60 && y <= 240) + + if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) { clicked_book_index = 0; } - else if(x >= 10 && x <= 740 && y >= 270 && y <= 450) + else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) { clicked_book_index = 1; } - else if(x >= 10 && x <= 740 && y >= 470 && y <= 680) + else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { clicked_book_index = 2; } - else if(x >= 10 && x <= 740 && y >= 700 && y <= 900) + else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y) { clicked_book_index = 3; } @@ -213,57 +220,58 @@ switch (ui_state) touch_sel = 8; action = SELECT; } - + + //阅读页面控制区域设置 - if(x >= 10 && x <= 250 && y >= 900 && y <= 960 && reader->is_overlay_active()) + if(x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y && reader->is_overlay_active())//第三层 { touch_sel = 8; action = SELECT; } - else if(x >= 280 && x <= 480 && y >= 900 && y <= 960 && reader->is_overlay_active()) + else if(x >= g_area_array[9].start_x && x <= g_area_array[9].end_x && y >= g_area_array[9].start_y && y <= g_area_array[9].end_y && reader->is_overlay_active()) { touch_sel = 9; action = SELECT; } - else if(x >= 520 && x <= 750 && y >= 900 && y <= 960 && reader->is_overlay_active()) + else if(x >= g_area_array[10].start_x && x <= g_area_array[10].end_x && y >= g_area_array[10].start_y && y <= g_area_array[10].end_y && reader->is_overlay_active()) { touch_sel = 10; action = SELECT; } - else if(x >= 10 && x <= 150 && y >= 690 && y <= 750 && reader->is_overlay_active()) + else if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y && reader->is_overlay_active())//第一层 { touch_sel= 0; rt_kprintf("Touch middle SELECT %d\n",touch_sel); action = SELECT; } - else if(x >= 170 && x <= 570 && y >= 690 && y <= 750 && reader->is_overlay_active()) + else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y && reader->is_overlay_active()) { touch_sel= 1; rt_kprintf("Touch middle SELECT %d\n",touch_sel); action = SELECT; } - else if(x >= 610 && x <= 750 && y >= 690 && y <= 750 && reader->is_overlay_active()) + else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y && reader->is_overlay_active()) { touch_sel= 2; rt_kprintf("Touch middle SELECT %d\n",touch_sel); action = SELECT; } - else if(x >= 10 && x <= 140 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y && reader->is_overlay_active()) { touch_sel = 3;//跳转-5页 action = SELECT; } - else if(x >= 165 && x <=300 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y && reader->is_overlay_active()) { touch_sel = 4;//跳转-1页 action = SELECT; } - else if(x >= 480 && x <= 570 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y && reader->is_overlay_active()) { touch_sel = 6;//跳转+1页 action = SELECT; } - else if(x >= 620 && x <= 750 && y >= 790 && y <= 850 && reader->is_overlay_active()) + else if(x >= g_area_array[7].start_x && x <= g_area_array[7].end_x && y >= g_area_array[7].start_y && y <= g_area_array[7].end_y && reader->is_overlay_active()) { touch_sel = 7;//跳转5页 action = SELECT; @@ -271,19 +279,19 @@ switch (ui_state) break; case SELECTING_TABLE_CONTENTS: //目录界面 - if(x >= 10 && x <= 250 && y >= 920 && y <= 1010) + if(x >= g_area_array[6].start_x && x <= g_area_array[6].end_x && y >= g_area_array[6].start_y && y <= g_area_array[6].end_y) { toc_bottom_mode = true; toc_bottom_idx = 0; action = SELECT; } - else if(x >= 280 && x <= 500 && y >= 920 && y <= 1010) + else if(x >= g_area_array[7].start_x && x <= g_area_array[7].end_x && y >= g_area_array[7].start_y && y <= g_area_array[7].end_y) { toc_bottom_mode = true; toc_bottom_idx = 1; action = SELECT; } - else if(x >= 520 && x <= 750 && y >= 920 && y <= 1010) + else if(x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y) { toc_bottom_mode = true; toc_bottom_idx = 2; @@ -293,27 +301,28 @@ switch (ui_state) { int clicked_toc_index = -1; - if(x >= 10 && x <= 750 && y >= 20 && y <= 170) + + if(x >= g_area_array[0].start_x && x <= g_area_array[0].end_x && y >= g_area_array[0].start_y && y <= g_area_array[0].end_y) { clicked_toc_index = 0; } - else if(x >= 10 && x <= 750 && y >= 180 && y <= 310) + else if(x >= g_area_array[1].start_x && x <= g_area_array[1].end_x && y >= g_area_array[1].start_y && y <= g_area_array[1].end_y) { clicked_toc_index = 1; } - else if(x >= 10 && x <= 750 && y >= 330 && y <= 450) + else if(x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { clicked_toc_index = 2; } - else if(x >= 10 && x <= 750 && y >= 470 && y <= 590) + else if(x >= g_area_array[3].start_x && x <= g_area_array[3].end_x && y >= g_area_array[3].start_y && y <= g_area_array[3].end_y) { clicked_toc_index = 3; } - else if(x >= 10 && x <= 750 && y >= 620 && y <= 750) + else if(x >= g_area_array[4].start_x && x <= g_area_array[4].end_x && y >= g_area_array[4].start_y && y <= g_area_array[4].end_y) { clicked_toc_index = 4; } - else if(x >= 10 && x <= 750 && y >= 770 && y <= 890) + else if(x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) { clicked_toc_index = 5; } @@ -347,54 +356,56 @@ switch (ui_state) break; case SETTINGS_PAGE: // 设置页面 // 设置页面每行左右箭头触控区域(与设置页布局一致) - if (x >= 100 && x <= 650 && y >= 160 && y <= 260) + + if (x >= g_area_array[2].start_x && x <= g_area_array[2].end_x && y >= g_area_array[2].start_y && y <= g_area_array[2].end_y) { settings_selected_idx = SET_TOUCH; action = SELECT_BOX; rt_kprintf("select touch switch\n"); } - else if (x >= 100 && x <= 650 && y >= 300 && y <= 400) + else if (x >= g_area_array[5].start_x && x <= g_area_array[5].end_x && y >= g_area_array[5].start_y && y <= g_area_array[5].end_y) { settings_selected_idx = SET_TIMEOUT; action = SELECT_BOX; rt_kprintf("select timeout switch\n"); } - else if (x >= 100 && x <= 650 && y >= 450 && y <= 540) + else if (x >= g_area_array[8].start_x && x <= g_area_array[8].end_x && y >= g_area_array[8].start_y && y <= g_area_array[8].end_y) { settings_selected_idx = SET_FULL_REFRESH; action = SELECT_BOX; rt_kprintf("select full refresh switch \n"); } - else if (x >= 100 && x <= 650 && y >= 830 && y <= 950) + else if (x >= g_area_array[9].start_x && x <= g_area_array[9].end_x && y >= g_area_array[9].start_y && y <= g_area_array[9].end_y) { settings_selected_idx = SET_CONFIRM; action = SELECT; - rt_kprintf("select touch switch\n"); + rt_kprintf("select confirm button\n"); } + - if(settings_selected_idx == SET_TOUCH && 0<=x && x<= 50 && 160<=y && y<=260) + if(settings_selected_idx == SET_TOUCH && g_area_array[0].start_x<=x && x<= g_area_array[0].end_x && g_area_array[0].start_y<=y && y<=g_area_array[0].end_y) { action = SELECT; } - else if(settings_selected_idx == SET_TOUCH && 700<=x && x<=750 && 160<=y && y<=260) + else if(settings_selected_idx == SET_TOUCH && g_area_array[1].start_x<=x && x<= g_area_array[1].end_x && g_area_array[1].start_y<=y && y<=g_area_array[1].end_y) { action = SELECT; } - else if(settings_selected_idx == SET_TIMEOUT && 0 <= x && x<=50 && 300 <= y && y<= 400) + else if(settings_selected_idx == SET_TIMEOUT && g_area_array[3].start_x<=x && x<= g_area_array[3].end_x && g_area_array[3].start_y<=y && y<=g_area_array[3].end_y) { action = PREV_OPTION; rt_kprintf("select timeout Reduce\n"); } - else if(settings_selected_idx == SET_TIMEOUT && 700<=x && x<=750 && 300<=y && y<= 400) + else if(settings_selected_idx == SET_TIMEOUT && g_area_array[4].start_x<=x && x<= g_area_array[4].end_x && g_area_array[4].start_y<=y && y<=g_area_array[4].end_y) { action = NEXT_OPTION; rt_kprintf("select timeout increase\n"); } - else if(settings_selected_idx == SET_FULL_REFRESH && 0 <= x && x<= 50 && 450 <= y && y<= 540) + else if(settings_selected_idx == SET_FULL_REFRESH && g_area_array[6].start_x<=x && x<= g_area_array[6].end_x && g_area_array[6].start_y<=y && y<=g_area_array[6].end_y) { action = PREV_OPTION; } - else if(settings_selected_idx == SET_FULL_REFRESH && 700 <= x && x<= 750 && 450 <= y && y<= 540) + else if(settings_selected_idx == SET_FULL_REFRESH && g_area_array[7].start_x<=x && x<= g_area_array[7].end_x && g_area_array[7].start_y<=y && y<=g_area_array[7].end_y) { action = NEXT_OPTION; } diff --git a/epdiy-epub/src/boards/display_dbi/epd_display.c b/epdiy-epub/src/boards/display_dbi/epd_display.c index 445ecd1..badd965 100644 --- a/epdiy-epub/src/boards/display_dbi/epd_display.c +++ b/epdiy-epub/src/boards/display_dbi/epd_display.c @@ -539,8 +539,6 @@ int get_part_disp_times(void) } #define PART_DISP_TIMES 10 -static uint32_t reflesh_times = 0; - L1_RET_CODE_SECT(epd_codes, static void LCD_WriteMultiplePixels(LCDC_HandleTypeDef *hlcdc, const uint8_t *RGBCode, uint16_t Xpos0, uint16_t Ypos0, uint16_t Xpos1, uint16_t Ypos1)) { uint32_t line, line_bytes; diff --git a/epdiy-epub/src/epub_mem.c b/epdiy-epub/src/epub_mem.c index b15b636..c875865 100644 --- a/epdiy-epub/src/epub_mem.c +++ b/epdiy-epub/src/epub_mem.c @@ -80,4 +80,4 @@ rt_uint32_t heap_free_size(void) rt_uint32_t psram_heap_free_size = epub_psram_memheap.available_size; return heap_free_size + psram_heap_free_size; -} +} \ No newline at end of file diff --git a/epdiy-epub/src/epub_screen.cpp b/epdiy-epub/src/epub_screen.cpp index 523b704..cf9d359 100644 --- a/epdiy-epub/src/epub_screen.cpp +++ b/epdiy-epub/src/epub_screen.cpp @@ -4,6 +4,9 @@ #include #include "type.h" +#include "UIRegionsManager.h" + + extern TouchControls *touch_controls; extern "C" { @@ -112,6 +115,9 @@ int screen_get_main_selected_option() // 绘制主页面 static void render_main_page(Renderer *renderer) { + + clear_areas(); // 清除之前的区域记录 + renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); const char *title = "S I F L I"; @@ -133,12 +139,26 @@ static void render_main_page(Renderer *renderer) const char *lt = "<"; int lt_w = renderer->get_text_width(lt); int lt_h = renderer->get_line_height(); + + int left_arrow_x = margin_side;//矩形的X轴起始坐标 + int left_arrow_y = y + margin_bottom;//矩形的Y轴起始坐标 + // 记录左箭头区域 + add_area(left_arrow_x, left_arrow_y, rect_w, rect_h); + + renderer->draw_text(left_x + (rect_w - lt_w) / 2, y + (rect_h - lt_h) / 2, lt, false, true); // 右 ">" const char *gt = ">"; int gt_w = renderer->get_text_width(gt); int gt_h = renderer->get_line_height(); + + int right_arrow_x = right_x ;//矩形的X轴起始坐标 + int right_arrow_y = y + margin_bottom;//矩形的Y轴起始坐标 + // 记录右箭头区域 + add_area(right_arrow_x, right_arrow_y, rect_w, rect_h); + + renderer->draw_text(right_x + (rect_w - gt_w) / 2, y + (rect_h - gt_h) / 2, gt, false, true); // 中间选项文本 @@ -158,6 +178,13 @@ static void render_main_page(Renderer *renderer) } int opt_w = renderer->get_text_width(opt_text); int opt_h = renderer->get_line_height(); + + int option_x = mid_x + (mid_w - opt_w) / 2 ; + int option_y = y + margin_bottom; + + // 记录选项区域 + add_area(option_x, option_y, opt_w, opt_h); + renderer->draw_text(mid_x + (mid_w - opt_w) / 2, y + (rect_h - opt_h) / 2, opt_text, false, true); } //主界面处理 @@ -205,6 +232,9 @@ void handleMainPage(Renderer *renderer, UIAction action, bool needs_redraw) // 设置页面 void render_settings_page(Renderer *renderer) { + + clear_areas(); // 清除之前的区域记录 + renderer->fill_rect(0, 0, renderer->get_page_width(), renderer->get_page_height(), 255); // 标题 @@ -227,9 +257,19 @@ void render_settings_page(Renderer *renderer) int item_x = margin_lr + arrow_col_w; if (settings_selected_idx == SET_TOUCH) { - const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + + const char *lt = "<"; + int lt_w = renderer->get_text_width(lt); + int touch_left_x = margin_lr; + int touch_left_y = y; + static_add_area(touch_left_x, touch_left_y, arrow_col_w, item_h,0); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); + const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + int touch_right_x = page_w - arrow_col_w + margin_lr; + int touch_right_y = y; + static_add_area(touch_right_x, touch_right_y, arrow_col_w, item_h,1); + renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_TOUCH) @@ -250,6 +290,11 @@ void render_settings_page(Renderer *renderer) int tx = item_x + (item_w - t1_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t1_w > item_x + item_w - 4) tx = item_x + item_w - t1_w - 4; + + int touch_switch_x = item_x; + int touch_switch_y = y ; + static_add_area(touch_switch_x, touch_switch_y, item_w, item_h,2); + renderer->draw_text(tx, y + (item_h - lh) / 2, buf1, false, true); } y += item_h + gap; @@ -257,9 +302,20 @@ void render_settings_page(Renderer *renderer) // 2) 超时关机 if (settings_selected_idx == SET_TIMEOUT) { - const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + + const char *lt = "<"; + int lt_w = renderer->get_text_width(lt); + int timeout_left_x = margin_lr; + int timeout_left_y = y; + static_add_area(timeout_left_x, timeout_left_y, arrow_col_w, item_h,3); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); - const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + + const char *gt = ">"; + int gt_w = renderer->get_text_width(gt); + int timeout_right_x = page_w - arrow_col_w + margin_lr; + int timeout_right_y = y; + static_add_area(timeout_right_x, timeout_right_y, arrow_col_w, item_h,4); + renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_TIMEOUT) @@ -288,6 +344,11 @@ void render_settings_page(Renderer *renderer) int tx = item_x + (item_w - t2_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t2_w > item_x + item_w - 4) tx = item_x + item_w - t2_w - 4; + + int timeout_setting_x = item_x; + int timeout_setting_y = y; + static_add_area(timeout_setting_x, timeout_setting_y, item_w, item_h,5); + renderer->draw_text(tx, y + (item_h - lh) / 2, buf2, false, true); } y += item_h + gap; @@ -295,9 +356,20 @@ void render_settings_page(Renderer *renderer) // 3) 全刷周期 if (settings_selected_idx == SET_FULL_REFRESH) { - const char *lt = "<"; int lt_w = renderer->get_text_width(lt); + + const char *lt = "<"; + int lt_w = renderer->get_text_width(lt); + int full_refresh_left_x = margin_lr; + int full_refresh_left_y = y; + static_add_area(full_refresh_left_x, full_refresh_left_y, arrow_col_w, item_h,6); renderer->draw_text(margin_lr + (arrow_col_w - lt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, lt, false, true); - const char *gt = ">"; int gt_w = renderer->get_text_width(gt); + + const char *gt = ">"; + int gt_w = renderer->get_text_width(gt); + int full_refresh_right_x = page_w - arrow_col_w + margin_lr; + int full_refresh_right_y = y; + static_add_area(full_refresh_right_x, full_refresh_right_y, arrow_col_w, item_h,7); + renderer->draw_text(page_w - margin_lr - arrow_col_w + (arrow_col_w - gt_w) / 2, y + (item_h - renderer->get_line_height()) / 2, gt, false, true); } if (settings_selected_idx == SET_FULL_REFRESH) @@ -319,6 +391,11 @@ void render_settings_page(Renderer *renderer) int tx = item_x + (item_w - t3_w) / 2; if (tx < item_x + 4) tx = item_x + 4; if (tx + t3_w > item_x + item_w - 4) tx = item_x + item_w - t3_w - 4; + + int full_refresh_setting_x = item_x; + int full_refresh_setting_y = y; + static_add_area(full_refresh_setting_x, full_refresh_setting_y, item_w, item_h,8); + renderer->draw_text(tx, y + (item_h - lh) / 2, buf3, false, true); } y += item_h + gap; @@ -339,6 +416,11 @@ void render_settings_page(Renderer *renderer) const char *confirm = "确认"; int c_w = renderer->get_text_width(confirm); int c_h = renderer->get_line_height(); + + int confirm_button_x = confirm_x; + int confirm_button_y = confirm_y; + static_add_area(confirm_button_x, confirm_button_y, confirm_w, confirm_h,9); + renderer->draw_text(confirm_x + (confirm_w - c_w) / 2, confirm_y + (confirm_h - c_h) / 2, confirm, false, true); } @@ -474,4 +556,4 @@ bool handleSettingsPage(Renderer *renderer, UIAction action, bool needs_redraw) break; } return false; -} +} \ No newline at end of file diff --git a/epdiy-epub/src/main.cpp b/epdiy-epub/src/main.cpp index 49cbbd6..3f7957c 100644 --- a/epdiy-epub/src/main.cpp +++ b/epdiy-epub/src/main.cpp @@ -13,7 +13,9 @@ #include "bf0_pm.h" #include "epd_driver.h" #include "type.h" + #include "UIRegionsManager.h" + #undef LOG_TAG #undef DBG_LEVEL #define DBG_LEVEL DBG_LOG //DBG_INFO // @@ -84,6 +86,9 @@ typedef enum { } MainOption; void handleEpubTableContents(Renderer *renderer, UIAction action, bool needs_redraw); + +//阅读设置页面 + void handleEpub(Renderer *renderer, UIAction action) { if (!reader) @@ -1176,7 +1181,7 @@ extern "C" int main() { // dump out the epub list state - //rt_pm_request(PM_SLEEP_MODE_IDLE); + rt_pm_request(PM_SLEEP_MODE_IDLE); ulog_i("main", "epub list state num_epubs=%d", epub_list_state.num_epubs); ulog_i("main", "epub list state is_loaded=%d", epub_list_state.is_loaded); ulog_i("main", "epub list state selected_item=%d", epub_list_state.selected_item); @@ -1190,4 +1195,4 @@ extern "C" } return 0; } -} +} \ No newline at end of file From c369a1424f553a124207af386074c41d2fd985e5 Mon Sep 17 00:00:00 2001 From: minjiezhong <2556899070@qq.com> Date: Wed, 18 Mar 2026 17:48:09 +0800 Subject: [PATCH 27/27] Delete epdiy-epub/project/Kconfig.proj --- epdiy-epub/project/Kconfig.proj | 105 -------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 epdiy-epub/project/Kconfig.proj diff --git a/epdiy-epub/project/Kconfig.proj b/epdiy-epub/project/Kconfig.proj deleted file mode 100644 index 2180d7c..0000000 --- a/epdiy-epub/project/Kconfig.proj +++ /dev/null @@ -1,105 +0,0 @@ -#APP specific configuration. - -comment "------------Project configuration-----------" - -config CUSTOM_MEM_MAP - bool - select custom_mem_map - default y - - -choice EPD_EPUB_COLOR_DEPTH - prompt "Select output framebuffer color depth" - default EPDIY_EPUB_1BPP if LCD_USING_EPD_OPMO37A3 - default EPDIY_EPUB_4BPP if !LCD_USING_EPD_OPMO37A3 - config EPDIY_EPUB_1BPP - bool "EPDIY_EPUB_1BPP" - config EPDIY_EPUB_4BPP - bool "EPDIY_EPUB_4BPP" -endchoice - -if !BSP_USING_BUILT_LCD -#define the EPD connection type - config LCD_USING_EPD_SPI - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V12_SPI - default n - config BSP_LCDC_USING_EPD_8BIT - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V11 || BSP_USING_BOARD_SF32_OED_EPD_V12 - default n - -#define the EPD module name - config LCD_USING_OPM060D - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V11 || BSP_USING_BOARD_SF32_OED_EPD_V12 - default n - - config LCD_USING_EPD_YZC085_V100 - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V11 - default n - select BSP_LCDC_USING_EPD_8BIT - select TSC_USING_FT5446U_V01 if BSP_USING_TOUCHD - - config LCD_USING_EPD_YZC085_V100_V12 - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V12 - default n - select BSP_LCDC_USING_EPD_8BIT - select TSC_USING_GT967 if BSP_USING_TOUCHD - - config LCD_USING_EPD_OPMO37A3 - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V12_SPI - default n - select LCD_USING_EPD_SPI - select TSC_USING_FT6336U if BSP_USING_TOUCHD - - config LCD_USING_EPD_R7D005 - bool - default n - - -#define the touch controller name - config TSC_USING_FT5446U_V01 - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V11 - default n - - config TSC_USING_FT6336U - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V12_SPI - default n - - config TSC_USING_GT967 - bool - default y if BSP_USING_BOARD_SF32_OED_EPD_V12 - default n - - - config EPD_WAVEFORM_USE_BIN - bool "OPM060D use binary waveform" - depends on LCD_USING_OPM060D - default n - - - config LCD_HOR_RES_MAX - int - default 1448 if LCD_USING_EPD_R7D005 - default 1032 if LCD_USING_EPD_YZC085_V100 - default 1032 if LCD_USING_EPD_YZC085_V100_V12 - default 240 if LCD_USING_EPD_OPMO37A3 - config LCD_VER_RES_MAX - int - default 1072 if LCD_USING_EPD_R7D005 - default 758 if LCD_USING_EPD_YZC085_V100 - default 758 if LCD_USING_EPD_YZC085_V100_V12 - default 416 if LCD_USING_EPD_OPMO37A3 - config LCD_DPI - int - default 315 if LCD_USING_EPD_R7D005 - default 300 if LCD_USING_EPD_YZC085_V100 - default 300 if LCD_USING_EPD_YZC085_V100_V12 - default 130 if LCD_USING_EPD_OPMO37A3 -endif \ No newline at end of file