33#include <allegro5/allegro_primitives.h>
40#define N_GUI_POPUP_PAD_X 10.0f
42#define N_GUI_POPUP_PAD_Y 4.0f
44#define N_GUI_POPUP_SEP_H 7.0f
46#define N_GUI_POPUP_ARROW_W 16.0f
48#define N_GUI_POPUP_MIN_W 120.0f
51#define N_GUI_POPUP_OVERLAP 2.0f
54#define _POPUP_KIND_ROOT 0
56#define _POPUP_KIND_ITEM 1
58#define _POPUP_KIND_SUB 2
60#define _POPUP_KIND_SEP 3
130 return popup &&
id >= 0 &&
id < popup->
nb_entries;
146 float line =
font ? (float)al_get_font_line_height(
font) : 12.0f;
167 memset(e, 0,
sizeof(*e));
177 if (text && text[0]) {
178 e->
text = strdup(text);
179 if (!e->
text)
return -1;
182 e->
tip = strdup(tip);
211 if (!e->
shown)
return 0;
223 int i = 0, n = 0, pending_sep = -1, has_sub = 0;
228 lv->
rows = (
int*)calloc((
size_t)popup->
nb_entries + 1,
sizeof(
int));
229 lv->
row_y = (
float*)calloc((
size_t)popup->
nb_entries + 1,
sizeof(
float));
238 if (
font) widest = (float)al_get_text_width(
font, lv->
text);
243 if (e->
parent != level)
continue;
245 if (e->
shown && n > 0) pending_sep = i;
249 if (pending_sep >= 0) {
250 lv->
rows[n] = pending_sep;
262 float w = (float)al_get_text_width(
font, e->
text);
264 if (w > widest) widest = w;
272 return n > 0 ? 0 : -1;
281 for (r = 0; r < lv->
nb_rows; r++) {
284 if (ly >= lv->
row_y[r] && ly < lv->
row_y[r] + h)
return r;
306 if (lv->
window >= 0)
return 0;
309 if (!lv->
hook)
return -1;
314 if (lv->
window < 0)
return -1;
338 if (dw > 0.0f && x + lv->
w > dw) x = dw - lv->
w;
339 if (dh > 0.0f && y + lv->
h > dh) y = dh - lv->
h;
340 if (x < 0.0f) x = 0.0f;
341 if (y < 0.0f) y = 0.0f;
363 if (lv->
child == sub)
return;
405 float s = 1.0f, row_h = 0.0f, pad_x = 0.0f, pad_y = 0.0f;
409 if (!widget || !hook || !hook->
popup || !
font)
return;
419 float tr = 0, tg = 0, tb = 0, ta = 0, br = 0, bg = 0, bb = 0, ba = 0;
421 al_unmap_rgba_f(th->
text_normal, &tr, &tg, &tb, &ta);
422 al_unmap_rgba_f(th->
bg_normal, &br, &bg, &bb, &ba);
423 dim = al_map_rgba_f((tr + br) * 0.5f, (tg + bg) * 0.5f, (tb + bb) * 0.5f, ta);
425 al_draw_filled_rectangle(x, y, x + widget->
w, y + widget->
h, th->
bg_normal);
426 al_draw_rectangle(x + 0.5f, y + 0.5f, x + widget->
w - 0.5f, y + widget->
h - 0.5f, th->
border_normal, 1.0f);
430 al_draw_text(
font, dim, x + pad_x, y + pad_y, 0, lv->
text);
431 al_draw_line(x + pad_x * 0.5f, my, x + widget->
w - pad_x * 0.5f, my, th->
border_normal, 1.0f);
433 for (r = 0; r < lv->
nb_rows; r++) {
435 float ry = y + lv->
row_y[r];
442 al_draw_line(x + pad_x * 0.5f, my, x + widget->
w - pad_x * 0.5f, my, th->
border_normal, 1.0f);
448 if (lit) al_draw_filled_rectangle(x + 1.0f, ry, x + widget->
w - 1.0f, ry + row_h, th->
bg_hover);
450 if (e->
text) al_draw_text(
font,
ink, x + pad_x, ry + pad_y, 0, e->
text);
453 float ax = x + widget->
w - pad_x - 4.0f * s, ay = ry + row_h * 0.5f, a = 3.5f * s;
455 al_draw_filled_triangle(ax - a, ay - a, ax - a, ay + a, ax + a * 0.5f, ay,
ink);
466 int level = 0,
row = -1;
468 if (!hook || !hook->
popup || !ev)
return 0;
511 popup->
scale = scale > 0.0f ? scale : 1.0f;
540 if (!popup || !popup->
entries)
return;
544 if (text && text[0]) root->
text = strdup(text);
558 if (!popup)
return -1;
564 if (!popup || !popup->
entries)
return;
582 if (x >= lv->
x && x < lv->x + lv->
w && y >= lv->
y && y < lv->y + lv->
h)
return 1;
595 int level = 0, r = 0;
601 for (r = 0; r < lv->
nb_rows; r++) {
610 if (!popup || !*popup)
return;
612 for (i = 0; i < (*popup)->nb_entries; i++) {
627 free((*popup)->entries);
static int row_y(int row)
The screen y of the middle of one row of the open list.
static void ink(N_GUI_CTX *gui, int x0, int y0, int w, int h, int *bands, int *widest_gap, int *first_right)
draw the context into a memory bitmap and describe the ink inside a rectangle: how many separate band...
static const char * row(N_GUI_TREE *tree, int index)
the text of a visible row, "" past the end
void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
draw a line
FONT * font
the default 8x8 font, valid after allegro_init()
#define FreeNoLog(__ptr)
Free Handler without log.
#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
N_GUI_THEME theme
color theme for this widget
ALLEGRO_COLOR text_normal
text normal
ALLEGRO_COLOR border_normal
border normal
ALLEGRO_COLOR text_hover
text hover
float display_w
display/viewport width (set via n_gui_set_display_size)
int type
N_GUI_MOUSE_DOWN, _UP, _MOVE, _DRAG or _WHEEL.
float display_h
display/viewport height
ALLEGRO_COLOR bg_normal
background normal
ALLEGRO_COLOR bg_hover
background hover
ALLEGRO_FONT * default_font
default font.
#define N_GUI_MOUSE_DOWN
custom widget mouse event: a press inside it, button 1 or 2
void n_gui_raise_window(N_GUI_CTX *ctx, int window_id)
Bring a window to the front (top of draw order).
void n_gui_set_widget_tooltip(N_GUI_CTX *ctx, int widget_id, const char *text)
Set (or clear) the tooltip text of any widget.
void n_gui_window_set_rect(N_GUI_CTX *ctx, int window_id, float x, float y, float w, float h)
Move and resize a window at runtime, reflowing its widgets.
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.
#define N_GUI_WIN_FIXED_POSITION
disable window dragging (default:enable)
void n_gui_close_window(N_GUI_CTX *ctx, int window_id)
Close (hide) a window.
void n_gui_window_set_zorder(N_GUI_CTX *ctx, int window_id, int z_mode, int z_value)
Set window z-order mode and value.
#define N_GUI_WIN_FRAMELESS
frameless window: no title bar drawn, drag via window body unless N_GUI_WIN_FIXED_POSITION is also se...
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
int n_gui_window_is_open(N_GUI_CTX *ctx, int window_id)
Check if a window is currently visible.
int n_gui_add_window(N_GUI_CTX *ctx, const char *title, float x, float y, float w, float h)
Add a new pseudo-window to the context.
#define N_GUI_MOUSE_MOVE
custom widget mouse event: the pointer moved over it with no button held
#define N_GUI_MOUSE_UP
custom widget mouse event: the release of a button 1 press that began in it, wherever the pointer is ...
void n_gui_open_window(N_GUI_CTX *ctx, int window_id)
Open (show) a window.
#define N_GUI_ZORDER_POPUP
popup/modal dialogs: drawn above EVERYTHING including ALWAYS_ON_TOP windows.
void n_gui_window_set_flags(N_GUI_CTX *ctx, int window_id, int flags)
Set feature flags on a window.
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.
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
The top-level GUI context that holds all windows.
A mouse event handed to a custom widget, in the widget's own coordinates.
Color theme for a widget.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
int n_gui_popup_window(const N_GUI_POPUP *popup, int level)
The window of a level, for an application that wants to test it.
void n_gui_popup_set_title(N_GUI_POPUP *popup, const char *text)
Set the heading line over the top level.
void n_gui_popup_close(N_GUI_POPUP *popup)
Close every level without picking anything.
int n_gui_popup_press(N_GUI_POPUP *popup, int entry)
Press the row of an entry, as a click on it would.
int n_gui_popup_open(N_GUI_POPUP *popup, float x, float y)
Open the top level with its corner at a point.
int n_gui_popup_add_item(N_GUI_POPUP *popup, int parent, const char *text, int tag, const char *tip)
Add an item at the end of a level.
int n_gui_popup_add_separator(N_GUI_POPUP *popup, int parent)
Add a separator at the end of a level.
int n_gui_popup_hit(const N_GUI_POPUP *popup, float x, float y)
Is a point on any of its open levels.
#define N_GUI_POPUP_ROOT
the top level, as a parent for n_gui_popup_add_item() and the others
void n_gui_popup_set_shown(N_GUI_POPUP *popup, int entry, int shown)
Show or hide an entry.
int n_gui_popup_add_submenu(N_GUI_POPUP *popup, int parent, const char *text, const char *tip)
Add a submenu at the end of a level.
N_GUI_POPUP * n_gui_popup_new(N_GUI_CTX *ctx, float scale, N_GUI_POPUP_FN on_pick, void *user_data)
Make an empty popup menu in ctx, closed.
void(* N_GUI_POPUP_FN)(N_GUI_POPUP *popup, int tag, void *user_data)
called when an item is picked, after the popup has closed.
int n_gui_popup_is_open(const N_GUI_POPUP *popup)
Is its top level on screen.
void n_gui_popup_set_enabled(N_GUI_POPUP *popup, int entry, int enabled)
Enable or grey out an entry.
void n_gui_popup_free(N_GUI_POPUP **popup)
Close the popup and release the handle.
Common headers and low-level functions & define.