From 68a3532728b55b73d8bcadb8ccfc1d9396346cd2 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 13 Jul 2024 11:44:32 -0700 Subject: Basic table scrollbar rendering. --- src/constants.h | 2 +- src/input.c | 5 ++++- src/layout.c | 6 ++++++ src/render.c | 22 ++++++++++++++++++++++ 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 @@ #define MaxWidgetEvents 8 // Width of scroll bars in pixels. -#define ScrollBarWidth 16 +#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 @@ #include +#define Min(a, b) ((a) < (b) ? (a) : (b)) #define Max(a, b) ((a) > (b) ? (a) : (b)) /// Return true if the rectangle contains the point. @@ -85,7 +86,9 @@ static void ClickTable(uiTable* table, const uiMouseClickEvent* event) { static void ScrollTable(uiTable* table, const uiMouseScrollEvent* event) { assert(table); assert(event); - table->offset = Max(0, table->offset - event->scroll_offset); + table->offset = + Min(table->rows - table->num_visible_rows, + Max(0, table->offset - event->scroll_offset)); } /// 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) { return; } + table->height = height; + + // Compute the number of rows that are visible at once. + table->num_visible_rows = height / g_ui.font->header.glyph_height; + assert(table->num_visible_rows <= table->rows); + // Determine if there is vertical overflow. This determines whether we need to // render a scroll bar, in which case room must be made for it. 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) { uiRect original_subsurface = {0}; uiPoint original_pen = {0}; + int col_widths_sum = 0; + // Render header. if (table->header) { for (int col = 0; col < table->cols; ++col) { @@ -201,6 +203,9 @@ static void RenderTable(const uiTable* table, RenderState* state) { // Reset the original subsurface and pen for subsequent columns. PopSubsurface(state, &original_subsurface, &original_pen); + // Keep track of the sum of column widths to later render the scroll bar. + col_widths_sum += table->widths[col]; + // Next column. state->pen.x += table->widths[col]; } @@ -235,6 +240,23 @@ static void RenderTable(const uiTable* table, RenderState* state) { state->pen.y += g_ui.font->header.glyph_height; } state->pen.y = y0; + + // Render scrollbar. + if (table->flags.vertical_overflow) { + state->pen.x = col_widths_sum; + + const int y_start = (int)((double)table->offset / (double)table->rows * + (double)table->height); + + const int height = (int)((double)table->num_visible_rows / + (double)table->rows * (double)table->height); + + FillRect( + &(uiRect){.y = y_start, .width = ScrollBarWidth, .height = height}, + uiPink, state); + + state->pen.x = x0; + } } /// 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 { 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. + int height; // Height in pixels. + 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. + int num_visible_rows; // The number of rows that are visible at once. struct { bool vertical_overflow : 1; // True if contents overflow vertically. } flags; -- cgit v1.2.3