77 int columns = (int)((w + g->
gap) / (g->
cell_w + g->
gap));
79 return columns > 0 ? columns : 1;
84 return (g->
count + (
size_t)columns - 1) / (size_t)columns;
102 if (most < 0.0f) most = 0.0f;
135 if (!want) g->
scroll = 0.0f;
146 int cx = 0, cy = 0, cw = 0, ch = 0;
148 size_t rows = 0, first_row = 0, last_row = 0,
row = 0;
152 if (!widget || !g)
return;
162 last_row = first_row + (size_t)(widget->
h / step) + 1;
163 if (last_row >= rows) last_row = rows - 1;
166 al_get_clipping_rectangle(&cx, &cy, &cw, &ch);
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;
173 if (x1 <= x0 || y1 <= y0)
return;
174 al_set_clipping_rectangle(x0, y0, x1 - x0, y1 - y0);
176 for (
row = first_row;
row <= last_row;
row++) {
179 for (column = 0; column < columns; column++) {
180 size_t index =
row * (size_t)columns + (
size_t)column;
182 if (index >= g->
count)
break;
186 al_set_clipping_rectangle(cx, cy, cw, ch);
190 size_t first = first_row * (size_t)columns;
191 size_t last = (last_row + 2) * (
size_t)columns;
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));
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;
221 if (!g || !wgt)
return 0;
237 float sx = 0.0f, sy = 0.0f;
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);
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;
336 if (!g || cell_w <= 0.0f || cell_h <= 0.0f)
return;
339 g->
gap = gap > 0.0f ? gap : 0.0f;
370 return g ? g->
scroll : 0.0f;
385 float top = 0.0f, bottom = 0.0f;
388 if (!g || index >= g->
count)
return;
393 if (top < g->scroll) g->
scroll = top;
402 float gx = 0.0f, gy = 0.0f, gw = 0.0f, gh = 0.0f;
407 if (x < gx || x >= gx + gw || y < gy || y >= gy + gh)
return FALSE;
413 float gx = 0.0f, gy = 0.0f, gw = 0.0f, gh = 0.0f, cx = 0.0f, cy = 0.0f;
416 if (!g || index >= g->
count)
return FALSE;
419 cx = gx + g->
gap + (float)(index % (
size_t)columns) * (g->
cell_w + g->
gap);
425 return (cy + g->
cell_h > gy && cy < gy + gh) ? TRUE : FALSE;
431 return g ? g->
bar : -1;
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
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
float y
pointer y from the widget's top edge; outside 0..h during a DRAG
int type
widget type (N_GUI_TYPE_*)
void * user_data
opaque user pointer handed back to the callback (not owned by n_gui)
int dz
wheel steps for WHEEL, positive away from the user; 0 otherwise
int button
1 left, 2 right for DOWN; 1 for UP and DRAG; 0 otherwise
N_GUI_CUSTOM_DRAW draw
paint callback invoked during n_gui_draw (NULL = draw nothing)
void * data
widget-specific data (union via void pointer)
int type
N_GUI_MOUSE_DOWN, _UP, _MOVE, _DRAG or _WHEEL.
int modifiers
the modifier keys held when the event came, ALLEGRO_KEYMOD_SHIFT, _CTRL, _ALT and _ALTGR ORed,...
float x
pointer x from the widget's left edge; outside 0..w during a DRAG
#define N_GUI_MOUSE_DOWN
custom widget mouse event: a press inside it, button 1 or 2
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.
#define N_GUI_MOUSE_WHEEL
custom widget mouse event: the wheel turned over it
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.
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
N_GUI_WIDGET * n_gui_get_widget(N_GUI_CTX *ctx, int widget_id)
Get a widget pointer by id.
#define N_GUI_TYPE_CUSTOM
widget type: owner-draw custom widget (rendering delegated to a callback)
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.
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
#define N_GUI_SHAPE_ROUNDED
rounded rectangle shape
void n_gui_set_widget_visible(N_GUI_CTX *ctx, int widget_id, int visible)
Show or hide a widget.
void n_gui_mark_dirty(N_GUI_CTX *ctx)
Mark the GUI as needing a redraw.
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
#define N_GUI_SCROLLBAR_V
vertical scrollbar
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
void n_gui_scrollbar_set_pos(N_GUI_CTX *ctx, int widget_id, double pos)
set the scroll position of a scrollbar widget
The top-level GUI context that holds all windows.
Owner-draw custom widget data: a paint callback, an optional mouse callback, and their user pointers.
A mouse event handed to a custom widget, in the widget's own coordinates.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
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.
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.
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.
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...
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...
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.
void n_gui_grid_set_scroll(N_GUI_CTX *ctx, int widget_id, float scroll)
Set the scroll offset, clamped to the content.
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.
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.
void n_gui_grid_set_count(N_GUI_CTX *ctx, int widget_id, size_t count)
Set how many cells there are.
int n_gui_grid_columns(N_GUI_CTX *ctx, int widget_id)
How many cells a row holds at the grid's width.
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.
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.
int n_gui_grid_scrollbar_showing(N_GUI_CTX *ctx, int widget_id)
Whether the scrollbar is shown, which is whether the rows overflow.
float n_gui_grid_get_scroll(N_GUI_CTX *ctx, int widget_id)
The scroll offset, in pixels from the top of the content.
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.
void n_gui_grid_set_visible(N_GUI_CTX *ctx, int widget_id, int visible)
Show or hide the grid and its scrollbar together.
int n_gui_grid_scrollbar(N_GUI_CTX *ctx, int widget_id)
The grid's scrollbar widget.
What the grid asks of its caller.
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
int placing
set while the bar is being told where it is, so its callback is not taken for a drag
static void _grid_draw(N_GUI_WIDGET *widget, float x, float y, ALLEGRO_FONT *font, void *user_data)
custom draw callback
static size_t _grid_rows_for(const _N_GUI_GRID *g, int columns)
helper: rows the cells make at a column count
static void _grid_clamp(_N_GUI_GRID *g)
helper: keep the view inside the content
static void _grid_sync_bar(_N_GUI_GRID *g)
helper: tell the scrollbar where the view is
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
static int _grid_columns_for(const _N_GUI_GRID *g, float w)
helper: cells across a width
static void _grid_destroy(void *user_data)
the widget's destroy callback.
int bar_showing
whether the bar is shown
float bar_w
width of the scrollbar's strip
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
static float _grid_step(const _N_GUI_GRID *g)
helper: one row and the gap below it
void * user_data
handed back to the callbacks
float scroll
pixels from the top of the content to the top of the view
float outer_x
the rectangle n_gui_grid_set_rect() was given, scrollbar included
static void _grid_place(_N_GUI_GRID *g)
helper: decide whether the bar shows, and place the grid and the bar
static int _grid_mouse(int widget_id, const N_GUI_MOUSE_EVENT *ev, void *user_data)
custom mouse callback
N_GUI_GRID_CALLBACKS cb
what the caller asked for
float gap
gap between and around cells
float inner_w
the grid's own width, the strip taken off when the bar shows
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
N_GUI_CTX * ctx
the context, for the callbacks that are handed only an id
size_t count
how many cells
int visible
whether the caller wants it shown
a grid's state, owned by its custom widget
A virtualised grid of cells for N_GUI, scrolled vertically.