From a4294e4a94189dffb1fdf99c9a60d87d77272926 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 13 Jul 2024 10:52:24 -0700 Subject: Restructure project. --- src/widget/button.c | 19 ++++++++++ src/widget/frame.c | 19 ++++++++++ src/widget/label.c | 28 ++++++++++++++ src/widget/table.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/widget/table.h | 11 ++++++ src/widget/widget.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ src/widget/widget.h | 66 +++++++++++++++++++++++++++++++++ 7 files changed, 339 insertions(+) create mode 100644 src/widget/button.c create mode 100644 src/widget/frame.c create mode 100644 src/widget/label.c create mode 100644 src/widget/table.c create mode 100644 src/widget/table.h create mode 100644 src/widget/widget.c create mode 100644 src/widget/widget.h (limited to 'src/widget') diff --git a/src/widget/button.c b/src/widget/button.c new file mode 100644 index 0000000..f2313fd --- /dev/null +++ b/src/widget/button.c @@ -0,0 +1,19 @@ +#include + +#include "widget.h" + +uiButton* uiMakeButton(const char* text) { + assert(text); + + uiButton* button = UI_NEW(uiButton); + + *button = (uiButton){ + .widget = + (uiWidget){ + .type = uiTypeButton, + .rect = {0}, + }, + .text = string_new(text), + }; + return button; +} diff --git a/src/widget/frame.c b/src/widget/frame.c new file mode 100644 index 0000000..e1078be --- /dev/null +++ b/src/widget/frame.c @@ -0,0 +1,19 @@ +#include + +#include "widget.h" + +uiFrame* uiMakeFrame(void) { + uiFrame* frame = UI_NEW(uiFrame); + frame->widget.type = uiTypeFrame; + return frame; +} + +void uiDestroyFrame(uiFrame** ppFrame) { DestroyWidget((uiWidget**)ppFrame); } + +uiSize uiGetFrameSize(const uiFrame* frame) { + assert(frame); + return (uiSize){ + .width = frame->widget.rect.width, + .height = frame->widget.rect.height, + }; +} diff --git a/src/widget/label.c b/src/widget/label.c new file mode 100644 index 0000000..30ca0ec --- /dev/null +++ b/src/widget/label.c @@ -0,0 +1,28 @@ +#include + +#include "uiLibrary.h" +#include "widget.h" + +uiLabel* uiMakeLabel(const char* text) { + assert(text); + + uiLabel* label = UI_NEW(uiLabel); + + *label = (uiLabel){ + .widget = + (uiWidget){ + .type = uiTypeLabel, + .rect = + (uiRect){ + .width = + (int)strlen(text) * g_ui.font->header.glyph_width, + .height = g_ui.font->header.glyph_height}}, + .text = string_new(text), + }; + return label; +} + +const char* uiLabelGetText(const uiLabel* label) { + assert(label); + return string_data(label->text); +} diff --git a/src/widget/table.c b/src/widget/table.c new file mode 100644 index 0000000..7a0ea03 --- /dev/null +++ b/src/widget/table.c @@ -0,0 +1,103 @@ +#include "table.h" + +#include "widget.h" + +const uiCell* GetCell(const uiTable* table, int row, int col) { + assert(table); + return &table->cells[row][col]; +} + +uiCell* GetCellMut(uiTable* table, int row, int col) { + assert(table); + return (uiCell*)GetCell(table, row, col); +} + +uiCell** GetLastRow(uiTable* table) { + assert(table); + assert(table->rows > 0); + return &table->cells[table->rows - 1]; +} + +uiTable* uiMakeTable(int rows, int cols, const char** header) { + uiTable* table = UI_NEW(uiTable); + + *table = (uiTable){ + .widget = (uiWidget){.type = uiTypeTable}, + .rows = rows, + .cols = cols, + .widths = (cols > 0) ? calloc(cols, sizeof(int)) : 0, + .header = header ? calloc(cols, sizeof(uiCell)) : 0, + .cells = (rows * cols > 0) ? calloc(rows, sizeof(uiCell*)) : 0, + .flags = {0}, + }; + + if (header) { + for (int col = 0; col < cols; ++col) { + table->header[col].child = (uiWidget*)uiMakeLabel(header[col]); + } + } + + return table; +} + +void uiTableClear(uiTable* table) { + assert(table); + + // Free row data. + if (table->cells) { + for (int row = 0; row < table->rows; ++row) { + for (int col = 0; col < table->cols; ++col) { + DestroyWidget(&table->cells[row][col].child); + } + free(table->cells[row]); + } + free(table->cells); + table->cells = 0; + } + table->rows = 0; + + // Clear row widths. + for (int i = 0; i < table->cols; ++i) { + table->widths[i] = 0; + } + + table->offset = 0; + + table->flags.vertical_overflow = 0; +} + +void uiTableAddRow(uiTable* table, const char** row) { + assert(table); + + table->rows++; + + uiCell** cells = realloc(table->cells, table->rows * sizeof(uiCell*)); + ASSERT(cells); + table->cells = cells; + + uiCell** pLastRow = GetLastRow(table); + *pLastRow = calloc(table->cols, sizeof(uiCell)); + ASSERT(*pLastRow); + uiCell* lastRow = *pLastRow; + + for (int col = 0; col < table->cols; ++col) { + lastRow[col].child = (uiWidget*)uiMakeLabel(row[col]); + } +} + +void uiTableSet(uiTable* table, int row, int col, uiPtr child) { + assert(table); + assert(child.widget); + + GetCellMut(table, row, col)->child = child.widget; +} + +const uiWidget* uiTableGet(const uiTable* table, int row, int col) { + assert(table); + return GetCell(table, row, col)->child; +} + +uiWidget* uiTableGetMut(uiTable* table, int row, int col) { + assert(table); + return GetCellMut(table, row, col)->child; +} diff --git a/src/widget/table.h b/src/widget/table.h new file mode 100644 index 0000000..9f466de --- /dev/null +++ b/src/widget/table.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "widget.h" + +const uiCell* GetCell(const uiTable* table, int row, int col); + +uiCell* GetCellMut(uiTable* table, int row, int col); + +uiCell** GetLastRow(uiTable* table); diff --git a/src/widget/widget.c b/src/widget/widget.c new file mode 100644 index 0000000..ef79ac4 --- /dev/null +++ b/src/widget/widget.c @@ -0,0 +1,93 @@ +#include "widget.h" + +#include + +// ----------------------------------------------------------------------------- +// Widget. + +#define UI_DEL(ppWidget) \ + { \ + assert(ppWidget); \ + void* widget_ = *ppWidget; \ + if (widget_) { \ + free(widget_); \ + *ppWidget = 0; \ + } \ + } + +uiWidgetType uiWidgetGetType(const uiWidget* widget) { + assert(widget); + return widget->type; +} + +void DestroyWidget(uiWidget** ppWidget) { + assert(ppWidget); + + uiWidget* widget = *ppWidget; + if (widget) { + list_foreach_mut(widget->children, child, { DestroyWidget(&child); }); + } + UI_DEL(ppWidget); +} + +void uiWidgetSetParent(uiPtr child_, uiPtr parent_) { + uiWidget* child = child_.widget; + uiWidget* parent = parent_.widget; + + assert(child); + assert(parent); + + list_add(parent->children, child); +} + +// ----------------------------------------------------------------------------- +// Widget pointers. + +uiPtr uiMakeButtonPtr(uiButton* button) { + assert(button); + return (uiPtr){.type = uiTypeButton, .button = button}; +} + +uiPtr uiMakeFramePtr(uiFrame* frame) { + assert(frame); + return (uiPtr){.type = uiTypeFrame, .frame = frame}; +} + +uiPtr uiMakeLabelPtr(uiLabel* label) { + assert(label); + return (uiPtr){.type = uiTypeLabel, .label = label}; +} + +uiPtr uiMakeTablePtr(uiTable* table) { + assert(table); + return (uiPtr){.type = uiTypeTable, .table = table}; +} + +static uiPtr uiMakeWidgetPtr(uiWidget* widget) { + assert(widget); + return (uiPtr){.type = widget->type, .widget = widget}; +} + +uiButton* uiGetButtonPtr(uiPtr ptr) { + assert(ptr.type == uiTypeButton); + assert(ptr.button); + return ptr.button; +} + +uiFrame* uiGetFramePtr(uiPtr ptr) { + assert(ptr.type == uiTypeFrame); + assert(ptr.frame); + return ptr.frame; +} + +uiLabel* uiGetLabelPtr(uiPtr ptr) { + assert(ptr.type == uiTypeLabel); + assert(ptr.label); + return ptr.label; +} + +uiTable* uiGetTablePtr(uiPtr ptr) { + assert(ptr.type == uiTypeTable); + assert(ptr.table); + return ptr.table; +} diff --git a/src/widget/widget.h b/src/widget/widget.h new file mode 100644 index 0000000..a2c96bc --- /dev/null +++ b/src/widget/widget.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +#include +#include + +#include + +DEF_LIST(Widget, uiWidget*) + +#define UI_NEW(TYPE) (TYPE*)uiAlloc(1, sizeof(TYPE)) + +static inline void* uiAlloc(size_t count, size_t size) { + void* mem = calloc(count, size); + ASSERT(mem); + return mem; +} + +// ----------------------------------------------------------------------------- +// Widgets. + +/// Base widget type. +typedef struct uiWidget { + uiWidgetType type; + uiRect rect; + Widget_list children; +} uiWidget; + +/// Button. +typedef struct uiButton { + uiWidget widget; + string text; +} uiButton; + +/// Frame. +typedef struct uiFrame { + uiWidget widget; +} uiFrame; + +/// Label. +typedef struct uiLabel { + uiWidget widget; + string text; +} uiLabel; + +/// Table cell. +typedef struct uiCell { + uiWidget* child; +} uiCell; + +/// Table. +typedef struct uiTable { + uiWidget widget; + int rows; + int cols; + int* widths; // Width, in pixels, for each column. + uiCell* header; // If non-null, row of 'cols' header cells. + uiCell** cells; // Array of 'rows' rows, each of 'cols' cells. + int offset; // Offset into the rows of the table. Units: rows. + struct { + bool vertical_overflow : 1; // True if contents overflow vertically. + } flags; +} uiTable; + +void DestroyWidget(uiWidget** ppWidget); -- cgit v1.2.3