diff --git a/stm-firmware/include/reflow-controller/ui/menu.h b/stm-firmware/include/reflow-controller/ui/menu.h index 7f0fb28..748091d 100644 --- a/stm-firmware/include/reflow-controller/ui/menu.h +++ b/stm-firmware/include/reflow-controller/ui/menu.h @@ -47,7 +47,9 @@ struct lcd_menu { }; struct menu_list { + void (*update_display)(uint8_t row, const char *data); const char **entry_names; + uint32_t entry_count; uint32_t currently_selected; const menu_func_t *submenu_list; }; @@ -62,6 +64,12 @@ void menu_entry_enter(struct lcd_menu *menu, menu_func_t parent_func, bool handl void menu_override_lcd_output(struct lcd_menu *menu, uint8_t row_num, const char *text); -void menu_list_display(struct menu_list *list, uint8_t top_row, uint8_t bottom_row); +void menu_list_display(struct menu_list *list, uint32_t top_row, uint32_t bottom_row); + +void menu_list_compute_count(struct menu_list *list); + +void menu_list_scroll_down(struct menu_list *list); + +void menu_list_scroll_up(struct menu_list *list); #endif /* __MENU_H__ */ diff --git a/stm-firmware/ui/menu.c b/stm-firmware/ui/menu.c index d708718..85427b0 100644 --- a/stm-firmware/ui/menu.c +++ b/stm-firmware/ui/menu.c @@ -20,6 +20,7 @@ #include #include +#include void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum button_state push_button) { @@ -38,9 +39,9 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto if (menu->active_entry_type == MENU_ENTRY_FIRST_ENTER) { - menu->active_entry(menu, menu->active_entry_type, menu->init_parent); + menu->active_entry(menu, menu->active_entry_type, menu->init_parent); } else { - menu->active_entry(menu, menu->active_entry_type, NULL); + menu->active_entry(menu, menu->active_entry_type, NULL); } if (menu->active_entry_type != MENU_ENTRY_CONTINUE && tmp == menu->active_entry) { @@ -95,9 +96,89 @@ void menu_override_lcd_output(struct lcd_menu *menu, uint8_t row_num, const char menu->update_display(row_num, text); } -void menu_list_display(struct menu_list *list, uint8_t top_row, uint8_t bottom_row) +void menu_list_display(struct menu_list *list, uint32_t top_row, uint32_t bottom_row) { - (void)list; - (void)top_row; - (void)bottom_row; + uint8_t row_count; + uint32_t mid_row; + uint32_t count_above_mid; + uint32_t count_below_mid; + uint32_t start_index; + uint32_t current_row; + uint32_t current_idx; + char workbuff[64]; + + if (!list || !list->update_display) + return; + + if (bottom_row < top_row) + return; + + if (list->entry_count == 0) { + for (current_row = top_row; current_row <= bottom_row; current_row++) { + list->update_display((uint8_t)current_row, ""); + } + return; + } + + /* Calculate list parameters */ + row_count = top_row - bottom_row + 1; + mid_row = (top_row + bottom_row) / 2; + count_above_mid = mid_row - top_row; + count_below_mid = bottom_row - mid_row; + + /* Check if there are more elements above the and below the currently selected one that can be displayed. in this case position + * active entry in center + */ + if (list->currently_selected > count_above_mid && (list->entry_count - list->currently_selected - 1) > count_below_mid) { + start_index = list->currently_selected - count_above_mid; + } else if (list->currently_selected < count_above_mid) { + start_index = 0; + } else if ((list->entry_count - list->currently_selected - 1) < count_below_mid) { + if (list->entry_count < row_count) { + start_index = 0; + } + start_index = list->entry_count - row_count; + } else { + start_index = 0; + } + + for (current_row = top_row, current_idx = start_index; current_row <= bottom_row; current_row++, current_idx++) { + if (current_idx >= list->entry_count) + break; + + snprintf(workbuff, sizeof(workbuff), "%c%s", (current_idx == list->currently_selected ? '>' : ' '), list->entry_names[current_idx]); + workbuff[sizeof(workbuff)-1] = 0; + list->update_display((uint8_t)current_row, workbuff); + } + +} + +void menu_list_compute_count(struct menu_list *list) +{ + uint32_t count = 0; + + if (!list) + return; + + for (count = 0; list->entry_names[count] != NULL; count++); + list->entry_count = count; +} + +void menu_list_scroll_down(struct menu_list *list) +{ + if (!list) + return; + + if (list->currently_selected < list->entry_count - 1) { + list->currently_selected++; + } +} + +void menu_list_scroll_up(struct menu_list *list) +{ + if (!list) + return; + + if (list->currently_selected > 0) + list->currently_selected--; }