summaryrefslogtreecommitdiff
path: root/src/widget
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2024-07-13 10:52:24 -0700
committer3gg <3gg@shellblade.net>2024-07-13 10:52:24 -0700
commita4294e4a94189dffb1fdf99c9a60d87d77272926 (patch)
tree2e92f7c95116861bc39f4dae1d0ab5d388550000 /src/widget
parentcf9579d7546c04dbc708bd8719e3f935a28088bd (diff)
Restructure project.
Diffstat (limited to 'src/widget')
-rw-r--r--src/widget/button.c19
-rw-r--r--src/widget/frame.c19
-rw-r--r--src/widget/label.c28
-rw-r--r--src/widget/table.c103
-rw-r--r--src/widget/table.h11
-rw-r--r--src/widget/widget.c93
-rw-r--r--src/widget/widget.h66
7 files changed, 339 insertions, 0 deletions
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 @@
1#include <ui.h>
2
3#include "widget.h"
4
5uiButton* uiMakeButton(const char* text) {
6 assert(text);
7
8 uiButton* button = UI_NEW(uiButton);
9
10 *button = (uiButton){
11 .widget =
12 (uiWidget){
13 .type = uiTypeButton,
14 .rect = {0},
15 },
16 .text = string_new(text),
17 };
18 return button;
19}
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 @@
1#include <ui.h>
2
3#include "widget.h"
4
5uiFrame* uiMakeFrame(void) {
6 uiFrame* frame = UI_NEW(uiFrame);
7 frame->widget.type = uiTypeFrame;
8 return frame;
9}
10
11void uiDestroyFrame(uiFrame** ppFrame) { DestroyWidget((uiWidget**)ppFrame); }
12
13uiSize uiGetFrameSize(const uiFrame* frame) {
14 assert(frame);
15 return (uiSize){
16 .width = frame->widget.rect.width,
17 .height = frame->widget.rect.height,
18 };
19}
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 @@
1#include <ui.h>
2
3#include "uiLibrary.h"
4#include "widget.h"
5
6uiLabel* uiMakeLabel(const char* text) {
7 assert(text);
8
9 uiLabel* label = UI_NEW(uiLabel);
10
11 *label = (uiLabel){
12 .widget =
13 (uiWidget){
14 .type = uiTypeLabel,
15 .rect =
16 (uiRect){
17 .width =
18 (int)strlen(text) * g_ui.font->header.glyph_width,
19 .height = g_ui.font->header.glyph_height}},
20 .text = string_new(text),
21 };
22 return label;
23}
24
25const char* uiLabelGetText(const uiLabel* label) {
26 assert(label);
27 return string_data(label->text);
28}
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 @@
1#include "table.h"
2
3#include "widget.h"
4
5const uiCell* GetCell(const uiTable* table, int row, int col) {
6 assert(table);
7 return &table->cells[row][col];
8}
9
10uiCell* GetCellMut(uiTable* table, int row, int col) {
11 assert(table);
12 return (uiCell*)GetCell(table, row, col);
13}
14
15uiCell** GetLastRow(uiTable* table) {
16 assert(table);
17 assert(table->rows > 0);
18 return &table->cells[table->rows - 1];
19}
20
21uiTable* uiMakeTable(int rows, int cols, const char** header) {
22 uiTable* table = UI_NEW(uiTable);
23
24 *table = (uiTable){
25 .widget = (uiWidget){.type = uiTypeTable},
26 .rows = rows,
27 .cols = cols,
28 .widths = (cols > 0) ? calloc(cols, sizeof(int)) : 0,
29 .header = header ? calloc(cols, sizeof(uiCell)) : 0,
30 .cells = (rows * cols > 0) ? calloc(rows, sizeof(uiCell*)) : 0,
31 .flags = {0},
32 };
33
34 if (header) {
35 for (int col = 0; col < cols; ++col) {
36 table->header[col].child = (uiWidget*)uiMakeLabel(header[col]);
37 }
38 }
39
40 return table;
41}
42
43void uiTableClear(uiTable* table) {
44 assert(table);
45
46 // Free row data.
47 if (table->cells) {
48 for (int row = 0; row < table->rows; ++row) {
49 for (int col = 0; col < table->cols; ++col) {
50 DestroyWidget(&table->cells[row][col].child);
51 }
52 free(table->cells[row]);
53 }
54 free(table->cells);
55 table->cells = 0;
56 }
57 table->rows = 0;
58
59 // Clear row widths.
60 for (int i = 0; i < table->cols; ++i) {
61 table->widths[i] = 0;
62 }
63
64 table->offset = 0;
65
66 table->flags.vertical_overflow = 0;
67}
68
69void uiTableAddRow(uiTable* table, const char** row) {
70 assert(table);
71
72 table->rows++;
73
74 uiCell** cells = realloc(table->cells, table->rows * sizeof(uiCell*));
75 ASSERT(cells);
76 table->cells = cells;
77
78 uiCell** pLastRow = GetLastRow(table);
79 *pLastRow = calloc(table->cols, sizeof(uiCell));
80 ASSERT(*pLastRow);
81 uiCell* lastRow = *pLastRow;
82
83 for (int col = 0; col < table->cols; ++col) {
84 lastRow[col].child = (uiWidget*)uiMakeLabel(row[col]);
85 }
86}
87
88void uiTableSet(uiTable* table, int row, int col, uiPtr child) {
89 assert(table);
90 assert(child.widget);
91
92 GetCellMut(table, row, col)->child = child.widget;
93}
94
95const uiWidget* uiTableGet(const uiTable* table, int row, int col) {
96 assert(table);
97 return GetCell(table, row, col)->child;
98}
99
100uiWidget* uiTableGetMut(uiTable* table, int row, int col) {
101 assert(table);
102 return GetCellMut(table, row, col)->child;
103}
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 @@
1#pragma once
2
3#include <ui.h>
4
5#include "widget.h"
6
7const uiCell* GetCell(const uiTable* table, int row, int col);
8
9uiCell* GetCellMut(uiTable* table, int row, int col);
10
11uiCell** 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 @@
1#include "widget.h"
2
3#include <cassert.h>
4
5// -----------------------------------------------------------------------------
6// Widget.
7
8#define UI_DEL(ppWidget) \
9 { \
10 assert(ppWidget); \
11 void* widget_ = *ppWidget; \
12 if (widget_) { \
13 free(widget_); \
14 *ppWidget = 0; \
15 } \
16 }
17
18uiWidgetType uiWidgetGetType(const uiWidget* widget) {
19 assert(widget);
20 return widget->type;
21}
22
23void DestroyWidget(uiWidget** ppWidget) {
24 assert(ppWidget);
25
26 uiWidget* widget = *ppWidget;
27 if (widget) {
28 list_foreach_mut(widget->children, child, { DestroyWidget(&child); });
29 }
30 UI_DEL(ppWidget);
31}
32
33void uiWidgetSetParent(uiPtr child_, uiPtr parent_) {
34 uiWidget* child = child_.widget;
35 uiWidget* parent = parent_.widget;
36
37 assert(child);
38 assert(parent);
39
40 list_add(parent->children, child);
41}
42
43// -----------------------------------------------------------------------------
44// Widget pointers.
45
46uiPtr uiMakeButtonPtr(uiButton* button) {
47 assert(button);
48 return (uiPtr){.type = uiTypeButton, .button = button};
49}
50
51uiPtr uiMakeFramePtr(uiFrame* frame) {
52 assert(frame);
53 return (uiPtr){.type = uiTypeFrame, .frame = frame};
54}
55
56uiPtr uiMakeLabelPtr(uiLabel* label) {
57 assert(label);
58 return (uiPtr){.type = uiTypeLabel, .label = label};
59}
60
61uiPtr uiMakeTablePtr(uiTable* table) {
62 assert(table);
63 return (uiPtr){.type = uiTypeTable, .table = table};
64}
65
66static uiPtr uiMakeWidgetPtr(uiWidget* widget) {
67 assert(widget);
68 return (uiPtr){.type = widget->type, .widget = widget};
69}
70
71uiButton* uiGetButtonPtr(uiPtr ptr) {
72 assert(ptr.type == uiTypeButton);
73 assert(ptr.button);
74 return ptr.button;
75}
76
77uiFrame* uiGetFramePtr(uiPtr ptr) {
78 assert(ptr.type == uiTypeFrame);
79 assert(ptr.frame);
80 return ptr.frame;
81}
82
83uiLabel* uiGetLabelPtr(uiPtr ptr) {
84 assert(ptr.type == uiTypeLabel);
85 assert(ptr.label);
86 return ptr.label;
87}
88
89uiTable* uiGetTablePtr(uiPtr ptr) {
90 assert(ptr.type == uiTypeTable);
91 assert(ptr.table);
92 return ptr.table;
93}
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 @@
1#pragma once
2
3#include <ui.h>
4
5#include <cstring.h>
6#include <list.h>
7
8#include <stdbool.h>
9
10DEF_LIST(Widget, uiWidget*)
11
12#define UI_NEW(TYPE) (TYPE*)uiAlloc(1, sizeof(TYPE))
13
14static inline void* uiAlloc(size_t count, size_t size) {
15 void* mem = calloc(count, size);
16 ASSERT(mem);
17 return mem;
18}
19
20// -----------------------------------------------------------------------------
21// Widgets.
22
23/// Base widget type.
24typedef struct uiWidget {
25 uiWidgetType type;
26 uiRect rect;
27 Widget_list children;
28} uiWidget;
29
30/// Button.
31typedef struct uiButton {
32 uiWidget widget;
33 string text;
34} uiButton;
35
36/// Frame.
37typedef struct uiFrame {
38 uiWidget widget;
39} uiFrame;
40
41/// Label.
42typedef struct uiLabel {
43 uiWidget widget;
44 string text;
45} uiLabel;
46
47/// Table cell.
48typedef struct uiCell {
49 uiWidget* child;
50} uiCell;
51
52/// Table.
53typedef struct uiTable {
54 uiWidget widget;
55 int rows;
56 int cols;
57 int* widths; // Width, in pixels, for each column.
58 uiCell* header; // If non-null, row of 'cols' header cells.
59 uiCell** cells; // Array of 'rows' rows, each of 'cols' cells.
60 int offset; // Offset into the rows of the table. Units: rows.
61 struct {
62 bool vertical_overflow : 1; // True if contents overflow vertically.
63 } flags;
64} uiTable;
65
66void DestroyWidget(uiWidget** ppWidget);