#include #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; } } }