#include "window_browser.h"
#include "display_utils.h"
#include "file_access.h"
#include "file_open.h"
#include "gui.h"
#include "gui_component_text.h"
#include "gui_container_info.h"
#include "gui_list_commands.h"
#include "gui_component_line.h"
#include "gui_window_info.h"
#include "input.h"
#include "logger.h"
#include "path.h"
#include "renderer.h"
typedef struct {
bool running;
gui_t *gui;
container_t *list_container;
window_t *browser_window;
font_t *font;
gui_list_command_state_t click_state;
text_t text_state;
directory_t *current_directory;
fileaccess_state_t state;
} browser_window_state_t;
static bool browser_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 bool browser_window_list_render_header(void *state, uint32_t index,
renderer_t *renderer,
int16_t beg_x, int16_t beg_y,
display_pixel_t color);
static void browser_window_item_clicked(container_t *container, void *state,
uint32_t selected_index);
static void *browser_window_construct(window_t *window, void *state);
static bool browser_window_running(void *state);
static void browser_window_job(void *state);
gui_container_info_t window_browser_containers[] = {
{.type = CONT_TABLE,
.payload.list = {.render_item_fn = browser_window_list_render_item,
.render_header_fn = browser_window_list_render_header,
.item_height = 16}},
{.type = CONT_GROUP, .payload.group.components_count = 2},
};
window_info_t window_browser_info = {
.construct = browser_window_construct,
.containers_count = 2,
.containers = window_browser_containers,
};
bool window_browser_open_local(gui_t *gui, font_t *font) {
fileaccess_state_t state = fileaccess_init(&local_file_access, NULL);
return window_browser_open(gui, font, state);
}
bool window_browser_open(gui_t *gui, font_t *font, fileaccess_state_t state) {
directory_or_error_t root = fileaccess_root_list(state);
if (root.error) {
fileaccess_log_error(gui->logger, root.error);
// TODO: dialog
return false;
}
browser_window_state_t bstate = {
.state = state,
.gui = gui,
.font = font,
.current_directory = root.payload.directory,
.running = true,
};
uint16_t commands_state = commands_save_state(gui->commands);
gui_window_init_and_loop(gui, &bstate, window_browser_info, browser_window_running,
browser_window_job);
commands_restore_state(gui->commands, commands_state);
return true;
}
static void command_handler_exit(void *state, int amount) {
browser_window_state_t *bstate = (browser_window_state_t *)state;
if (bstate->gui->active_window == bstate->browser_window) {
bstate->running = false;
}
}
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;
logger_info(logger, __FILE__, __FUNCTION__, __LINE__,
"Constructing browser window");
bstate->list_container = &window->containers[0];
bstate->browser_window = window;
bstate->click_state.container = bstate->list_container;
bstate->click_state.state = state;
bstate->click_state.clicked = browser_window_item_clicked;
bstate->click_state.font = bstate->font;
bstate->click_state.gui = bstate->gui;
bstate->click_state.window = window;
bstate->text_state.font = bstate->font;
bstate->text_state.line = bstate->current_directory->path;
bstate->text_state.color = WHITE_PIXEL;
// containers init
// group components init
component_t path_text = gui_text_create(&bstate->text_state, 3, 3, 0, 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);
gui_group_container_add_component(&window->containers[1], line_component);
// list init
gui_container_info_init(bstate->list_container, bstate,
bstate->current_directory->files_count, 5,
5 + line_component.height + 5);
bstate->list_container->width = bstate->gui->size.x - 20;
bstate->list_container->height = bstate->gui->size.y - bstate->list_container->y - 20;
// commands register
gui_list_commands_register(bstate->gui->commands, &bstate->click_state);
commands_register(bstate->gui->commands, IN_KEYBOARD, 'e',
command_handler_exit, state);
return state;
}
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;
logger_t *logger = bstate->gui->logger;
file_t current_file = bstate->current_directory->files[selected_index];
if (current_file.type == FT_FILE) {
// open
logger_info(logger, __FILE__, __FUNCTION__, __LINE__, "Opening file %s",
current_file.name);
file_operation_error_t error = file_open(¤t_file, browser_exec_options, bstate->state);
if (error != FILOPER_SUCCESS) {
fileaccess_log_error(logger, error);
} else {
logger_info(logger, __FILE__, __FUNCTION__, __LINE__, "Successfully returned from executing file.");
}
} else if (current_file.type == FT_FOLDER || current_file.type == FT_OTHER) {
char new_dir_path[path_join_memory_size(bstate->current_directory->path, current_file.name)];
path_join(bstate->current_directory->path, current_file.name, new_dir_path);
directory_or_error_t data = fileaccess_directory_list(bstate->state, new_dir_path);
if (data.error) {
// show error
fileaccess_log_error(logger, data.payload.error);
} else {
fileaccess_directory_close(bstate->state, bstate->current_directory);
bstate->current_directory = data.payload.directory;
bstate->text_state.line = bstate->current_directory->path;
gui_list_container_set_state(bstate->list_container, bstate, bstate->current_directory->files_count);
logger_info(logger, __FILE__, __FUNCTION__, __LINE__, "Opening directory %s", bstate->current_directory->path);
}
}
}
static bool browser_window_list_render_item(void *state, uint32_t index,
renderer_t *renderer, int16_t beg_x,
int16_t beg_y,
display_pixel_t color) {
browser_window_state_t *bstate = (browser_window_state_t *)state;
logger_t *logger = bstate->gui->logger;
if (index >= bstate->current_directory->files_count) {
logger_error(logger, __FILE__, __FUNCTION__, __LINE__, "Tried to reach item out of index");
return false;
}
file_t file = bstate->current_directory->files[index];
renderer_write_string(renderer, beg_x, beg_y, 0, bstate->font, file.name,
color);
return true;
}
static bool browser_window_list_render_header(void *state, uint32_t index,
renderer_t *renderer,
int16_t beg_x, int16_t beg_y,
display_pixel_t color) {
browser_window_state_t *bstate = (browser_window_state_t *)state;
renderer_write_string(renderer, beg_x, beg_y, 0, bstate->font, "This is header", color);
return true;
}
static bool browser_window_running(void *state) {
browser_window_state_t *bstate = (browser_window_state_t*)state;
return bstate->running;
}
static void browser_window_job(void *state) {
browser_window_state_t *bstate = (browser_window_state_t *)state;
if (!bstate->running) {
// cleanup
fileaccess_directory_close(bstate->state, bstate->current_directory);
}
}