Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_gui_grid.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27
28#ifdef HAVE_ALLEGRO
29
30#include <math.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "nilorea/n_common.h"
35#include "nilorea/n_log.h"
36#include "nilorea/n_gui_grid.h"
37
39typedef struct {
43 int id;
45 int bar;
49 void* user_data;
51 size_t count;
53 float cell_w;
55 float cell_h;
57 float gap;
59 float scroll;
63 float bar_w;
65 float inner_w;
74
76static int _grid_columns_for(const _N_GUI_GRID* g, float w) {
77 int columns = (int)((w + g->gap) / (g->cell_w + g->gap));
78
79 return columns > 0 ? columns : 1;
80}
81
83static size_t _grid_rows_for(const _N_GUI_GRID* g, int columns) {
84 return (g->count + (size_t)columns - 1) / (size_t)columns;
85}
86
88static float _grid_step(const _N_GUI_GRID* g) {
89 return g->cell_h + g->gap;
90}
91
94static float _grid_content_h_for(const _N_GUI_GRID* g, float w) {
95 return g->gap + (float)_grid_rows_for(g, _grid_columns_for(g, w)) * _grid_step(g);
96}
97
99static void _grid_clamp(_N_GUI_GRID* g) {
100 float most = _grid_content_h_for(g, g->inner_w) - g->outer_h;
101
102 if (most < 0.0f) most = 0.0f;
103 if (g->scroll > most) g->scroll = most;
104 if (g->scroll < 0.0f) g->scroll = 0.0f;
105}
106
109 if (!g->bar_showing) return;
110 g->placing = 1;
113 g->placing = 0;
114}
115
117static void _grid_place(_N_GUI_GRID* g) {
118 /* Asked of the whole width first. A grid that needs a bar still needs
119 * one once the bar has its strip, and one that does not cannot be made
120 * to by narrowing it: narrowing a grid of fixed cells only adds rows.
121 * So one pass settles it. */
122 int want = g->count > 0 && _grid_content_h_for(g, g->outer_w) > g->outer_h + 0.5f;
123
124 g->inner_w = g->outer_w;
125 if (want) {
126 g->inner_w = g->outer_w - g->bar_w;
127 if (g->inner_w < 1.0f) g->inner_w = 1.0f;
128 }
129 n_gui_widget_set_rect(g->ctx, g->id, g->outer_x, g->outer_y, g->inner_w, g->outer_h);
130 n_gui_widget_set_rect(g->ctx, g->bar, g->outer_x + g->inner_w, g->outer_y, g->bar_w > 0.0f ? g->bar_w : 1.0f, g->outer_h);
131 /* hidden with the grid too: a bar left over a hidden grid is drawn on
132 * whatever took its place */
133 n_gui_set_widget_visible(g->ctx, g->bar, want && g->visible);
134 g->bar_showing = want;
135 if (!want) g->scroll = 0.0f;
136 _grid_clamp(g);
139}
140
142// cppcheck-suppress constParameterCallback ; callback signature must match N_GUI_CUSTOM_DRAW
143// cppcheck-suppress constParameter ; the same, under the id cppcheck 2.10 uses
144static void _grid_draw(N_GUI_WIDGET* widget, float x, float y, ALLEGRO_FONT* font, void* user_data) {
145 const _N_GUI_GRID* g = (const _N_GUI_GRID*)user_data;
146 int cx = 0, cy = 0, cw = 0, ch = 0;
147 int columns = 0;
148 size_t rows = 0, first_row = 0, last_row = 0, row = 0;
149 float step = 0.0f;
150
151 (void)font;
152 if (!widget || !g) return;
153 if (g->cb.draw_background) g->cb.draw_background(g->id, x, y, widget->w, widget->h, g->user_data);
154 if (!g->count || !g->cb.draw_cell) return;
155 columns = _grid_columns_for(g, widget->w);
156 rows = _grid_rows_for(g, columns);
157 step = _grid_step(g);
158 /* The rows the view touches, one either side of the arithmetic: the
159 * clipping rectangle cuts the overhang, and an off by one here would
160 * show as a strip of empty grid. */
161 first_row = g->scroll > g->gap ? (size_t)((g->scroll - g->gap) / step) : 0;
162 last_row = first_row + (size_t)(widget->h / step) + 1;
163 if (last_row >= rows) last_row = rows - 1;
164
165 /* the cells are cut at the grid, inside whatever the window cuts at */
166 al_get_clipping_rectangle(&cx, &cy, &cw, &ch);
167 {
168 int x0 = (int)x > cx ? (int)x : cx;
169 int y0 = (int)y > cy ? (int)y : cy;
170 int x1 = (int)(x + widget->w) < cx + cw ? (int)(x + widget->w) : cx + cw;
171 int y1 = (int)(y + widget->h) < cy + ch ? (int)(y + widget->h) : cy + ch;
172
173 if (x1 <= x0 || y1 <= y0) return;
174 al_set_clipping_rectangle(x0, y0, x1 - x0, y1 - y0);
175 }
176 for (row = first_row; row <= last_row; row++) {
177 int column = 0;
178
179 for (column = 0; column < columns; column++) {
180 size_t index = row * (size_t)columns + (size_t)column;
181
182 if (index >= g->count) break;
183 g->cb.draw_cell(g->id, index, x + g->gap + (float)column * (g->cell_w + g->gap), y + g->gap + (float)row * step - g->scroll, g->cell_w, g->cell_h, g->user_data);
184 }
185 }
186 al_set_clipping_rectangle(cx, cy, cw, ch);
187 if (g->cb.visible) {
188 /* one row beyond the bottom, so a steady scroll does not outrun
189 * whatever prepares the cells */
190 size_t first = first_row * (size_t)columns;
191 size_t last = (last_row + 2) * (size_t)columns;
192
193 if (last > g->count) last = g->count;
194 g->cb.visible(g->id, first, last, g->user_data);
195 }
196}
197
199static int _grid_index_local(const _N_GUI_GRID* g, float w, float lx, float ly, size_t* index) {
200 int columns = _grid_columns_for(g, w);
201 long column = (long)floorf((lx - g->gap) / (g->cell_w + g->gap));
202 float content_y = ly - g->gap + g->scroll;
203 long row = content_y < 0.0f ? 0 : (long)floorf(content_y / _grid_step(g));
204 size_t at = 0;
205
206 if (column < 0) column = 0;
207 if (column >= columns) column = columns - 1;
208 at = (size_t)row * (size_t)columns + (size_t)column;
209 if (at >= g->count) return FALSE;
210 *index = at;
211 return TRUE;
212}
213
215// cppcheck-suppress constParameterCallback ; callback signature must match N_GUI_CUSTOM_MOUSE
216// cppcheck-suppress constParameter ; the same, under the id cppcheck 2.10 uses
217static int _grid_mouse(int widget_id, const N_GUI_MOUSE_EVENT* ev, void* user_data) {
218 _N_GUI_GRID* g = (_N_GUI_GRID*)user_data;
219 const N_GUI_WIDGET* wgt = g ? n_gui_get_widget(g->ctx, widget_id) : NULL;
220
221 if (!g || !wgt) return 0;
222 if (ev->type == N_GUI_MOUSE_WHEEL) {
223 /* the caller first: a turn it takes is not a scroll */
224 if (g->cb.wheel && g->cb.wheel(widget_id, ev->dz, ev->modifiers, g->user_data)) {
226 return 1;
227 }
228 /* one notch, one row: the unit the grid is read in */
229 g->scroll -= (float)ev->dz * _grid_step(g);
230 _grid_clamp(g);
233 return 1;
234 }
235 if (ev->type == N_GUI_MOUSE_DOWN) {
236 size_t index = 0;
237 float sx = 0.0f, sy = 0.0f;
238
239 if (!_grid_index_local(g, wgt->w, ev->x, ev->y, &index)) return 0;
240 if (!g->cb.press) return 1;
241 n_gui_widget_screen_rect(g->ctx, widget_id, &sx, &sy, NULL, NULL);
242 g->cb.press(widget_id, index, ev->button, sx + ev->x, sy + ev->y, g->user_data);
243 return 1;
244 }
245 return 0;
246}
247
249static void _grid_on_bar(int widget_id, double pos, void* user_data) {
250 _N_GUI_GRID* g = (_N_GUI_GRID*)user_data;
251
252 (void)widget_id;
253 /* a bar being told where it is reports it as a move; following that
254 * would place the bar again, and the grid would walk under the hand */
255 if (!g || g->placing) return;
256 g->scroll = (float)pos;
257 _grid_clamp(g);
259}
260
265static void _grid_destroy(void* user_data) {
266 free(user_data);
267}
268
270static _N_GUI_GRID* _grid_of(N_GUI_CTX* ctx, int widget_id) {
271 const N_GUI_WIDGET* wgt = ctx ? n_gui_get_widget(ctx, widget_id) : NULL;
272 const N_GUI_CUSTOM_DATA* cd = NULL;
273
274 if (!wgt || wgt->type != N_GUI_TYPE_CUSTOM || !wgt->data) return NULL;
275 cd = (const N_GUI_CUSTOM_DATA*)wgt->data;
276 /* the paint callback says what the widget is */
277 if (cd->draw != _grid_draw) return NULL;
278 return (_N_GUI_GRID*)cd->user_data;
279}
280
281int n_gui_grid_new(N_GUI_CTX* ctx, int window_id, const N_GUI_GRID_CALLBACKS* callbacks, void* user_data) {
282 _N_GUI_GRID* g = NULL;
283
284 __n_assert(ctx, return -1);
285 __n_assert(callbacks, return -1);
286 if (!callbacks->draw_cell) {
287 n_log(LOG_ERR, "grid: draw_cell is required");
288 return -1;
289 }
290 g = (_N_GUI_GRID*)calloc(1, sizeof(*g));
291 if (!g) return -1;
292 g->ctx = ctx;
293 g->cb = *callbacks;
294 g->user_data = user_data;
295 g->cell_w = 64.0f;
296 g->cell_h = 64.0f;
297 g->gap = 4.0f;
298 g->outer_w = 16.0f;
299 g->outer_h = 16.0f;
300 g->inner_w = 16.0f;
301 g->bar_w = 12.0f;
302 g->visible = 1;
303 g->id = n_gui_add_custom(ctx, window_id, 0.0f, 0.0f, 16.0f, 16.0f, _grid_draw, g);
304 if (g->id < 0) {
305 free(g);
306 return -1;
307 }
310 g->bar = n_gui_add_scrollbar(ctx, window_id, 0.0f, 0.0f, 16.0f, 16.0f, N_GUI_SCROLLBAR_V, N_GUI_SHAPE_ROUNDED, 1.0, 1.0, _grid_on_bar, g);
311 if (g->bar < 0) {
312 n_log(LOG_ERR, "grid: cannot create its scrollbar");
313 /* the widget owns the state now; it goes when the window does */
314 n_gui_set_widget_visible(ctx, g->id, 0);
315 return -1;
316 }
317 n_gui_set_widget_visible(ctx, g->bar, 0);
318 return g->id;
319}
320
321void n_gui_grid_set_rect(N_GUI_CTX* ctx, int widget_id, float x, float y, float w, float h, float bar_w) {
322 _N_GUI_GRID* g = _grid_of(ctx, widget_id);
323
324 if (!g) return;
325 g->outer_x = x;
326 g->outer_y = y;
327 g->outer_w = w > 1.0f ? w : 1.0f;
328 g->outer_h = h > 1.0f ? h : 1.0f;
329 g->bar_w = bar_w > 0.0f ? bar_w : 0.0f;
330 _grid_place(g);
331}
332
333void n_gui_grid_set_cell_size(N_GUI_CTX* ctx, int widget_id, float cell_w, float cell_h, float gap) {
334 _N_GUI_GRID* g = _grid_of(ctx, widget_id);
335
336 if (!g || cell_w <= 0.0f || cell_h <= 0.0f) return;
337 g->cell_w = cell_w;
338 g->cell_h = cell_h;
339 g->gap = gap > 0.0f ? gap : 0.0f;
340 _grid_place(g);
341}
342
343void n_gui_grid_set_count(N_GUI_CTX* ctx, int widget_id, size_t count) {
344 _N_GUI_GRID* g = _grid_of(ctx, widget_id);
345
346 if (!g) return;
347 g->count = count;
348 _grid_place(g);
349}
350
351void n_gui_grid_set_visible(N_GUI_CTX* ctx, int widget_id, int visible) {
352 _N_GUI_GRID* g = _grid_of(ctx, widget_id);
353
354 if (!g) return;
355 g->visible = visible ? 1 : 0;
358 n_gui_mark_dirty(ctx);
359}
360
361int n_gui_grid_columns(N_GUI_CTX* ctx, int widget_id) {
362 const _N_GUI_GRID* g = _grid_of(ctx, widget_id);
363
364 return g ? _grid_columns_for(g, g->inner_w) : 0;
365}
366
367float n_gui_grid_get_scroll(N_GUI_CTX* ctx, int widget_id) {
368 const _N_GUI_GRID* g = _grid_of(ctx, widget_id);
369
370 return g ? g->scroll : 0.0f;
371}
372
373void n_gui_grid_set_scroll(N_GUI_CTX* ctx, int widget_id, float scroll) {
374 _N_GUI_GRID* g = _grid_of(ctx, widget_id);
375
376 if (!g) return;
377 g->scroll = scroll;
378 _grid_clamp(g);
380 n_gui_mark_dirty(ctx);
381}
382
383void n_gui_grid_scroll_to(N_GUI_CTX* ctx, int widget_id, size_t index) {
384 _N_GUI_GRID* g = _grid_of(ctx, widget_id);
385 float top = 0.0f, bottom = 0.0f;
386 size_t row = 0;
387
388 if (!g || index >= g->count) return;
389 row = index / (size_t)_grid_columns_for(g, g->inner_w);
390 /* the first row counts from the very top, so the gap above it shows */
391 top = row ? g->gap + (float)row * _grid_step(g) : 0.0f;
392 bottom = g->gap + (float)(row + 1) * _grid_step(g);
393 if (top < g->scroll) g->scroll = top;
394 if (bottom > g->scroll + g->outer_h) g->scroll = bottom - g->outer_h;
395 _grid_clamp(g);
397 n_gui_mark_dirty(ctx);
398}
399
400int n_gui_grid_index_at(N_GUI_CTX* ctx, int widget_id, float x, float y, size_t* index) {
401 const _N_GUI_GRID* g = _grid_of(ctx, widget_id);
402 float gx = 0.0f, gy = 0.0f, gw = 0.0f, gh = 0.0f;
403
404 __n_assert(index, return FALSE);
405 if (!g || !g->visible || !g->count) return FALSE;
406 if (!n_gui_widget_screen_rect(ctx, widget_id, &gx, &gy, &gw, &gh)) return FALSE;
407 if (x < gx || x >= gx + gw || y < gy || y >= gy + gh) return FALSE;
408 return _grid_index_local(g, gw, x - gx, y - gy, index);
409}
410
411int n_gui_grid_cell_rect(N_GUI_CTX* ctx, int widget_id, size_t index, float* x, float* y, float* w, float* h) {
412 const _N_GUI_GRID* g = _grid_of(ctx, widget_id);
413 float gx = 0.0f, gy = 0.0f, gw = 0.0f, gh = 0.0f, cx = 0.0f, cy = 0.0f;
414 int columns = 0;
415
416 if (!g || index >= g->count) return FALSE;
417 n_gui_widget_screen_rect(ctx, widget_id, &gx, &gy, &gw, &gh);
418 columns = _grid_columns_for(g, g->inner_w);
419 cx = gx + g->gap + (float)(index % (size_t)columns) * (g->cell_w + g->gap);
420 cy = gy + g->gap + (float)(index / (size_t)columns) * _grid_step(g) - g->scroll;
421 if (x) *x = cx;
422 if (y) *y = cy;
423 if (w) *w = g->cell_w;
424 if (h) *h = g->cell_h;
425 return (cy + g->cell_h > gy && cy < gy + gh) ? TRUE : FALSE;
426}
427
428int n_gui_grid_scrollbar(N_GUI_CTX* ctx, int widget_id) {
429 const _N_GUI_GRID* g = _grid_of(ctx, widget_id);
430
431 return g ? g->bar : -1;
432}
433
434int n_gui_grid_scrollbar_showing(N_GUI_CTX* ctx, int widget_id) {
435 const _N_GUI_GRID* g = _grid_of(ctx, widget_id);
436
437 return g ? g->bar_showing : 0;
438}
439
440#endif /* HAVE_ALLEGRO */
static N_GUI_MOUSE_EVENT last
the last event the widget was told of, and how many
static void visible(int widget_id, size_t first, size_t last, void *user_data)
the range to prepare
Definition ex_gui_grid.c:86
static const char * row(N_GUI_TREE *tree, int index)
the text of a visible row, "" past the end
FONT * font
the default 8x8 font, valid after allegro_init()
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
float h
height
Definition n_gui.h:1104
float y
pointer y from the widget's top edge; outside 0..h during a DRAG
Definition n_gui.h:1208
float w
width
Definition n_gui.h:1102
int type
widget type (N_GUI_TYPE_*)
Definition n_gui.h:1096
void * user_data
opaque user pointer handed back to the callback (not owned by n_gui)
Definition n_gui.h:1233
int dz
wheel steps for WHEEL, positive away from the user; 0 otherwise
Definition n_gui.h:1210
int button
1 left, 2 right for DOWN; 1 for UP and DRAG; 0 otherwise
Definition n_gui.h:1204
N_GUI_CUSTOM_DRAW draw
paint callback invoked during n_gui_draw (NULL = draw nothing)
Definition n_gui.h:1231
void * data
widget-specific data (union via void pointer)
Definition n_gui.h:1122
int type
N_GUI_MOUSE_DOWN, _UP, _MOVE, _DRAG or _WHEEL.
Definition n_gui.h:1202
int modifiers
the modifier keys held when the event came, ALLEGRO_KEYMOD_SHIFT, _CTRL, _ALT and _ALTGR ORed,...
Definition n_gui.h:1215
float x
pointer x from the widget's left edge; outside 0..w during a DRAG
Definition n_gui.h:1206
#define N_GUI_MOUSE_DOWN
custom widget mouse event: a press inside it, button 1 or 2
Definition n_gui.h:1187
int n_gui_widget_screen_rect(N_GUI_CTX *ctx, int widget_id, float *x, float *y, float *w, float *h)
Where a widget is on screen, rather than inside its window.
Definition n_gui.c:2091
#define N_GUI_MOUSE_WHEEL
custom widget mouse event: the wheel turned over it
Definition n_gui.h:1197
void n_gui_widget_set_rect(N_GUI_CTX *ctx, int widget_id, float x, float y, float w, float h)
Move and resize a widget after creation.
Definition n_gui.c:3854
void n_gui_custom_set_mouse(N_GUI_CTX *ctx, int widget_id, N_GUI_CUSTOM_MOUSE on_mouse, void *user_data)
give a custom widget mouse input
Definition n_gui.c:5730
N_GUI_WIDGET * n_gui_get_widget(N_GUI_CTX *ctx, int widget_id)
Get a widget pointer by id.
Definition n_gui.c:3701
#define N_GUI_TYPE_CUSTOM
widget type: owner-draw custom widget (rendering delegated to a callback)
Definition n_gui.h:140
int n_gui_add_scrollbar(N_GUI_CTX *ctx, int window_id, float x, float y, float w, float h, int orientation, int shape, double content_size, double viewport_size, void(*on_scroll)(int, double, void *), void *user_data)
Add a scrollbar widget.
Definition n_gui.c:3241
void n_gui_custom_set_destroy(N_GUI_CTX *ctx, int widget_id, void(*destroy)(void *user_data))
hand a custom widget's paint user pointer to the widget
Definition n_gui.c:5745
#define N_GUI_SHAPE_ROUNDED
rounded rectangle shape
Definition n_gui.h:172
void n_gui_set_widget_visible(N_GUI_CTX *ctx, int widget_id, int visible)
Show or hide a widget.
Definition n_gui.c:3828
void n_gui_mark_dirty(N_GUI_CTX *ctx)
Mark the GUI as needing a redraw.
Definition n_gui.c:1188
void n_gui_scrollbar_set_sizes(N_GUI_CTX *ctx, int widget_id, double content_size, double viewport_size)
set the content and viewport sizes of a scrollbar widget
Definition n_gui.c:4338
#define N_GUI_SCROLLBAR_V
vertical scrollbar
Definition n_gui.h:192
int n_gui_add_custom(N_GUI_CTX *ctx, int window_id, float x, float y, float w, float h, N_GUI_CUSTOM_DRAW draw, void *user_data)
add an owner-draw custom widget; returns the widget id or -1
Definition n_gui.c:5698
void n_gui_scrollbar_set_pos(N_GUI_CTX *ctx, int widget_id, double pos)
set the scroll position of a scrollbar widget
Definition n_gui.c:4307
The top-level GUI context that holds all windows.
Definition n_gui.h:1669
Owner-draw custom widget data: a paint callback, an optional mouse callback, and their user pointers.
Definition n_gui.h:1229
A mouse event handed to a custom widget, in the widget's own coordinates.
Definition n_gui.h:1200
A single GUI widget.
Definition n_gui.h:1092
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
void(* draw_background)(int widget_id, float x, float y, float w, float h, void *user_data)
Draw behind the cells, over the whole grid, before any cell; with no cells, the only thing drawn.
Definition n_gui_grid.h:75
void(* press)(int widget_id, size_t index, int button, float x, float y, void *user_data)
A press of button (1 or 2) on cell index, at screen x, y.
Definition n_gui_grid.h:81
void(* draw_cell)(int widget_id, size_t index, float x, float y, float w, float h, void *user_data)
Draw cell index in the box at x, y, w by h, on screen.
Definition n_gui_grid.h:72
int(* wheel)(int widget_id, int dz, int modifiers, void *user_data)
A wheel turn of dz notches over the grid, positive away from the user, with the modifier keys held (A...
Definition n_gui_grid.h:87
void(* visible)(int widget_id, size_t first, size_t last, void *user_data)
Called after each draw with the cells drawn and one row beyond, first included and last excluded: wha...
Definition n_gui_grid.h:78
void n_gui_grid_set_rect(N_GUI_CTX *ctx, int widget_id, float x, float y, float w, float h, float bar_w)
Place the grid and its scrollbar in a rectangle of the window.
Definition n_gui_grid.c:321
void n_gui_grid_set_scroll(N_GUI_CTX *ctx, int widget_id, float scroll)
Set the scroll offset, clamped to the content.
Definition n_gui_grid.c:373
int n_gui_grid_new(N_GUI_CTX *ctx, int window_id, const N_GUI_GRID_CALLBACKS *callbacks, void *user_data)
Add a grid, and its scrollbar, to a window.
Definition n_gui_grid.c:281
int n_gui_grid_index_at(N_GUI_CTX *ctx, int widget_id, float x, float y, size_t *index)
Which cell is at a point on screen.
Definition n_gui_grid.c:400
void n_gui_grid_set_count(N_GUI_CTX *ctx, int widget_id, size_t count)
Set how many cells there are.
Definition n_gui_grid.c:343
int n_gui_grid_columns(N_GUI_CTX *ctx, int widget_id)
How many cells a row holds at the grid's width.
Definition n_gui_grid.c:361
int n_gui_grid_cell_rect(N_GUI_CTX *ctx, int widget_id, size_t index, float *x, float *y, float *w, float *h)
Where a cell is on screen, whether or not it is scrolled into view.
Definition n_gui_grid.c:411
void n_gui_grid_scroll_to(N_GUI_CTX *ctx, int widget_id, size_t index)
Scroll the least that brings a cell's whole row into view.
Definition n_gui_grid.c:383
int n_gui_grid_scrollbar_showing(N_GUI_CTX *ctx, int widget_id)
Whether the scrollbar is shown, which is whether the rows overflow.
Definition n_gui_grid.c:434
float n_gui_grid_get_scroll(N_GUI_CTX *ctx, int widget_id)
The scroll offset, in pixels from the top of the content.
Definition n_gui_grid.c:367
void n_gui_grid_set_cell_size(N_GUI_CTX *ctx, int widget_id, float cell_w, float cell_h, float gap)
Set the size of a cell and the gap around cells.
Definition n_gui_grid.c:333
void n_gui_grid_set_visible(N_GUI_CTX *ctx, int widget_id, int visible)
Show or hide the grid and its scrollbar together.
Definition n_gui_grid.c:351
int n_gui_grid_scrollbar(N_GUI_CTX *ctx, int widget_id)
The grid's scrollbar widget.
Definition n_gui_grid.c:428
What the grid asks of its caller.
Definition n_gui_grid.h:69
Common headers and low-level functions & define.
static void _grid_on_bar(int widget_id, double pos, void *user_data)
the scrollbar's callback: the view follows a drag of the bar
Definition n_gui_grid.c:249
int placing
set while the bar is being told where it is, so its callback is not taken for a drag
Definition n_gui_grid.c:72
float outer_w
Definition n_gui_grid.c:61
static void _grid_draw(N_GUI_WIDGET *widget, float x, float y, ALLEGRO_FONT *font, void *user_data)
custom draw callback
Definition n_gui_grid.c:144
static size_t _grid_rows_for(const _N_GUI_GRID *g, int columns)
helper: rows the cells make at a column count
Definition n_gui_grid.c:83
static void _grid_clamp(_N_GUI_GRID *g)
helper: keep the view inside the content
Definition n_gui_grid.c:99
static void _grid_sync_bar(_N_GUI_GRID *g)
helper: tell the scrollbar where the view is
Definition n_gui_grid.c:108
static _N_GUI_GRID * _grid_of(N_GUI_CTX *ctx, int widget_id)
helper: find a grid's state behind a widget id, or NULL
Definition n_gui_grid.c:270
int id
the grid widget
Definition n_gui_grid.c:43
static int _grid_columns_for(const _N_GUI_GRID *g, float w)
helper: cells across a width
Definition n_gui_grid.c:76
static void _grid_destroy(void *user_data)
the widget's destroy callback.
Definition n_gui_grid.c:265
int bar_showing
whether the bar is shown
Definition n_gui_grid.c:69
float bar_w
width of the scrollbar's strip
Definition n_gui_grid.c:63
static int _grid_index_local(const _N_GUI_GRID *g, float w, float lx, float ly, size_t *index)
helper: the cell at a widget-local point, the rules of n_gui_grid_index_at
Definition n_gui_grid.c:199
static float _grid_step(const _N_GUI_GRID *g)
helper: one row and the gap below it
Definition n_gui_grid.c:88
float outer_h
Definition n_gui_grid.c:61
void * user_data
handed back to the callbacks
Definition n_gui_grid.c:49
float scroll
pixels from the top of the content to the top of the view
Definition n_gui_grid.c:59
float outer_x
the rectangle n_gui_grid_set_rect() was given, scrollbar included
Definition n_gui_grid.c:61
static void _grid_place(_N_GUI_GRID *g)
helper: decide whether the bar shows, and place the grid and the bar
Definition n_gui_grid.c:117
float outer_y
Definition n_gui_grid.c:61
static int _grid_mouse(int widget_id, const N_GUI_MOUSE_EVENT *ev, void *user_data)
custom mouse callback
Definition n_gui_grid.c:217
N_GUI_GRID_CALLBACKS cb
what the caller asked for
Definition n_gui_grid.c:47
int bar
its scrollbar
Definition n_gui_grid.c:45
float gap
gap between and around cells
Definition n_gui_grid.c:57
float inner_w
the grid's own width, the strip taken off when the bar shows
Definition n_gui_grid.c:65
float cell_h
cell height
Definition n_gui_grid.c:55
static float _grid_content_h_for(const _N_GUI_GRID *g, float w)
helper: content height at a width: the gap above the first row, then each row with its gap
Definition n_gui_grid.c:94
N_GUI_CTX * ctx
the context, for the callbacks that are handed only an id
Definition n_gui_grid.c:41
size_t count
how many cells
Definition n_gui_grid.c:51
int visible
whether the caller wants it shown
Definition n_gui_grid.c:67
float cell_w
cell width
Definition n_gui_grid.c:53
a grid's state, owned by its custom widget
Definition n_gui_grid.c:39
A virtualised grid of cells for N_GUI, scrolled vertically.
Generic log system.