2023-02-05 01:02:48 +08:00

176 lines
7.1 KiB
C

#include <stdint.h>
#include "keypad.h"
#include "st7735.h"
#include "asciifont.h"
#include "ui_menu.h"
#include "ui_utils.h"
#define LIST_STYLE_SELECTED_COLOR_BG ST7735_COLOR565(0x40, 0x40, 0x40)
#define LIST_STYLE_OFFSET_LEFT 32
#define UI_HALF_Y (UI_Y + (UI_H / 2))
#define LIST_PAGE_SIZE (UI_H / font_unifont_8x16->char_height)
#define LIST_PAGE_SIZE_HALF ((LIST_PAGE_SIZE + 1) / 2)
#define LIST_ITEM_LEVEL(p) ((p < LIST_PAGE_SIZE_HALF) ? (p) : (LIST_PAGE_SIZE - p - 1))
#define UI_LIST_OFFSET_X(p) (UI_X + (LIST_STYLE_OFFSET_LEFT * LIST_ITEM_LEVEL(p) / (LIST_PAGE_SIZE_HALF - 1)) + 8)
#define UI_LIST_OFFSET_Y(p) (UI_Y + (font_unifont_8x16->char_height * p))
#define UI_LIST_WIDTH(p) (UI_W - (LIST_STYLE_OFFSET_LEFT * LIST_ITEM_LEVEL(p) / (LIST_PAGE_SIZE_HALF - 1)) - 8)
#define U8_RESET 255
/*
0
1
2
3
4
5
6
7
8
*/
static uint16_t get_item_count(uiu_GetStrItemFunc get_item) {
uint16_t len = 0;
while (get_item(len).len > 0) {
len ++;
}
return len;
}
static void render_page_number(uint8_t curr, uint8_t total) {
uint8_t number_str[4] = {0, 0, 0, 0};
uint8_t scale = 100;
uint8_t num_pos = 0;
while (scale > 0) {
uint8_t num = (curr / scale) % 10;
scale /= 10;
if (num == 0 && num_pos == 0) continue;
number_str[num_pos] = '0' + num;
num_pos ++;
}
uiu_text_area(font_quan_8x8, number_str, 4,
UI_X, UI_HALF_Y - 1 - font_quan_8x8->char_height - 1,
font_quan_8x8->char_width * 3, font_quan_8x8->char_height,
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_YELLOW, ST7735_BLACK
);
number_str[0] = 0;
number_str[1] = 0;
number_str[2] = 0;
number_str[3] = 0;
scale = 100;
num_pos = 0;
while (scale > 0) {
uint8_t num = (total / scale) % 10;
scale /= 10;
if (num == 0 && num_pos == 0) continue;
number_str[num_pos] = '0' + num;
num_pos ++;
}
uiu_text_area(font_quan_8x8, number_str, 4,
UI_X, UI_HALF_Y + 2,
font_quan_8x8->char_width * 3, font_quan_8x8->char_height,
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_YELLOW, ST7735_BLACK
);
}
IndexResult iui_list_select(const uint8_t *title, uint32_t len, uiu_GetStrItemFunc get_item, uint16_t init_index) {
uint16_t item_count = get_item_count(get_item);
uint16_t pointer = init_index % item_count;
uint8_t tmp_pointer = U8_RESET;
uint8_t last_pointer = U8_RESET;
uint16_t page_start = (pointer / LIST_PAGE_SIZE) * LIST_PAGE_SIZE;
printf("item count: %u\n", item_count);
// clear
ST7735_FillScreen(ST7735_BLACK);
// render title
uiu_title(title, len);
// render line
ST7735_DrawLine(UI_X, UI_Y + font_unifont_8x16->char_height, LIST_STYLE_OFFSET_LEFT - 1, UI_HALF_Y - 1, ST7735_YELLOW);
ST7735_DrawLine(UI_X, UI_Y + UI_H - font_unifont_8x16->char_height - 1, LIST_STYLE_OFFSET_LEFT - 1, UI_HALF_Y, ST7735_YELLOW);
ST7735_FillRectangle(UI_X, UI_HALF_Y - 1, LIST_STYLE_OFFSET_LEFT - 1, 1, ST7735_YELLOW);
while (1) {
uint8_t event = kp_query();
uint8_t et = kp_Type(event);
uint8_t ev = kp_Value(event);
// process event
if (et == kp_ROTATE_RIGHT || et == kp_ROTATE_LEFT) {
if (et == kp_ROTATE_RIGHT) {
pointer += ev;
} else {
pointer += (0x7FFF / item_count) * item_count;
pointer -= ev;
}
pointer %= item_count;
if (((pointer / LIST_PAGE_SIZE) * LIST_PAGE_SIZE) != page_start) {
last_pointer = U8_RESET;
page_start = ((pointer / LIST_PAGE_SIZE) * LIST_PAGE_SIZE);
}
tmp_pointer = U8_RESET;
printf("Move list pointer to %u\n", pointer);
} else if (et == kp_SHORT_CLICK) {
if (ev == kp_KEYENCODER) {
discare_kp_events();
printf("Confirm list item %u\n", pointer);
IndexResult ret = {pointer, 1};
return ret;
}
} else if (et == kp_LONG_PRESS) {
if (ev == kp_KEYENCODER) {
discare_kp_events();
printf("Cancel list item %u\n", pointer);
IndexResult ret = {pointer, 0};
return ret;
}
} else if (et != kp_NOP) {
printf("Unhandled event: %u %u\n", et, ev);
}
// render items
if (tmp_pointer == U8_RESET) {
// need render
if (last_pointer == U8_RESET) {
// render all
render_page_number((pointer / LIST_PAGE_SIZE) + 1, (item_count + LIST_PAGE_SIZE - 1) / LIST_PAGE_SIZE);
for (tmp_pointer = 0; tmp_pointer < LIST_PAGE_SIZE; tmp_pointer ++) {
uint16_t current = page_start + tmp_pointer;
if (current >= item_count) {
uiu_text_area(font_unifont_8x16, u8str(" "), 1,
UI_LIST_OFFSET_X(tmp_pointer), UI_LIST_OFFSET_Y(tmp_pointer),
UI_LIST_WIDTH(tmp_pointer), font_unifont_8x16->char_height,
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_WHITE, ST7735_BLACK
);
continue;
}
StrItem item = get_item(current);
if (current == pointer) {
uiu_text_area(font_unifont_8x16, item.text, item.len,
UI_LIST_OFFSET_X(tmp_pointer), UI_LIST_OFFSET_Y(tmp_pointer),
UI_LIST_WIDTH(tmp_pointer), font_unifont_8x16->char_height,
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_GREEN, LIST_STYLE_SELECTED_COLOR_BG
);
last_pointer = tmp_pointer;
} else {
uiu_text_area(font_unifont_8x16, item.text, item.len,
UI_LIST_OFFSET_X(tmp_pointer), UI_LIST_OFFSET_Y(tmp_pointer),
UI_LIST_WIDTH(tmp_pointer), font_unifont_8x16->char_height,
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_WHITE, ST7735_BLACK
);
}
}
} else {
StrItem item = get_item(page_start + last_pointer);
uiu_text_area(font_unifont_8x16, item.text, item.len,
UI_LIST_OFFSET_X(last_pointer), UI_LIST_OFFSET_Y(last_pointer),
UI_LIST_WIDTH(last_pointer), font_unifont_8x16->char_height,
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_WHITE, ST7735_BLACK
);
last_pointer = pointer - page_start;
StrItem item_curr = get_item(pointer);
uiu_text_area(font_unifont_8x16, item_curr.text, item_curr.len,
UI_LIST_OFFSET_X(last_pointer), UI_LIST_OFFSET_Y(last_pointer),
UI_LIST_WIDTH(last_pointer), font_unifont_8x16->char_height,
uiu_ALIGN_HCENTER | uiu_ALIGN_VCENTER, ST7735_GREEN, LIST_STYLE_SELECTED_COLOR_BG
);
}
tmp_pointer = 0;
}
}
}