#include "gui_component_text_view.h" #include "display_utils.h" #include "input.h" #include "renderer.h" #include #include #include #include "direction.h" #include "keyboard_const.h" #include "rotation_const.h" multiline_text_t *gui_multiline_text_create(font_t *font, display_pixel_t color, char *text) { size_t len = strlen(text) + 1; size_t lines = 1; for (int i = 0; i < len; i++) { if (text[i] == '\n') { lines++; } } void* new = realloc(text, len + sizeof(multiline_text_t) + sizeof(line_t) * lines); if (new == NULL) { free(text); return NULL; } text = new; multiline_text_t *multiline_text = (multiline_text_t*)(new + len); line_t *line_ptr = (line_t*)(new + len + sizeof(multiline_text_t)); multiline_text->font = font; multiline_text->color = color; multiline_text->lines = line_ptr; multiline_text->lines_count = lines; multiline_text->text = text; bool new_line = false; uint32_t line_index = 0; uint32_t line_length = 0; char *line_str_ptr = text; for (int i = 0; i < len; i++) { if (new_line) { line_ptr[line_index].line = line_str_ptr; line_ptr[line_index++].length = line_length; line_str_ptr += line_length + 1; line_length = 0; new_line = false; } if (text[i] == '\n') { text[i] = '\0'; new_line = true; } else { line_length++; } } if (line_index < lines) { line_ptr[line_index].line = line_str_ptr; line_ptr[line_index].length = line_length; } return multiline_text; } void gui_text_view_scroll(component_t *text_view, int32_t x, int32_t y) { text_view->x -= x; text_view->y -= y; } void gui_text_view_reset_scroll(component_t *text_view) { text_view->x = 0; text_view->y = 0; } void gui_text_view_full_scroll(component_t *text_view) { text_view->x = 0; text_view->y = INT16_MIN; } uint16_t gui_text_view_get_lines_scrolled(component_t *component) { multiline_text_t *text = (multiline_text_t *)component->state; return (-component->y) / (text->font->size + text->font->line_spacing); } void gui_text_view_render(container_t *container, component_t *component, gui_t *gui) { multiline_text_t *text = (multiline_text_t*)component->state; font_t *font = text->font; int32_t x_offset = component->x, y_offset = component->y; if (x_offset > 0) { x_offset = 0; } if (y_offset >= 0) { y_offset = 0; } else if (y_offset < -(font->size + font->line_spacing) * (text->lines_count) + gui->size.y - container->y) { y_offset = -(font->size + font->line_spacing) * (text->lines_count) + gui->size.y - container->y; } component->x = x_offset; component->y = y_offset; int16_t first_line_index = -y_offset / (font->size + font->line_spacing); int16_t lines_count = gui->size.y / font->size + 1; if (first_line_index < 0) { first_line_index = 0; } int16_t last_line_index = lines_count + first_line_index; y_offset += first_line_index * (font->size + font->line_spacing); for (int i = first_line_index; i < last_line_index && i < text->lines_count; i++) { line_t *line = &text->lines[i]; size2d_t size = renderer_write_string(gui->renderer, x_offset, y_offset, line->length, font, line->line, text->color); y_offset += size.y; } } void gui_text_view_update(container_t *container, component_t *component, gui_t *gui) { // do nothing }