~ruther/CTU-FEE-B0B35APO-Semestral-project

85f0ec9e2c5f7bd6ff9f7368fdf4c950b2be2329 — František Boháček 4 years ago f181e32
feat: add files contextmenu
M file-browser/include/file_open.h => file-browser/include/file_open.h +5 -2
@@ 1,9 1,9 @@
#ifndef __FILE_OPEN_H__
#define __FILE_OPEN_H__

#include <stdbool.h>
#include "file_access.h"
#include "options.h"
#include <stdbool.h>

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);

A file-browser/include/window_contextmenu.h => file-browser/include/window_contextmenu.h +12 -0
@@ 0,0 1,12 @@
#ifndef __WINDOW_CONTEXTMENU_H__
#define __WINDOW_CONTEXTMENU_H__

#include "file_access.h"
#include "font.h"
#include "gui.h"
#include <stdbool.h>

bool window_contextmenu_open(gui_t *gui, font_t *font, fileaccess_state_t state,
                             file_t *file);

#endif // __WINDOW_CONTEXTMENU_H__

M file-browser/src/file_open.c => file-browser/src/file_open.c +1 -1
@@ 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");
}

M file-browser/src/window_browser.c => file-browser/src/window_browser.c +22 -0
@@ 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,

A file-browser/src/window_contextmenu.c => file-browser/src/window_contextmenu.c +199 -0
@@ 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 <stdbool.h>

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