diff options
| author | 3gg <3gg@shellblade.net> | 2024-07-13 11:44:32 -0700 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2024-07-13 11:44:32 -0700 |
| commit | 68a3532728b55b73d8bcadb8ccfc1d9396346cd2 (patch) | |
| tree | c87a636a36f21024032fc5cb5900982957491f95 | |
| parent | a4294e4a94189dffb1fdf99c9a60d87d77272926 (diff) | |
Basic table scrollbar rendering.
| -rw-r--r-- | src/constants.h | 2 | ||||
| -rw-r--r-- | src/input.c | 5 | ||||
| -rw-r--r-- | src/layout.c | 6 | ||||
| -rw-r--r-- | src/render.c | 22 | ||||
| -rw-r--r-- | src/widget/widget.h | 10 |
5 files changed, 39 insertions, 6 deletions
diff --git a/src/constants.h b/src/constants.h index 457f461..0d93d14 100644 --- a/src/constants.h +++ b/src/constants.h | |||
| @@ -4,4 +4,4 @@ | |||
| 4 | #define MaxWidgetEvents 8 | 4 | #define MaxWidgetEvents 8 |
| 5 | 5 | ||
| 6 | // Width of scroll bars in pixels. | 6 | // Width of scroll bars in pixels. |
| 7 | #define ScrollBarWidth 16 | 7 | #define ScrollBarWidth 32 |
diff --git a/src/input.c b/src/input.c index c4b1be7..20551a6 100644 --- a/src/input.c +++ b/src/input.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <cassert.h> | 7 | #include <cassert.h> |
| 8 | 8 | ||
| 9 | #define Min(a, b) ((a) < (b) ? (a) : (b)) | ||
| 9 | #define Max(a, b) ((a) > (b) ? (a) : (b)) | 10 | #define Max(a, b) ((a) > (b) ? (a) : (b)) |
| 10 | 11 | ||
| 11 | /// Return true if the rectangle contains the point. | 12 | /// Return true if the rectangle contains the point. |
| @@ -85,7 +86,9 @@ static void ClickTable(uiTable* table, const uiMouseClickEvent* event) { | |||
| 85 | static void ScrollTable(uiTable* table, const uiMouseScrollEvent* event) { | 86 | static void ScrollTable(uiTable* table, const uiMouseScrollEvent* event) { |
| 86 | assert(table); | 87 | assert(table); |
| 87 | assert(event); | 88 | assert(event); |
| 88 | table->offset = Max(0, table->offset - event->scroll_offset); | 89 | table->offset = |
| 90 | Min(table->rows - table->num_visible_rows, | ||
| 91 | Max(0, table->offset - event->scroll_offset)); | ||
| 89 | } | 92 | } |
| 90 | 93 | ||
| 91 | /// Process a scroll event. | 94 | /// Process a scroll event. |
diff --git a/src/layout.c b/src/layout.c index 9d4b556..f83976f 100644 --- a/src/layout.c +++ b/src/layout.c | |||
| @@ -13,6 +13,12 @@ static void ResizeTable(uiTable* table, int width, int height) { | |||
| 13 | return; | 13 | return; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | table->height = height; | ||
| 17 | |||
| 18 | // Compute the number of rows that are visible at once. | ||
| 19 | table->num_visible_rows = height / g_ui.font->header.glyph_height; | ||
| 20 | assert(table->num_visible_rows <= table->rows); | ||
| 21 | |||
| 16 | // Determine if there is vertical overflow. This determines whether we need to | 22 | // Determine if there is vertical overflow. This determines whether we need to |
| 17 | // render a scroll bar, in which case room must be made for it. | 23 | // render a scroll bar, in which case room must be made for it. |
| 18 | table->flags.vertical_overflow = | 24 | table->flags.vertical_overflow = |
diff --git a/src/render.c b/src/render.c index 24490c0..b1fd3e8 100644 --- a/src/render.c +++ b/src/render.c | |||
| @@ -186,6 +186,8 @@ static void RenderTable(const uiTable* table, RenderState* state) { | |||
| 186 | uiRect original_subsurface = {0}; | 186 | uiRect original_subsurface = {0}; |
| 187 | uiPoint original_pen = {0}; | 187 | uiPoint original_pen = {0}; |
| 188 | 188 | ||
| 189 | int col_widths_sum = 0; | ||
| 190 | |||
| 189 | // Render header. | 191 | // Render header. |
| 190 | if (table->header) { | 192 | if (table->header) { |
| 191 | for (int col = 0; col < table->cols; ++col) { | 193 | for (int col = 0; col < table->cols; ++col) { |
| @@ -201,6 +203,9 @@ static void RenderTable(const uiTable* table, RenderState* state) { | |||
| 201 | // Reset the original subsurface and pen for subsequent columns. | 203 | // Reset the original subsurface and pen for subsequent columns. |
| 202 | PopSubsurface(state, &original_subsurface, &original_pen); | 204 | PopSubsurface(state, &original_subsurface, &original_pen); |
| 203 | 205 | ||
| 206 | // Keep track of the sum of column widths to later render the scroll bar. | ||
| 207 | col_widths_sum += table->widths[col]; | ||
| 208 | |||
| 204 | // Next column. | 209 | // Next column. |
| 205 | state->pen.x += table->widths[col]; | 210 | state->pen.x += table->widths[col]; |
| 206 | } | 211 | } |
| @@ -235,6 +240,23 @@ static void RenderTable(const uiTable* table, RenderState* state) { | |||
| 235 | state->pen.y += g_ui.font->header.glyph_height; | 240 | state->pen.y += g_ui.font->header.glyph_height; |
| 236 | } | 241 | } |
| 237 | state->pen.y = y0; | 242 | state->pen.y = y0; |
| 243 | |||
| 244 | // Render scrollbar. | ||
| 245 | if (table->flags.vertical_overflow) { | ||
| 246 | state->pen.x = col_widths_sum; | ||
| 247 | |||
| 248 | const int y_start = (int)((double)table->offset / (double)table->rows * | ||
| 249 | (double)table->height); | ||
| 250 | |||
| 251 | const int height = (int)((double)table->num_visible_rows / | ||
| 252 | (double)table->rows * (double)table->height); | ||
| 253 | |||
| 254 | FillRect( | ||
| 255 | &(uiRect){.y = y_start, .width = ScrollBarWidth, .height = height}, | ||
| 256 | uiPink, state); | ||
| 257 | |||
| 258 | state->pen.x = x0; | ||
| 259 | } | ||
| 238 | } | 260 | } |
| 239 | 261 | ||
| 240 | /// Render a widget. | 262 | /// Render a widget. |
diff --git a/src/widget/widget.h b/src/widget/widget.h index a2c96bc..c75bd65 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h | |||
| @@ -54,10 +54,12 @@ typedef struct uiTable { | |||
| 54 | uiWidget widget; | 54 | uiWidget widget; |
| 55 | int rows; | 55 | int rows; |
| 56 | int cols; | 56 | int cols; |
| 57 | int* widths; // Width, in pixels, for each column. | 57 | int height; // Height in pixels. |
| 58 | uiCell* header; // If non-null, row of 'cols' header cells. | 58 | int* widths; // Width, in pixels, for each column. |
| 59 | uiCell** cells; // Array of 'rows' rows, each of 'cols' cells. | 59 | uiCell* header; // If non-null, row of 'cols' header cells. |
| 60 | int offset; // Offset into the rows of the table. Units: rows. | 60 | uiCell** cells; // Array of 'rows' rows, each of 'cols' cells. |
| 61 | int offset; // Offset into the rows of the table. Units: rows. | ||
| 62 | int num_visible_rows; // The number of rows that are visible at once. | ||
| 61 | struct { | 63 | struct { |
| 62 | bool vertical_overflow : 1; // True if contents overflow vertically. | 64 | bool vertical_overflow : 1; // True if contents overflow vertically. |
| 63 | } flags; | 65 | } flags; |
