From 6615fb42ecfa0deef95bea0eeac1297e869f2ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Tue, 29 Jun 2021 10:23:11 +0200 Subject: [PATCH] feat: add better navigation --- file-browser/src/gui_list_commands.c | 54 ++++++++++++++++++++++++++++ file-browser/src/window_browser.c | 50 +++++++++++++++++++++++++- lib-gui/include/gui.h | 4 +++ lib-gui/include/keyboard_const.h | 9 +++++ lib-gui/src/gui_list_container.c | 35 +++++++++++++----- 5 files changed, 142 insertions(+), 10 deletions(-) diff --git a/file-browser/src/gui_list_commands.c b/file-browser/src/gui_list_commands.c index 51d4df4d4abdfb3250fd7f7328f99e86e5482325..dc73fc568a4bbe69c8daecbc917a840cf95e5fa8 100644 --- a/file-browser/src/gui_list_commands.c +++ b/file-browser/src/gui_list_commands.c @@ -54,11 +54,65 @@ static void command_handler_move_up(void *state, int amount) { command_handler_move(state, UP, amount); } +static void command_handler_home(void *state, int amount) { + gui_list_command_state_t *click_state = (gui_list_command_state_t *)state; + if (click_state->window == click_state->gui->active_window) { + gui_list_set_selected_index(click_state->container, 0); + } +} + +static void command_handler_end(void *state, int amount) { + gui_list_command_state_t *click_state = (gui_list_command_state_t *)state; + if (click_state->window == click_state->gui->active_window) { + gui_list_set_selected_index(click_state->container, gui_list_get_items_count(click_state->container)); + } +} + +static void command_handler_page_down(void *state, int amount) { + gui_list_command_state_t *click_state = (gui_list_command_state_t *)state; + if (click_state->window == click_state->gui->active_window) { + uint32_t selected_index = gui_list_get_selected_index(click_state->container); + gui_list_set_selected_index( + click_state->container, + selected_index + + gui_list_get_visible_items_count(click_state->container)); + } +} + +static void command_handler_page_up(void *state, int amount) { + gui_list_command_state_t *click_state = (gui_list_command_state_t *)state; + if (click_state->window == click_state->gui->active_window) { + uint32_t selected_index = + gui_list_get_selected_index(click_state->container); + uint32_t visible_items = gui_list_get_visible_items_count(click_state->container); + + if (selected_index < visible_items) { + selected_index = 0; + } else { + selected_index -= visible_items; + } + + gui_list_set_selected_index( + click_state->container, + selected_index); + } +} + void gui_list_commands_register(commands_t *commands, gui_list_command_state_t *state) { commands_register(commands, IN_KEYBOARD, 13, command_handler_gui_list_clicked, state); commands_register(commands, IN_KEYBOARD, 'v', command_handler_gui_list_clicked, state); + commands_register(commands, IN_KEYBOARD, KEYBOARD_HOME, command_handler_home, + state); + commands_register(commands, IN_KEYBOARD, KEYBOARD_END, command_handler_end, + state); + + commands_register(commands, IN_KEYBOARD, KEYBOARD_PAGE_DOWN, + command_handler_page_down, state); + commands_register(commands, IN_KEYBOARD, KEYBOARD_PAGE_UP, + command_handler_page_up, state); + commands_register(commands, IN_KEYBOARD, KEYBOARD_DOWN, command_handler_move_down, state); commands_register(commands, IN_KEYBOARD, KEYBOARD_UP, command_handler_move_up, diff --git a/file-browser/src/window_browser.c b/file-browser/src/window_browser.c index 31e7f75da10421d5b6c35b38687c476a1c9aa5b3..63c3bd558386385791deefb583c1486929d661a2 100644 --- a/file-browser/src/window_browser.c +++ b/file-browser/src/window_browser.c @@ -14,6 +14,7 @@ #include "logger.h" #include "path.h" #include "renderer.h" +#include "keyboard_const.h" #include #include #include @@ -114,6 +115,45 @@ static void command_handler_exit(void *state, int amount) { } } +static void command_handler_jump_right(void *state, int amount) { + browser_window_state_t *bstate = (browser_window_state_t *)state; + if (bstate->gui->active_window == bstate->browser_window) { + uint32_t scroll_x = bstate->list_container->inner.list.scroll_x; + uint32_t current_x = 0; + + int i; + for (i = 0; i < COLUMNS_COUNT - 1; i++) { + current_x += bstate->column_widths[i]; + if (scroll_x < current_x) { + break; + } + } + + if (amount < 0) { + i --; + } else { + i++; + } + + if (i < 0) { + i = 0; + } else if (i > COLUMNS_COUNT - 1) { + i = COLUMNS_COUNT - 1; + } + + scroll_x = 0; + for (int j = 0; j < i; j++) { + scroll_x += bstate->column_widths[j]; + } + + bstate->list_container->inner.list.scroll_x = scroll_x; + } +} + +static void command_handler_jump_left(void *state, int amount) { + command_handler_jump_right(state, -amount); +} + static void *browser_window_construct(window_t *window, void *state) { browser_window_state_t *bstate = (browser_window_state_t *)state; logger_t *logger = bstate->gui->logger; @@ -137,7 +177,7 @@ static void *browser_window_construct(window_t *window, void *state) { // group components init component_t path_text = gui_text_create(&bstate->text_state, 3, 3, bstate->gui->size.x, 0); component_t line_component = gui_line_create(&WHITE_PIXEL, 0, path_text.height + path_text.y + 3, 1000, 1); - + gui_group_container_add_component(&window->containers[1], path_text); bstate->line_component = gui_group_container_add_component(&window->containers[1], line_component); @@ -153,6 +193,10 @@ static void *browser_window_construct(window_t *window, void *state) { gui_list_commands_register(bstate->gui->commands, &bstate->click_state); commands_register(bstate->gui->commands, IN_KEYBOARD, 'e', command_handler_exit, state); + commands_register(bstate->gui->commands, IN_KEYBOARD, KEYBOARD_JUMP_RIGHT, + command_handler_jump_right, state); + commands_register(bstate->gui->commands, IN_KEYBOARD, KEYBOARD_JUMP_LEFT, + command_handler_jump_left, state); return state; } @@ -161,6 +205,10 @@ static void browser_window_item_clicked(container_t *container, void *state, uint32_t selected_index) { browser_window_state_t *bstate = (browser_window_state_t *)state; + if (bstate->gui->active_window != bstate->browser_window) { + return; + } + logger_t *logger = bstate->gui->logger; file_t current_file = bstate->current_directory->files[selected_index]; diff --git a/lib-gui/include/gui.h b/lib-gui/include/gui.h index ae689a2780b25630f43eeacf876edd675e6fde81..728c5ec5da27977cd516b05d642c72b616d0e276 100644 --- a/lib-gui/include/gui.h +++ b/lib-gui/include/gui.h @@ -353,6 +353,8 @@ container_t gui_list_container_create(void *state, uint32_t items_count, */ uint32_t gui_list_get_selected_index(container_t *container); +void gui_list_set_selected_index(container_t *container, uint32_t index); + /** * @brief Scroll list container by x, y * @details Increase scroll coordinates by x, y so different view arrea is shown @@ -389,5 +391,7 @@ bool gui_list_container_set_render_function(container_t *container, void gui_list_container_render(gui_t *gui, container_t *container); void gui_list_container_update(gui_t *gui, container_t *container); +uint32_t gui_list_get_visible_items_count(container_t *container); +uint32_t gui_list_get_items_count(container_t *container); #endif // __GUI_H__ diff --git a/lib-gui/include/keyboard_const.h b/lib-gui/include/keyboard_const.h index 9dfb2ee268e6882647fee0d98319fbb974b4c319..c9f5e0d9bb8a50ad3a2f97b195d6bc3907933a18 100644 --- a/lib-gui/include/keyboard_const.h +++ b/lib-gui/include/keyboard_const.h @@ -4,3 +4,12 @@ #define KEYBOARD_UP 'k' #define KEYBOARD_ZOOM_IN 'z' #define KEYBOARD_ZOOM_OUT 'x' + +#define KEYBOARD_HOME 'n' +#define KEYBOARD_END 'm' + +#define KEYBOARD_PAGE_UP 'u' +#define KEYBOARD_PAGE_DOWN 'i' + +#define KEYBOARD_JUMP_LEFT 'y' +#define KEYBOARD_JUMP_RIGHT 'o' diff --git a/lib-gui/src/gui_list_container.c b/lib-gui/src/gui_list_container.c index cf01508ee56a02ded1c78bb209ebf868d6c771a8..abef404aa561946c9a1f1ad9c3d1e52f32ba7f26 100644 --- a/lib-gui/src/gui_list_container.c +++ b/lib-gui/src/gui_list_container.c @@ -123,6 +123,31 @@ uint32_t gui_list_get_selected_index(container_t *container) { return container->inner.list.selected_index; } +void gui_list_set_selected_index(container_t *container, uint32_t index) { + if (index >= container->inner.list.items_count) { + index = container->inner.list.items_count - 1; + } + + container->inner.list.selected_index = index; +} + +uint32_t gui_list_get_items_count(container_t *container) { + return container->inner.list.items_count; +} + +uint32_t gui_list_get_visible_items_count(container_t *container) { + list_container_t list = container->inner.list; + uint16_t item_full_height = list.item_height + list.item_padding * 2; + uint32_t container_height = container->height; + + bool header = list.render_header_fn != NULL; + if (header) { + container_height -= item_full_height; + } + + return (double)(container_height) / item_full_height - 1; +} + void gui_list_container_update(gui_t *gui, container_t *container) { list_container_t list = container->inner.list; @@ -138,16 +163,8 @@ void gui_list_container_update(gui_t *gui, container_t *container) { first_visible_index = 0; } - uint32_t container_height = container->height; - - bool header = list.render_header_fn != NULL; - if (header) { - container_height -= item_full_height; - } - - uint32_t items_count = (double)(container_height) / item_full_height - 1; + uint32_t items_count = gui_list_get_visible_items_count(container); uint32_t last_visible_index = first_visible_index + items_count; - uint32_t selected_index = list.selected_index; if (selected_index < first_visible_index) {