Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_gui_hover.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
35
36#define ALLEGRO_UNSTABLE 1
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#include "nilorea/n_common.h"
44#include "nilorea/n_log.h"
45#include "nilorea/n_gui.h"
46
47static int log_level = LOG_ERR;
48static int failures = 0;
49
50static void expect_true(const char* label, int cond) {
51 if (!cond) {
52 n_log(LOG_ERR, "%s: condition false", label);
53 failures++;
54 } else {
55 n_log(LOG_INFO, "%s: OK", label);
56 }
57}
58
59static void on_click(int widget_id, void* user_data) {
60 (void)widget_id;
61 (void)user_data;
62}
63
64static int process_args(int argc, char** argv) {
65 int opt;
66 while ((opt = getopt(argc, argv, "V:")) != -1) {
67 switch (opt) {
68 case 'V':
69 if (!strcmp("LOG_NULL", optarg))
71 else if (!strcmp("LOG_NOTICE", optarg))
73 else if (!strcmp("LOG_INFO", optarg))
75 else if (!strcmp("LOG_ERR", optarg))
77 else if (!strcmp("LOG_DEBUG", optarg))
79 else
80 return -1;
81 break;
82 default:
83 return -1;
84 }
85 }
86 return 0;
87}
88
89/* Build a mouse event at (x, y). */
90static ALLEGRO_EVENT mouse_event(int type, int x, int y) {
91 ALLEGRO_EVENT ev;
92 memset(&ev, 0, sizeof(ev));
93 ev.type = (unsigned int)type;
94 ev.mouse.x = x;
95 ev.mouse.y = y;
96 ev.mouse.button = 1;
97 return ev;
98}
99
100static void move_to(N_GUI_CTX* gui, int x, int y) {
101 ALLEGRO_EVENT ev = mouse_event(ALLEGRO_EVENT_MOUSE_AXES, x, y);
103}
104
105int main(int argc, char** argv) {
107 if (process_args(argc, argv) != 0) {
108 fprintf(stderr, "Usage: %s [-V LOG_LEVEL]\n", argv[0]);
109 return 2;
110 }
112
113 if (!al_init()) {
114 n_log(LOG_ERR, "al_init failed");
115 return 1;
116 }
117 if (!al_init_font_addon()) {
118 n_log(LOG_ERR, "al_init_font_addon failed");
119 return 1;
120 }
121 /* Builtin font does not need a display. */
122 ALLEGRO_FONT* font = al_create_builtin_font();
123 if (!font) {
124 n_log(LOG_ERR, "al_create_builtin_font failed");
125 return 1;
126 }
127
129 if (!gui) {
130 n_log(LOG_ERR, "n_gui_new_ctx failed");
131 al_destroy_font(font);
132 return 1;
133 }
134 n_gui_set_display_size(gui, 800.0f, 600.0f);
135
136 expect_true("no hover before any event", n_gui_hovered_widget(gui) == -1);
137
138 /* Window A (frameless: widget screen coords == window coords) with a
139 button at (10,10,80,30) and a label at (10,60,80,20). */
140 int win_a = n_gui_add_window(gui, "A", 0.0f, 0.0f, 200.0f, 150.0f);
142 int btn = n_gui_add_button(gui, win_a, "Go", 10.0f, 10.0f, 80.0f, 30.0f, N_GUI_SHAPE_ROUNDED, on_click, NULL);
143 int lbl = n_gui_add_label(gui, win_a, "text", 10.0f, 60.0f, 80.0f, 20.0f, N_GUI_ALIGN_LEFT);
144 n_gui_open_window(gui, win_a);
145
146 expect_true("window + widgets created", win_a >= 0 && btn >= 0 && lbl >= 0);
147
148 move_to(gui, 50, 25);
149 expect_true("button hovered under pointer", n_gui_hovered_widget(gui) == btn);
150 {
152 expect_true("hovered widget type is BUTTON", w && w->type == N_GUI_TYPE_BUTTON);
153 }
154
155 move_to(gui, 50, 70);
156 expect_true("label hovered under pointer", n_gui_hovered_widget(gui) == lbl);
157
158 move_to(gui, 150, 140);
159 expect_true("empty window space hovers nothing", n_gui_hovered_widget(gui) == -1);
160
161 /* ACTIVE during a press still reports the widget (the pointer is on it). */
162 move_to(gui, 50, 25);
163 {
164 ALLEGRO_EVENT down = mouse_event(ALLEGRO_EVENT_MOUSE_BUTTON_DOWN, 50, 25);
166 expect_true("pressed button still reported", n_gui_hovered_widget(gui) == btn);
167 ALLEGRO_EVENT up = mouse_event(ALLEGRO_EVENT_MOUSE_BUTTON_UP, 50, 25);
169 }
170
171 /* An invisible widget is skipped even if a stale flag were left set. */
173 move_to(gui, 50, 25);
174 expect_true("invisible widget not reported", n_gui_hovered_widget(gui) != btn);
176
177 /* Window B overlaps A and sits later in z-order (front-most): its widget
178 wins the hit test, and the query must report it, not A's. */
179 int win_b = n_gui_add_window(gui, "B", 0.0f, 0.0f, 200.0f, 150.0f);
181 int btn_b = n_gui_add_button(gui, win_b, "Top", 10.0f, 10.0f, 80.0f, 30.0f, N_GUI_SHAPE_ROUNDED, on_click, NULL);
182 n_gui_open_window(gui, win_b);
183 n_gui_raise_window(gui, win_b);
184 move_to(gui, 50, 25);
185 expect_true("front-most window's widget wins", n_gui_hovered_widget(gui) == btn_b);
186
187 /* Closing the front window hands hover back to the one behind. */
188 n_gui_close_window(gui, win_b);
189 move_to(gui, 50, 25);
190 expect_true("closed window skipped, back window hovers", n_gui_hovered_widget(gui) == btn);
191
193 al_destroy_font(font);
194
195 if (failures) {
196 fprintf(stderr, "ex_gui_hover: %d failure(s)\n", failures);
197 return 1;
198 }
199 printf("ex_gui_hover: all checks passed\n");
200 return 0;
201}
void process_args(int argc, char **argv)
static int failures
Definition ex_atlas.c:51
int main(void)
Definition ex_atlas.c:117
static void expect_true(const char *label, int cond)
Definition ex_atlas.c:53
static int log_level
static void on_click(int widget_id, void *user_data)
a button's click: counted
static void move_to(N_GUI_CTX *gui, float x, float y)
a move of the pointer to a point, nothing pressed
static ALLEGRO_EVENT mouse_event(int type, int x, int y, int dz)
Build a left-button mouse event at (x, y).
static N_GUI_CTX * gui
static void type(N_GUI_CTX *gui, const char *s)
Type a whole string into whatever has focus.
FONT * font
the default 8x8 font, valid after allegro_init()
int type
widget type (N_GUI_TYPE_*)
Definition n_gui.h:1096
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.
Definition n_gui.c:12348
#define N_GUI_ALIGN_LEFT
left aligned text
Definition n_gui.h:212
void n_gui_raise_window(N_GUI_CTX *ctx, int window_id)
Bring a window to the front (top of draw order).
Definition n_gui.c:2058
int n_gui_hovered_widget(const N_GUI_CTX *ctx)
Id of the widget currently under the mouse pointer, or -1.
Definition n_gui.c:3723
int n_gui_process_event(N_GUI_CTX *ctx, ALLEGRO_EVENT event)
Process an allegro event through the GUI system.
Definition n_gui.c:13611
int n_gui_add_label(N_GUI_CTX *ctx, int window_id, const char *text, float x, float y, float w, float h, int align)
Add a static text label.
Definition n_gui.c:3639
void n_gui_close_window(N_GUI_CTX *ctx, int window_id)
Close (hide) a window.
Definition n_gui.c:1406
#define N_GUI_WIN_FRAMELESS
frameless window: no title bar drawn, drag via window body unless N_GUI_WIN_FIXED_POSITION is also se...
Definition n_gui.h:276
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
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.
Definition n_gui.c:1277
N_GUI_CTX * n_gui_new_ctx(ALLEGRO_FONT *default_font)
Create a new GUI context.
Definition n_gui.c:1103
#define N_GUI_TYPE_BUTTON
widget type: button
Definition n_gui.h:106
void n_gui_destroy_ctx(N_GUI_CTX **ctx)
Destroy a GUI context and all its windows/widgets.
Definition n_gui.c:1209
void n_gui_open_window(N_GUI_CTX *ctx, int window_id)
Open (show) a window.
Definition n_gui.c:1436
#define N_GUI_SHAPE_ROUNDED
rounded rectangle shape
Definition n_gui.h:172
void n_gui_window_set_flags(N_GUI_CTX *ctx, int window_id, int flags)
Set feature flags on a window.
Definition n_gui.c:2515
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
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.
Definition n_gui.c:2720
The top-level GUI context that holds all windows.
Definition n_gui.h:1669
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_DEBUG
debug-level messages
Definition n_log.h:108
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:104
#define LOG_NULL
no log output
Definition n_log.h:70
#define LOG_INFO
informational
Definition n_log.h:106
Common headers and low-level functions & define.
GUI system: buttons, sliders, text areas, checkboxes, scrollbars, dropdown menus, windows.
Generic log system.