Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_gui_color_picker.c
Go to the documentation of this file.
1
14
15#define ALLEGRO_UNSTABLE 1
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21
22#include <allegro5/allegro_primitives.h>
23
24#include "nilorea/n_common.h"
25#include "nilorea/n_log.h"
26#include "nilorea/n_gui.h"
27#include "nilorea/n_gui_color.h"
28
29static int log_level = LOG_ERR;
30static int failures = 0;
31
33static int changes = 0;
34static float changed[4] = {0.0f, 0.0f, 0.0f, 0.0f};
35
37static void expect_true(const char* what, int ok) {
38 if (!ok) {
39 n_log(LOG_ERR, "FAIL: %s", what);
40 failures++;
41 } else {
42 n_log(LOG_INFO, "ok: %s", what);
43 }
44}
45
47static int process_args(int argc, char** argv) {
48 int opt = 0;
49
50 while ((opt = getopt(argc, argv, "V:")) != -1) {
51 if (opt == 'V') {
52 log_level = atoi(optarg);
53 } else {
54 return -1;
55 }
56 }
57 return 0;
58}
59
61static void on_change(const float rgba[4], void* user_data) {
62 int c = 0;
63
64 changes++;
65 for (c = 0; c < 4; c++) changed[c] = rgba[c];
66 if (user_data) (*(int*)user_data)++;
67}
68
70static void click_middle(N_GUI_CTX* gui, int window_id, int widget_id) {
71 N_GUI_WINDOW* win = n_gui_get_window(gui, window_id);
72 N_GUI_WIDGET* wgt = n_gui_get_widget(gui, widget_id);
73 ALLEGRO_EVENT ev;
74
75 if (!win || !wgt) return;
76 memset(&ev, 0, sizeof(ev));
77 ev.mouse.x = (int)(win->x + wgt->x + wgt->w / 2.0f);
78 ev.mouse.y = (int)(win->y + win->titlebar_h + wgt->y + wgt->h / 2.0f);
79 ev.mouse.button = 1;
80 ev.type = ALLEGRO_EVENT_MOUSE_AXES;
82 ev.type = ALLEGRO_EVENT_MOUSE_BUTTON_DOWN;
84 ev.type = ALLEGRO_EVENT_MOUSE_BUTTON_UP;
86}
87
89static ALLEGRO_COLOR swatch_centre(const float rgba[4]) {
90 ALLEGRO_BITMAP* target = NULL;
91 ALLEGRO_COLOR px;
92 int old = al_get_new_bitmap_flags();
93
94 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
95 target = al_create_bitmap(40, 40);
96 al_set_new_bitmap_flags(old);
97 al_set_target_bitmap(target);
98 al_clear_to_color(al_map_rgb(0, 0, 0));
99 n_gui_draw_color_swatch(0.0f, 0.0f, 40.0f, 40.0f, rgba);
100 /* 20,20 is the corner of four checker squares; 21,21 is inside one */
101 px = al_get_pixel(target, 21, 21);
102 al_set_target_bitmap(NULL);
103 al_destroy_bitmap(target);
104 return px;
105}
106
107int main(int argc, char** argv) {
108 const float start[4] = {1.0f, 0.0f, 0.0f, 128.0f / 255.0f};
109 float now[4] = {0.0f, 0.0f, 0.0f, 0.0f};
110 char hex[16] = "";
111 int counted = 0;
112 unsigned char r = 0, g = 0, b = 0;
113
115 if (process_args(argc, argv) != 0) {
116 fprintf(stderr, "Usage: %s [-V LOG_LEVEL]\n", argv[0]);
117 return 2;
118 }
120 if (!al_init() || !al_init_font_addon() || !al_init_primitives_addon()) {
121 n_log(LOG_ERR, "allegro init failed");
122 return 1;
123 }
124 ALLEGRO_FONT* font = al_create_builtin_font();
125 if (!font) return 1;
127 if (!gui) {
128 al_destroy_font(font);
129 return 1;
130 }
131 n_gui_set_display_size(gui, 640.0f, 480.0f);
132
133 N_GUI_COLOR_PICKER* picker = n_gui_color_picker_new(gui, NULL, 1.0f);
134 expect_true("a picker is built", picker != NULL);
135 if (picker) {
136 int win = n_gui_color_picker_window(picker);
138
139 expect_true("it starts closed", n_gui_color_picker_is_open(picker) == 0);
140 expect_true("a channel out of range has no slider", n_gui_color_picker_slider(picker, 4) == -1);
141
142 n_gui_color_picker_open(picker, "Test: Colour", start, on_change, &counted);
143 expect_true("open opens it", n_gui_color_picker_is_open(picker) == 1);
144 expect_true("the sliders show the colour",
148 expect_true("opening does not call back", changes == 0);
149 expect_true("it is centred on the display",
150 w && (int)(w->x + w->w / 2.0f + 0.5f) == 320);
151
153 expect_true("moving green calls back once", changes == 1 && counted == 1);
154 expect_true("with the new green, in steps of 1/255",
155 changed[1] > 0.3f && changed[1] < 0.7f &&
156 (float)(int)(changed[1] * 255.0f + 0.5f) == changed[1] * 255.0f);
157 expect_true("and the rest as they were",
158 changed[0] == 1.0f && changed[2] == 0.0f && changed[3] == start[3]);
159 expect_true("get returns what was handed on",
160 n_gui_color_picker_get(picker, now) == TRUE && memcmp(now, changed, sizeof(now)) == 0);
161
163 expect_true("close closes it", n_gui_color_picker_is_open(picker) == 0);
165 expect_true("a closed picker does not call back", changes == 1);
166
168 expect_true("free sets the handle to NULL", picker == NULL);
169 }
172
173 {
174 const float blue[4] = {0.0f, 0.0f, 1.0f, 1.0f};
175 const float clear[4] = {1.0f, 0.0f, 0.0f, 0.0f};
176
177 al_unmap_rgb(swatch_centre(blue), &r, &g, &b);
178 expect_true("an opaque swatch is its colour", r == 0 && g == 0 && b == 255);
179 al_unmap_rgb(swatch_centre(clear), &r, &g, &b);
180 expect_true("a see-through swatch shows the checkerboard grey", r == g && g == b && r > 100);
181 }
182
183 n_gui_color_to_hex(start, hex, sizeof(hex));
184 expect_true("hex writes #RRGGBBAA", strcmp(hex, "#FF000080") == 0);
185 {
186 const float wild[4] = {-1.0f, 2.0f, 0.5f, 1.0f};
187
188 n_gui_color_to_hex(wild, hex, sizeof(hex));
189 expect_true("hex clamps and rounds", strcmp(hex, "#00FF80FF") == 0);
190 }
191 n_gui_color_to_hex(NULL, hex, sizeof(hex));
192 expect_true("hex of NULL is empty", hex[0] == '\0');
193
195 al_destroy_font(font);
196 if (failures) {
197 fprintf(stderr, "ex_gui_color_picker: %d failure(s)\n", failures);
198 return 1;
199 }
200 printf("ex_gui_color_picker: ok\n");
201 return 0;
202}
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 ALLEGRO_COLOR swatch_centre(const float rgba[4])
draw a swatch into a memory bitmap and read the pixel at its centre
static int changes
how many times the picker called back, and with what
static void click_middle(N_GUI_CTX *gui, int window_id, int widget_id)
click the middle of a widget, in display coordinates
static void on_change(const float rgba[4], void *user_data)
the picker's callback
static float changed[4]
static N_GUI_CTX * gui
FONT * font
the default 8x8 font, valid after allegro_init()
void clear(BITMAP *bmp)
clear to black
float h
height
Definition n_gui.h:1104
float x
position x on screen
Definition n_gui.h:1312
float titlebar_h
title bar height
Definition n_gui.h:1320
float w
width
Definition n_gui.h:1102
float w
window width
Definition n_gui.h:1316
float x
position x relative to parent window
Definition n_gui.h:1098
float y
position y relative to parent window
Definition n_gui.h:1100
float y
position y on screen
Definition n_gui.h:1314
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
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
double n_gui_slider_get_value(N_GUI_CTX *ctx, int widget_id)
get the current value of a slider widget
Definition n_gui.c:3962
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
N_GUI_WINDOW * n_gui_get_window(N_GUI_CTX *ctx, int window_id)
Get a window pointer by id.
Definition n_gui.c:1397
N_GUI_CTX * n_gui_new_ctx(ALLEGRO_FONT *default_font)
Create a new GUI context.
Definition n_gui.c:1103
void n_gui_destroy_ctx(N_GUI_CTX **ctx)
Destroy a GUI context and all its windows/widgets.
Definition n_gui.c:1209
The top-level GUI context that holds all windows.
Definition n_gui.h:1669
A single GUI widget.
Definition n_gui.h:1092
A pseudo window that contains widgets.
Definition n_gui.h:1298
#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 set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_INFO
informational
Definition n_log.h:106
int n_gui_color_picker_get(const N_GUI_COLOR_PICKER *picker, float rgba[4])
The colour the picker holds now.
void n_gui_color_picker_open(N_GUI_COLOR_PICKER *picker, const char *what, const float rgba[4], N_GUI_COLOR_FN on_change, void *user_data)
Open the picker on a colour, centred on the display.
void n_gui_color_to_hex(const float rgba[4], char *out, size_t len)
Write a colour as #RRGGBBAA, each channel clamped to 0..1 and rounded to the nearest of 255 steps.
int n_gui_color_picker_window(const N_GUI_COLOR_PICKER *picker)
The picker's window id, for a caller that walks its windows or sets their flags.
int n_gui_color_picker_slider(const N_GUI_COLOR_PICKER *picker, int channel)
The slider for one channel, for a caller or a test that drives it.
N_GUI_COLOR_PICKER * n_gui_color_picker_new(N_GUI_CTX *ctx, const char *title, float scale)
Build a colour picker window in ctx, closed.
void n_gui_color_picker_close(N_GUI_COLOR_PICKER *picker)
Close the picker.
void n_gui_draw_color_swatch(float x, float y, float w, float h, const float rgba[4])
Draw a colour as a swatch, over a checkerboard so its alpha shows, with a thin dark border.
void n_gui_color_picker_free(N_GUI_COLOR_PICKER **picker)
Close the picker's window and free the handle.
int n_gui_color_picker_is_open(const N_GUI_COLOR_PICKER *picker)
Whether the picker is open.
Common headers and low-level functions & define.
GUI system: buttons, sliders, text areas, checkboxes, scrollbars, dropdown menus, windows.
a colour picker: the ids of its widgets and the colour being edited
Definition n_gui_color.c:61
A colour picker dialog for N_GUI, and a swatch to show a colour.
Generic log system.