29#define ALLEGRO_UNSTABLE 1
67 " -V log level: LOG_NULL, LOG_NOTICE, LOG_INFO, LOG_ERR, LOG_DEBUG\n"
77 while ((
getoptret = getopt(argc, argv,
"hvV:")) != EOF) {
80 fprintf(stderr,
"build date: %s %s\n", __DATE__, __TIME__);
83 if (!strcmp(
"LOG_NULL", optarg))
85 else if (!strcmp(
"LOG_NOTICE", optarg))
87 else if (!strcmp(
"LOG_INFO", optarg))
89 else if (!strcmp(
"LOG_ERR", optarg))
91 else if (!strcmp(
"LOG_DEBUG", optarg))
94 fprintf(stderr,
"%s is not a valid log level\n", optarg);
103 if (optopt ==
'V') fprintf(stderr,
"\n Missing log level\n");
115 al_set_target_bitmap(target);
116 al_clear_to_color(al_map_rgb(0, 0, 0));
117 gui->tooltip_widget_id = armed ? widget_id : -1;
120 gui->tooltip_armed_at = al_get_time() - (double)
gui->style.tooltip_delay - 1.0;
128 ALLEGRO_LOCKED_REGION* la = al_lock_bitmap(a, ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE, ALLEGRO_LOCK_READONLY);
129 ALLEGRO_LOCKED_REGION* lb = al_lock_bitmap(b, ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE, ALLEGRO_LOCK_READONLY);
130 int min_x =
TT_W, max_x = -1;
133 for (
int y = 0; y <
TT_H; y++) {
134 const unsigned char* ra = (
const unsigned char*)la->data + (ptrdiff_t)y * la->pitch;
135 const unsigned char* rb = (
const unsigned char*)lb->data + (ptrdiff_t)y * lb->pitch;
136 for (
int x = 0; x <
TT_W; x++) {
137 if (memcmp(ra + (ptrdiff_t)x * 4, rb + (ptrdiff_t)x * 4, 4) != 0) {
138 if (x < min_x) min_x = x;
139 if (x > max_x) max_x = x;
144 if (la) al_unlock_bitmap(a);
145 if (lb) al_unlock_bitmap(b);
147 return (max_x < 0) ? 0 : (max_x - min_x + 1);
155 memset(&ev, 0,
sizeof(ev));
156 ev.type = ALLEGRO_EVENT_MOUSE_AXES;
160 return gui->tooltip_widget_id;
163int main(
int argc,
char** argv) {
166 if (!al_init() || !al_init_font_addon()) {
170 al_init_primitives_addon();
173 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
174 ALLEGRO_BITMAP* plain = al_create_bitmap(
TT_W,
TT_H);
175 ALLEGRO_BITMAP* tipped = al_create_bitmap(
TT_W,
TT_H);
176 ALLEGRO_FONT*
font = al_create_builtin_font();
177 if (!plain || !tipped || !
font) {
196 "Promote this panel to a real OS window, and back again, "
197 "which is the sort of sentence a tooltip has to hold when it "
198 "explains something instead of restating the label beside it.");
204 const int btn_x = (int)(
PANEL_X + 5.0f + 15.0f);
205 const int btn_y = (int)(10.0f +
gui->style.titlebar_h + 5.0f + 10.0f);
225 gui->style.tooltip_max_w = 480.0f;
231 expect_true(
"bubble honours tooltip_max_w", capped <= 480 + 16 + 2);
232 expect_true(
"bubble still uses the width it is allowed", capped > 480 / 2);
235 gui->style.tooltip_max_w = 0.0f;
239 expect_true(
"tooltip_max_w = 0 restores wrap-at-the-clamp-edge", uncapped > capped);
240 n_log(
LOG_INFO,
"capped %d px, uncapped %d px", capped, uncapped);
242 gui->style.tooltip_max_w = 480.0f;
267 int divider_x = (int)(ox +
SPLIT_W * 0.5f);
269 expect_true(
"pointer on the divider arms the split pane",
271 expect_true(
"pointer well left of the divider arms nothing",
273 expect_true(
"pointer well right of the divider arms nothing",
279 expect_true(
"a widget above the pane still arms its own tooltip",
293 gui->mouse_x = btn_x;
294 gui->mouse_y = btn_y;
304 expect_true(
"nothing is pending while a window covers the pointer",
314 expect_true(
"a window that does not cover the pointer changes nothing",
331 for (button = 1; button <= 3; button++) {
332 expect_true(
"the pointer arms the button's tooltip",
334 memset(&ev, 0,
sizeof(ev));
335 ev.type = ALLEGRO_EVENT_MOUSE_BUTTON_DOWN;
336 ev.mouse.button = (unsigned)button;
340 expect_true(
"and a press on any button dismisses it",
gui->tooltip_widget_id == -1);
342 memset(&ev, 0,
sizeof(ev));
343 ev.type = ALLEGRO_EVENT_MOUSE_BUTTON_UP;
344 ev.mouse.button = (unsigned)button;
352 al_destroy_font(
font);
353 al_destroy_bitmap(plain);
354 al_destroy_bitmap(tipped);
void process_args(int argc, char **argv)
static void expect_true(const char *label, int cond)
FONT * font
the default 8x8 font, valid after allegro_init()
void n_gui_set_display_size(N_GUI_CTX *ctx, float w, float h)
set the display (viewport) size so global scrollbars can be computed.
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.
int n_gui_process_event(N_GUI_CTX *ctx, ALLEGRO_EVENT event)
Process an allegro event through the GUI system.
void n_gui_close_window(N_GUI_CTX *ctx, int window_id)
Close (hide) a window.
int n_gui_tooltip_pending(N_GUI_CTX *ctx)
Report the tooltip phase.
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.
int n_gui_add_splitpane(N_GUI_CTX *ctx, int window_id, float x, float y, float w, float h, int orientation, float ratio, void(*on_change)(int, float, void *), void *user_data)
Add a split pane widget: a draggable divider between two regions.
#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_draw(N_GUI_CTX *ctx)
draw all visible GUI windows and widgets
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.
N_GUI_CTX * n_gui_new_ctx(ALLEGRO_FONT *default_font)
Create a new GUI context.
#define N_GUI_SPLIT_VERTICAL
split pane: vertical divider, regions are left and right
void n_gui_destroy_ctx(N_GUI_CTX **ctx)
Destroy a GUI context and all its windows/widgets.
#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.
#define N_GUI_SHAPE_RECT
rectangle shape (default)
int n_gui_add_button(N_GUI_CTX *ctx, int window_id, const char *label, float x, float y, float w, float h, int shape, void(*on_click)(int, void *), void *user_data)
Add a button widget to a window.
The top-level GUI context that holds all windows.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
#define LOG_NOTICE
normal but significant condition
#define LOG_NULL
no log output
#define LOG_INFO
informational
Common headers and low-level functions & define.
GUI system: buttons, sliders, text areas, checkboxes, scrollbars, dropdown menus, windows.