From 85f0ec9e2c5f7bd6ff9f7368fdf4c950b2be2329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Tue, 29 Jun 2021 17:18:43 +0200 Subject: [PATCH] feat: add files contextmenu --- file-browser/include/file_open.h | 7 +- file-browser/include/window_contextmenu.h | 12 ++ file-browser/src/file_open.c | 2 +- file-browser/src/window_browser.c | 22 +++ file-browser/src/window_contextmenu.c | 199 ++++++++++++++++++++++ 5 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 file-browser/include/window_contextmenu.h create mode 100644 file-browser/src/window_contextmenu.c diff --git a/file-browser/include/file_open.h b/file-browser/include/file_open.h index fe6141bd80a05454edd95ceee0bb7d9a1f5f4e1d..1a4da5350e0aa906e00a521f9e6bcceb72695161 100644 --- a/file-browser/include/file_open.h +++ b/file-browser/include/file_open.h @@ -1,9 +1,9 @@ #ifndef __FILE_OPEN_H__ #define __FILE_OPEN_H__ -#include #include "file_access.h" #include "options.h" +#include typedef enum { OPENED_NONE, @@ -24,7 +24,10 @@ typedef struct { } opened_file_state_t; opened_file_state_t file_open(file_t *file, exec_options_t *options, - fileaccess_state_t state); + fileaccess_state_t state); + +opened_file_state_t file_open_text(file_t *file, exec_options_t *options, + fileaccess_state_t state); opened_file_state_t file_open_mime_raw(char *file, exec_options_t *options, char *mime); diff --git a/file-browser/include/window_contextmenu.h b/file-browser/include/window_contextmenu.h new file mode 100644 index 0000000000000000000000000000000000000000..387a78708374ff2f0098e26922605e6a2e53fc07 --- /dev/null +++ b/file-browser/include/window_contextmenu.h @@ -0,0 +1,12 @@ +#ifndef __WINDOW_CONTEXTMENU_H__ +#define __WINDOW_CONTEXTMENU_H__ + +#include "file_access.h" +#include "font.h" +#include "gui.h" +#include + +bool window_contextmenu_open(gui_t *gui, font_t *font, fileaccess_state_t state, + file_t *file); + +#endif // __WINDOW_CONTEXTMENU_H__ diff --git a/file-browser/src/file_open.c b/file-browser/src/file_open.c index 09c47a1392a88271be947eac742f3a40a765ba3b..0e3e5e1ee11739d16316c5dd69912948d9e1bcb1 100644 --- a/file-browser/src/file_open.c +++ b/file-browser/src/file_open.c @@ -73,7 +73,7 @@ static opened_file_state_t file_open_mime(file_t *file, exec_options_t *options, return file_open_mime_raw(local_path, options, mime); } -static opened_file_state_t file_open_text(file_t *file, exec_options_t *options, +opened_file_state_t file_open_text(file_t *file, exec_options_t *options, fileaccess_state_t state) { return file_open_mime(file, options, state, "text"); } diff --git a/file-browser/src/window_browser.c b/file-browser/src/window_browser.c index 08976f2a94d37e719ecb1afe2e73c86d985b0cde..fb2c6c5fa3d60933df6bb809b910777050c9fef2 100644 --- a/file-browser/src/window_browser.c +++ b/file-browser/src/window_browser.c @@ -2,6 +2,7 @@ #include "dialog.h" #include "file_browser_utils.h" #include "display_utils.h" +#include "window_contextmenu.h" #include "gui_list_table.h" #include "file_access.h" #include "file_open.h" @@ -83,6 +84,25 @@ static void command_handler_exit(void *state, int amount) { } } +static void command_handler_contextmenu(void *state, int amount) { + browser_window_state_t *bstate = (browser_window_state_t *)state; + if (bstate->gui->active_window == bstate->browser_window) { + uint32_t selected_index = gui_list_get_selected_index(bstate->list_container); + file_t *file = &bstate->current_directory->files[selected_index]; + + if (file->type != FT_FILE) { + logger_warn(bstate->gui->logger, __FILE__, __FUNCTION__, __LINE__, + "Context menus are for files only"); + return; + } + + logger_info(bstate->gui->logger, __FILE__, __FUNCTION__, __LINE__, + "Context menu will open"); + + window_contextmenu_open(bstate->gui, bstate->font, bstate->state, file); + } +} + 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) { @@ -166,6 +186,8 @@ 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, 'c', + command_handler_contextmenu, 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, diff --git a/file-browser/src/window_contextmenu.c b/file-browser/src/window_contextmenu.c new file mode 100644 index 0000000000000000000000000000000000000000..93216d7dde5f746c51b752cfe27883b3f107edf7 --- /dev/null +++ b/file-browser/src/window_contextmenu.c @@ -0,0 +1,199 @@ +#include "file_access.h" +#include "file_browser_utils.h" +#include "file_open.h" +#include "font.h" +#include "gui.h" +#include "gui_component_text.h" +#include "gui_component_line.h" +#include "gui_list_commands.h" +#include "gui_window_info.h" +#include "renderer.h" +#include + +#define CONTEXTMENU_OPEN_INDEX 0 +#define CONTEXTMENU_OPEN_TEXT_INDEX 1 +#define CONTEXTMENU_BACK_INDEX 2 + +typedef struct { + bool running; + gui_t *gui; + + fileaccess_state_t state; + file_t *file; + + window_t *contextmenu_window; + + container_t *list_container; + component_t *line_component; + + text_t name_state; + + font_t *font; + + gui_list_command_state_t click_state; +} contextmenu_window_state_t; + +static bool contextmenu_window_list_render_item(void *state, uint32_t index, + renderer_t *renderer, int16_t beg_x, + int16_t beg_y, + display_pixel_t color); + +static void contextmenu_window_item_clicked(container_t *container, void *state, + uint32_t selected_index); + +static void *contextmenu_window_construct(window_t *window, void *state); +static bool contextmenu_window_running(void *state); +static void contextmenu_window_job(void *state); + +gui_container_info_t contextmenu_window_container_info[] = { + {.type = CONT_TABLE, + .payload.list = {.item_height = 16, + .render_item_fn = contextmenu_window_list_render_item, + .render_header_fn = NULL}}, + {.type = CONT_GROUP, .payload.group.components_count = 2}}; + +window_info_t contextmenu_window_info = { + .containers_count = 2, + .containers = contextmenu_window_container_info, + .construct = contextmenu_window_construct}; + +bool window_contextmenu_open(gui_t *gui, font_t *font, fileaccess_state_t state, + file_t *file) { + logger_t *logger = gui->logger; + logger_info(logger, __FILE__, __FUNCTION__, __LINE__, + "Opening initial window"); + + contextmenu_window_state_t cstate = { + .running = true, + .gui = gui, + .font = font, + .file = file, + .state = state, + }; + + uint16_t commands_state = commands_save_state(gui->commands); + bool success = + gui_window_init_and_loop(gui, &cstate, contextmenu_window_info, + contextmenu_window_running, contextmenu_window_job); + commands_restore_state(gui->commands, commands_state); + logger_info(logger, __FILE__, __FUNCTION__, __LINE__, + "Initial window closed"); + + return success; +} + +static bool contextmenu_window_list_render_item(void *state, uint32_t index, + renderer_t *renderer, + int16_t beg_x, int16_t beg_y, + display_pixel_t color) { + contextmenu_window_state_t *cstate = (contextmenu_window_state_t *)state; + char *data; + switch (index) { + case CONTEXTMENU_OPEN_INDEX: + data = "OPEN"; + break; + case CONTEXTMENU_OPEN_TEXT_INDEX: + data = "SHOW TEXT"; + break; + case CONTEXTMENU_BACK_INDEX: + data = "BACK"; + break; + default: + return false; + } + + renderer_write_string(renderer, beg_x, beg_y, 0, cstate->font, data, color); + + return true; +} + +static void contextmenu_window_item_clicked(container_t *container, void *state, + uint32_t selected_index) { + contextmenu_window_state_t *cstate = (contextmenu_window_state_t *)state; + logger_t *logger = cstate->gui->logger; + switch (selected_index) { + case CONTEXTMENU_OPEN_INDEX: + { + logger_info(logger, __FILE__, __FUNCTION__, __LINE__, + "Opening file"); + opened_file_state_t opened = + file_open(cstate->file, browser_exec_options, cstate->state); + file_browser_handle_opened_file(opened, cstate->gui, cstate->font); + } + break; + case CONTEXTMENU_OPEN_TEXT_INDEX: { + logger_info(logger, __FILE__, __FUNCTION__, __LINE__, "Opening text"); + opened_file_state_t opened = + file_open_text(cstate->file, browser_exec_options, cstate->state); + file_browser_handle_opened_file(opened, cstate->gui, cstate->font); + } + break; + case CONTEXTMENU_BACK_INDEX: + logger_info(logger, __FILE__, __FUNCTION__, __LINE__, "Going back"); + cstate->running = false; + break; + default: + break; + } +} + +static void command_handler_exit(void *state, int amount) { + contextmenu_window_state_t *cstate = (contextmenu_window_state_t *)state; + cstate->running = false; +} + +static void *contextmenu_window_construct(window_t *window, void *state) { + contextmenu_window_state_t *cstate = (contextmenu_window_state_t *)state; + logger_t *logger = cstate->gui->logger; + logger_info(logger, __FILE__, __FUNCTION__, __LINE__, + "Constructing contextmenu window"); + cstate->list_container = &window->containers[0]; + cstate->contextmenu_window = window; + + cstate->click_state.container = cstate->list_container; + cstate->click_state.state = state; + cstate->click_state.clicked = contextmenu_window_item_clicked; + cstate->click_state.font = cstate->font; + cstate->click_state.gui = cstate->gui; + cstate->click_state.window = window; + + cstate->name_state.font = cstate->font; + cstate->name_state.line = cstate->file->name; + cstate->name_state.color = WHITE_PIXEL; + + // containers init + // group components init + component_t path_text = gui_text_create(&cstate->name_state, 3, 3, cstate->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); + cstate->line_component = + gui_group_container_add_component(&window->containers[1], line_component); + + // list init + gui_container_info_init(cstate->list_container, cstate, + 3, 5, + cstate->font->size / 2 + 3); + cstate->list_container->width = cstate->gui->size.x - 20; + cstate->list_container->height = cstate->gui->size.y - cstate->list_container->y - 20; + + // commands register + gui_list_commands_register(cstate->gui->commands, &cstate->click_state); + commands_register(cstate->gui->commands, IN_KEYBOARD, 'e', + command_handler_exit, state); + + return state; +} + +static bool contextmenu_window_running(void *state) { + contextmenu_window_state_t *cstate = (contextmenu_window_state_t*)state; + return cstate->running; +} + +static void contextmenu_window_job(void *state) { + contextmenu_window_state_t *cstate = (contextmenu_window_state_t *)state; + cstate->line_component->y = cstate->font->size + 5; + cstate->list_container->y = cstate->line_component->y / 2; + gui_list_container_set_item_height(cstate->list_container, + cstate->font->size); +}