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

61727753cc0b74adb9be0fcdb4accfe47a1af0f3 — František Boháček 3 years ago 03e3847
feat: add list container selected index, padding and colors
M file-browser/include/extern_file_access.h => file-browser/include/extern_file_access.h +18 -1
@@ 3,7 3,24 @@

#include "file_access.h"

fileaccess_state_t extern_fileaccess_init_state(void *data);
/**
 * @brief Initialize extern fileaccess state with given path to device
 * 
 * @param data path to device 
 * @return fileaccess_state_t 
 */
fileaccess_state_t extern_fileaccess_init_state(void *device);

/**
 * @brief Deinitialize extern fileaccess state
 * 
 * All allocated memory for the state will be freed and
 * associated device unmounted so it can be ejected
 * 
 * @param state 
 * @return true Everything was cleaned
 * @return false Could not clean everything
 */
bool extern_fileaccess_deinit_state(fileaccess_state_t state);

directory_or_error_t extern_fileaccess_directory_list(fileaccess_state_t state,

M file-browser/include/file_execute.h => file-browser/include/file_execute.h +35 -5
@@ 1,17 1,47 @@
#include <unistd.h>
#include <stdbool.h>

/**
 * @brief This structure holds information about executing subprocess
 * 
 */
typedef struct {
  pid_t pid;
  int output_signal;
  bool exited;
  pid_t pid;/**< PID of the running process */
  int output_signal;/**< Exit code of the process*/
  bool exited;/**< Whether the process has ended */
} executing_file_t;

/**
 * @brief This structure holds error or executing subprocess
 * 
 */
typedef struct {
  bool error;
  executing_file_t file;
  bool error; /**< in case there was an error, this is true*/
  executing_file_t file; /**< executing file if error is false*/
} executing_file_error_t;

/**
 * @brief Start executing given file
 * 
 * @param path path to the executable
 * @param args arguments to start the executable with
 * @return executing_file_error_t with either error or process information set
 */
executing_file_error_t executing_file_execute(char *path, char *args);

/**
 * @brief Wait for the process to exit
 * 
 * @param file 
 * @return int exit code
 */
int executing_file_wait(executing_file_t *file);

/**
 * @brief Check whether the process has ended and return immediatelly
 * 
 * @param file 
 * @return true when the process has ended
 * @return false when the process is still running
 */
bool executing_file_has_ended(executing_file_t *file);

M lib-gui/include/gui.h => lib-gui/include/gui.h +66 -3
@@ 39,17 39,36 @@ typedef enum {
  CONT_ONE,
} container_type_t;

typedef bool (*render_item)(void *state, uint32_t index, renderer_t *renderer, int16_t beg_x, int16_t beg_y);
/**
 * @brief Summary
 * @details Description
 * @param[inout] state
 * @param[in] index Index of the item to render
 * @param[out] renderer
 * @param[in] beg_x Begin x coordinate
 * @param[in] beg_y Begin y coordinate
 * @return Whether item was rendered
 */
typedef bool (*render_item)(void *state, uint32_t index, renderer_t *renderer, int16_t beg_x, int16_t beg_y, display_pixel_t foreground);

typedef struct {
  void *state;
  render_item render_item_fn;
  render_item render_header_fn;
  uint32_t items_count;
  uint32_t selected_index;
  uint16_t item_height;

  int16_t scroll_x;
  int16_t scroll_y;
  int32_t scroll_x;
  int32_t scroll_y;

  display_pixel_t regular_foreground;
  display_pixel_t regular_background;

  display_pixel_t selected_foreground;
  display_pixel_t selected_background;

  uint16_t item_padding;
} list_container_t;

typedef struct {


@@ 310,16 329,60 @@ void gui_group_container_render(gui_t *gui, container_t *container);
void gui_group_container_update(gui_t *gui, container_t *container);

// list_container.c

/**
 * @brief Create list container
 *
 * @param[inout] state Custom state of items to pass to render function
 * @param[in] items_count Count of items to show
 * @param[in] item_height The height of item
 * @param[in] render_it Function to render item
 * @param[in] render_header Function to render header
 * @return Container with list data
 */
container_t gui_list_container_create(void *state, uint32_t items_count,
                                      uint16_t item_height,
                                      render_item render_it,
                                      render_item render_header);

/**
 * @brief Get current selected index based on scroll
 *
 * @param[inout] container
 * @return Current selected index
 */
uint32_t gui_list_get_selected_index(container_t *container);

/**
 * @brief Scroll list container by x, y
 * @details Increase scroll coordinates by x, y so different view arrea is shown
 * @param[inout] container
 * @param[in] x x coordinate
 * @param[in] y y coordinate
 */
void gui_list_scroll(container_t *container, int16_t x, int16_t y);

/**
 * @brief List container set new state
 *
 * @param[inout] container
 * @param[out] state Custom state of items
 * @param[in] items_count The count of items
 * @return Whether the state was set correctly
 */
bool gui_list_container_set_state(container_t *container, void *state,
                                  uint32_t items_count);

/**
 * @brief List container set new item height
 *
 * @param[inout] container
 * @param[in] item_height The height of item
 * @return Whether the item was set correctly
 */
bool gui_list_container_set_item_height(container_t *container,
                                        uint16_t item_height);

bool gui_list_container_set_render_function(container_t *container,
                                            render_item render_it,
                                            render_item render_header);

M lib-gui/src/gui_list_container.c => lib-gui/src/gui_list_container.c +61 -9
@@ 1,3 1,4 @@
#include "display_utils.h"
#include "gui.h"
#include "renderer.h"



@@ 11,8 12,14 @@ container_t gui_list_container_create(void *state, uint32_t items_count,
    .state = state,
    .scroll_x = 0,
    .scroll_y = 0,
    .selected_index = 0,
    .render_header_fn = render_header,
    .render_item_fn = render_it,
    .regular_background = BLACK_PIXEL,
    .regular_foreground = WHITE_PIXEL,
    .selected_background = WHITE_PIXEL,
    .selected_foreground = BLACK_PIXEL,
    .item_padding = 3,
  };

  container_t container = {


@@ 30,7 37,11 @@ container_t gui_list_container_create(void *state, uint32_t items_count,

void gui_list_scroll(container_t *container, int16_t x, int16_t y) {
  container->inner.list.scroll_x += x;
  container->inner.list.scroll_y += y;
  if (y < 0) {
    container->inner.list.selected_index--;
  } else if (y > 0) {
    container->inner.list.selected_index++;
  }
}

bool gui_list_container_set_state(container_t *container, void *state,


@@ 55,7 66,7 @@ bool gui_list_container_set_render_function(container_t *container, render_item 

void gui_list_container_render(gui_t *gui, container_t *container) {
  renderer_translate(gui->renderer, container->x, container->y);
  renderer_set_draw_area(gui->renderer, gui->size.x, gui->size.y);
  renderer_set_draw_area(gui->renderer, container->width, container->height);

  list_container_t list = container->inner.list;
  if (list.scroll_x < 0) {


@@ 68,24 79,65 @@ void gui_list_container_render(gui_t *gui, container_t *container) {
  container->inner.list = list;

  uint16_t item_height = list.item_height;
  uint16_t item_full_height = item_height + list.item_padding * 2;

  int32_t first_index = list.scroll_y / item_height;
  int32_t first_index = list.scroll_y / item_full_height;
  if (first_index < 0) {
    first_index = 0;
  }
  uint32_t items_count = gui->size.y / item_height;

  uint32_t items_count = gui->size.y / item_full_height + 1;
  uint32_t end_index = first_index + items_count;

  int32_t beg_x = -list.scroll_x;
  int32_t beg_y = -list.scroll_y + first_index * item_height;
  int32_t beg_y = -list.scroll_y + first_index * item_full_height;

  uint32_t selected_index = gui_list_get_selected_index(container);

  for (int i = first_index; i < end_index; i++) {
    int32_t y = beg_y + i * item_height;
  for (uint32_t i = first_index; i < end_index && i < list.items_count; i++) {
    int32_t y = beg_y + (i - first_index) * item_full_height;
    display_pixel_t fgcolor = list.regular_foreground;
    display_pixel_t bgcolor = list.regular_background;

    list.render_item_fn(list.state, i, gui->renderer, beg_x, y);
    if (selected_index == i) {
      fgcolor = list.selected_foreground;
      bgcolor = list.selected_background;
    }

    renderer_render_rectangle(gui->renderer, beg_x, y, 1000, item_full_height, bgcolor);
    list.render_item_fn(list.state, i, gui->renderer, beg_x + list.item_padding, y + list.item_padding, fgcolor);
  }
}

uint32_t gui_list_get_selected_index(container_t *container) {
  return container->inner.list.selected_index;
}

void gui_list_container_update(gui_t *gui, container_t *container) {
  // do nothing :)
  list_container_t list = container->inner.list;

  if (list.selected_index == UINT32_MAX) {
    list.selected_index = 0;
  } else if (list.selected_index > list.items_count - 1) {
    list.selected_index = list.items_count - 1;
  }

  uint16_t item_full_height = list.item_height + list.item_padding * 2;
  int32_t first_visible_index = list.scroll_y / item_full_height;
  if (first_visible_index < 0) {
    first_visible_index = 0;
  }
  uint32_t items_count = container->height / item_full_height - 1;
  uint32_t last_visible_index = first_visible_index + items_count;

  uint32_t selected_index = list.selected_index;

  if (selected_index < first_visible_index) {
    list.scroll_y = selected_index * item_full_height;
  } else if (selected_index > last_visible_index) {
    list.scroll_y = (selected_index - items_count) * item_full_height;
  }


  container->inner.list = list;
}

Do not follow this link