Nuklear
This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.
 
Loading...
Searching...
No Matches
nuklear_toggle.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ===============================================================
5 *
6 * TOGGLE
7 *
8 * ===============================================================*/
9NK_LIB nk_bool
10nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
11 nk_flags *state, nk_bool active)
12{
13 nk_widget_state_reset(state);
14 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
16 active = !active;
17 }
18 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
20 else if (nk_input_is_mouse_prev_hovering_rect(in, select))
21 *state |= NK_WIDGET_STATE_LEFT;
22 return active;
23}
24NK_LIB void
25nk_draw_checkbox(struct nk_command_buffer *out,
26 nk_flags state, const struct nk_style_toggle *style, nk_bool active,
27 const struct nk_rect *label, const struct nk_rect *selector,
28 const struct nk_rect *cursors, const char *string, int len,
29 const struct nk_user_font *font, nk_flags text_alignment)
30{
31 const struct nk_style_item *background;
32 const struct nk_style_item *cursor;
33 struct nk_text text;
34
35 /* select correct colors/images */
36 if (state & NK_WIDGET_STATE_HOVER) {
37 background = &style->hover;
38 cursor = &style->cursor_hover;
39 text.text = style->text_hover;
40 } else if (state & NK_WIDGET_STATE_ACTIVED) {
41 background = &style->hover;
42 cursor = &style->cursor_hover;
43 text.text = style->text_active;
44 } else {
45 background = &style->normal;
46 cursor = &style->cursor_normal;
47 text.text = style->text_normal;
48 }
49
50 text.text = nk_rgb_factor(text.text, style->color_factor);
51 text.padding.x = 0;
52 text.padding.y = 0;
53 text.background = style->text_background;
54 nk_widget_text(out, *label, string, len, &text, text_alignment, font);
55
56 /* draw background and cursor */
57 if (background->type == NK_STYLE_ITEM_COLOR) {
58 nk_fill_rect(out, *selector, 0, nk_rgb_factor(style->border_color, style->color_factor));
59 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, nk_rgb_factor(background->data.color, style->color_factor));
60 } else nk_draw_image(out, *selector, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
61 if (active) {
62 if (cursor->type == NK_STYLE_ITEM_IMAGE)
63 nk_draw_image(out, *cursors, &cursor->data.image, nk_rgb_factor(nk_white, style->color_factor));
64 else nk_fill_rect(out, *cursors, 0, cursor->data.color);
65 }
66}
67NK_LIB void
68nk_draw_option(struct nk_command_buffer *out,
69 nk_flags state, const struct nk_style_toggle *style, nk_bool active,
70 const struct nk_rect *label, const struct nk_rect *selector,
71 const struct nk_rect *cursors, const char *string, int len,
72 const struct nk_user_font *font, nk_flags text_alignment)
73{
74 const struct nk_style_item *background;
75 const struct nk_style_item *cursor;
76 struct nk_text text;
77
78 /* select correct colors/images */
79 if (state & NK_WIDGET_STATE_HOVER) {
80 background = &style->hover;
81 cursor = &style->cursor_hover;
82 text.text = style->text_hover;
83 } else if (state & NK_WIDGET_STATE_ACTIVED) {
84 background = &style->hover;
85 cursor = &style->cursor_hover;
86 text.text = style->text_active;
87 } else {
88 background = &style->normal;
89 cursor = &style->cursor_normal;
90 text.text = style->text_normal;
91 }
92
93 text.text = nk_rgb_factor(text.text, style->color_factor);
94 text.padding.x = 0;
95 text.padding.y = 0;
96 text.background = style->text_background;
97 nk_widget_text(out, *label, string, len, &text, text_alignment, font);
98
99 /* draw background and cursor */
100 if (background->type == NK_STYLE_ITEM_COLOR) {
101 nk_fill_circle(out, *selector, nk_rgb_factor(style->border_color, style->color_factor));
102 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), nk_rgb_factor(background->data.color, style->color_factor));
103 } else nk_draw_image(out, *selector, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
104 if (active) {
105 if (cursor->type == NK_STYLE_ITEM_IMAGE)
106 nk_draw_image(out, *cursors, &cursor->data.image, nk_rgb_factor(nk_white, style->color_factor));
107 else nk_fill_circle(out, *cursors, cursor->data.color);
108 }
109}
110NK_LIB nk_bool
111nk_do_toggle(nk_flags *state,
112 struct nk_command_buffer *out, struct nk_rect r,
113 nk_bool *active, const char *str, int len, enum nk_toggle_type type,
114 const struct nk_style_toggle *style, const struct nk_input *in,
115 const struct nk_user_font *font, nk_flags widget_alignment, nk_flags text_alignment)
116{
117 int was_active;
118 struct nk_rect bounds;
119 struct nk_rect select;
120 struct nk_rect cursor;
121 struct nk_rect label;
122
123 NK_ASSERT(style);
124 NK_ASSERT(out);
125 NK_ASSERT(font);
126 if (!out || !style || !font || !active)
127 return 0;
128
129 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
130 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
131
132 /* add additional touch padding for touch screen devices */
133 bounds.x = r.x - style->touch_padding.x;
134 bounds.y = r.y - style->touch_padding.y;
135 bounds.w = r.w + 2 * style->touch_padding.x;
136 bounds.h = r.h + 2 * style->touch_padding.y;
137
138 /* calculate the selector space */
139 select.w = font->height;
140 select.h = select.w;
141
142 if (widget_alignment & NK_WIDGET_ALIGN_RIGHT) {
143 select.x = r.x + r.w - font->height;
144
145 /* label in front of the selector */
146 label.x = r.x;
147 label.w = r.w - select.w - style->spacing * 2;
148 } else if (widget_alignment & NK_WIDGET_ALIGN_CENTERED) {
149 select.x = r.x + (r.w - select.w) / 2;
150
151 /* label in front of selector */
152 label.x = r.x;
153 label.w = (r.w - select.w - style->spacing * 2) / 2;
154 } else { /* Default: NK_WIDGET_ALIGN_LEFT */
155 select.x = r.x;
156
157 /* label behind the selector */
158 label.x = select.x + select.w + style->spacing;
159 label.w = NK_MAX(r.x + r.w, label.x) - label.x;
160 }
161
162 if (widget_alignment & NK_WIDGET_ALIGN_TOP) {
163 select.y = r.y;
164 } else if (widget_alignment & NK_WIDGET_ALIGN_BOTTOM) {
165 select.y = r.y + r.h - select.h - 2 * style->padding.y;
166 } else { /* Default: NK_WIDGET_ALIGN_MIDDLE */
167 select.y = r.y + r.h/2.0f - select.h/2.0f;
168 }
169
170 label.y = select.y;
171 label.h = select.w;
172
173 /* calculate the bounds of the cursor inside the selector */
174 cursor.x = select.x + style->padding.x + style->border;
175 cursor.y = select.y + style->padding.y + style->border;
176 cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
177 cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
178
179 /* update selector */
180 was_active = *active;
181 *active = nk_toggle_behavior(in, bounds, state, *active);
182
183 /* draw selector */
184 if (style->draw_begin)
185 style->draw_begin(out, style->userdata);
186 if (type == NK_TOGGLE_CHECK) {
187 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font, text_alignment);
188 } else {
189 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font, text_alignment);
190 }
191 if (style->draw_end)
192 style->draw_end(out, style->userdata);
193 return (was_active != *active);
194}
195/*----------------------------------------------------------------
196 *
197 * CHECKBOX
198 *
199 * --------------------------------------------------------------*/
200NK_API nk_bool
201nk_check_text(struct nk_context *ctx, const char *text, int len, nk_bool active)
202{
203 struct nk_window *win;
204 struct nk_panel *layout;
205 const struct nk_input *in;
206 const struct nk_style *style;
207
208 struct nk_rect bounds;
209 enum nk_widget_layout_states state;
210
211 NK_ASSERT(ctx);
212 NK_ASSERT(ctx->current);
213 NK_ASSERT(ctx->current->layout);
214 if (!ctx || !ctx->current || !ctx->current->layout)
215 return active;
216
217 win = ctx->current;
218 style = &ctx->style;
219 layout = win->layout;
220
221 state = nk_widget(&bounds, ctx);
222 if (!state) return active;
223 in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
224 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
225 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font, NK_WIDGET_LEFT, NK_TEXT_LEFT);
226 return active;
227}
228NK_API nk_bool
229nk_check_text_align(struct nk_context *ctx, const char *text, int len, nk_bool active, nk_flags widget_alignment, nk_flags text_alignment)
230{
231 struct nk_window *win;
232 struct nk_panel *layout;
233 const struct nk_input *in;
234 const struct nk_style *style;
235
236 struct nk_rect bounds;
237 enum nk_widget_layout_states state;
238
239 NK_ASSERT(ctx);
240 NK_ASSERT(ctx->current);
241 NK_ASSERT(ctx->current->layout);
242 if (!ctx || !ctx->current || !ctx->current->layout)
243 return active;
244
245 win = ctx->current;
246 style = &ctx->style;
247 layout = win->layout;
248
249 state = nk_widget(&bounds, ctx);
250 if (!state) return active;
251 in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
252 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
253 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font, widget_alignment, text_alignment);
254 return active;
255}
256NK_API unsigned int
257nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
258 unsigned int flags, unsigned int value)
259{
260 int old_active;
261 NK_ASSERT(ctx);
262 NK_ASSERT(text);
263 if (!ctx || !text) return flags;
264 old_active = (int)((flags & value) & value);
265 if (nk_check_text(ctx, text, len, old_active))
266 flags |= value;
267 else flags &= ~value;
268 return flags;
269}
270NK_API nk_bool
271nk_checkbox_text(struct nk_context *ctx, const char *text, int len, nk_bool *active)
272{
273 int old_val;
274 NK_ASSERT(ctx);
275 NK_ASSERT(text);
276 NK_ASSERT(active);
277 if (!ctx || !text || !active) return 0;
278 old_val = *active;
279 *active = nk_check_text(ctx, text, len, *active);
280 return old_val != *active;
281}
282NK_API nk_bool
283nk_checkbox_text_align(struct nk_context *ctx, const char *text, int len, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
284{
285 int old_val;
286 NK_ASSERT(ctx);
287 NK_ASSERT(text);
288 NK_ASSERT(active);
289 if (!ctx || !text || !active) return 0;
290 old_val = *active;
291 *active = nk_check_text_align(ctx, text, len, *active, widget_alignment, text_alignment);
292 return old_val != *active;
293}
294NK_API nk_bool
295nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
296 unsigned int *flags, unsigned int value)
297{
298 nk_bool active;
299 NK_ASSERT(ctx);
300 NK_ASSERT(text);
301 NK_ASSERT(flags);
302 if (!ctx || !text || !flags) return 0;
303
304 active = (int)((*flags & value) & value);
305 if (nk_checkbox_text(ctx, text, len, &active)) {
306 if (active) *flags |= value;
307 else *flags &= ~value;
308 return 1;
309 }
310 return 0;
311}
312NK_API nk_bool nk_check_label(struct nk_context *ctx, const char *label, nk_bool active)
313{
314 return nk_check_text(ctx, label, nk_strlen(label), active);
315}
316NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
317 unsigned int flags, unsigned int value)
318{
319 return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
320}
321NK_API nk_bool nk_checkbox_label(struct nk_context *ctx, const char *label, nk_bool *active)
322{
323 return nk_checkbox_text(ctx, label, nk_strlen(label), active);
324}
325NK_API nk_bool nk_checkbox_label_align(struct nk_context *ctx, const char *label, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
326{
327 return nk_checkbox_text_align(ctx, label, nk_strlen(label), active, widget_alignment, text_alignment);
328}
329NK_API nk_bool nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
330 unsigned int *flags, unsigned int value)
331{
332 return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
333}
334/*----------------------------------------------------------------
335 *
336 * OPTION
337 *
338 * --------------------------------------------------------------*/
339NK_API nk_bool
340nk_option_text(struct nk_context *ctx, const char *text, int len, nk_bool is_active)
341{
342 struct nk_window *win;
343 struct nk_panel *layout;
344 const struct nk_input *in;
345 const struct nk_style *style;
346
347 struct nk_rect bounds;
348 enum nk_widget_layout_states state;
349
350 NK_ASSERT(ctx);
351 NK_ASSERT(ctx->current);
352 NK_ASSERT(ctx->current->layout);
353 if (!ctx || !ctx->current || !ctx->current->layout)
354 return is_active;
355
356 win = ctx->current;
357 style = &ctx->style;
358 layout = win->layout;
359
360 state = nk_widget(&bounds, ctx);
361 if (!state) return (int)state;
362 in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
363 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
364 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font, NK_WIDGET_LEFT, NK_TEXT_LEFT);
365 return is_active;
366}
367NK_API nk_bool
368nk_option_text_align(struct nk_context *ctx, const char *text, int len, nk_bool is_active, nk_flags widget_alignment, nk_flags text_alignment)
369{
370 struct nk_window *win;
371 struct nk_panel *layout;
372 const struct nk_input *in;
373 const struct nk_style *style;
374
375 struct nk_rect bounds;
376 enum nk_widget_layout_states state;
377
378 NK_ASSERT(ctx);
379 NK_ASSERT(ctx->current);
380 NK_ASSERT(ctx->current->layout);
381 if (!ctx || !ctx->current || !ctx->current->layout)
382 return is_active;
383
384 win = ctx->current;
385 style = &ctx->style;
386 layout = win->layout;
387
388 state = nk_widget(&bounds, ctx);
389 if (!state) return (int)state;
390 in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
391 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
392 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font, widget_alignment, text_alignment);
393 return is_active;
394}
395NK_API nk_bool
396nk_radio_text(struct nk_context *ctx, const char *text, int len, nk_bool *active)
397{
398 int old_value;
399 NK_ASSERT(ctx);
400 NK_ASSERT(text);
401 NK_ASSERT(active);
402 if (!ctx || !text || !active) return 0;
403 old_value = *active;
404 *active = nk_option_text(ctx, text, len, old_value);
405 return old_value != *active;
406}
407NK_API nk_bool
408nk_radio_text_align(struct nk_context *ctx, const char *text, int len, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
409{
410 int old_value;
411 NK_ASSERT(ctx);
412 NK_ASSERT(text);
413 NK_ASSERT(active);
414 if (!ctx || !text || !active) return 0;
415 old_value = *active;
416 *active = nk_option_text_align(ctx, text, len, old_value, widget_alignment, text_alignment);
417 return old_value != *active;
418}
419NK_API nk_bool
420nk_option_label(struct nk_context *ctx, const char *label, nk_bool active)
421{
422 return nk_option_text(ctx, label, nk_strlen(label), active);
423}
424NK_API nk_bool
425nk_option_label_align(struct nk_context *ctx, const char *label, nk_bool active, nk_flags widget_alignment, nk_flags text_alignment)
426{
427 return nk_option_text_align(ctx, label, nk_strlen(label), active, widget_alignment, text_alignment);
428}
429NK_API nk_bool
430nk_radio_label(struct nk_context *ctx, const char *label, nk_bool *active)
431{
432 return nk_radio_text(ctx, label, nk_strlen(label), active);
433}
434NK_API nk_bool
435nk_radio_label_align(struct nk_context *ctx, const char *label, nk_bool *active, nk_flags widget_alignment, nk_flags text_alignment)
436{
437 return nk_radio_text_align(ctx, label, nk_strlen(label), active, widget_alignment, text_alignment);
438}
439
main API and documentation file
@ NK_WINDOW_ROM
sets window widgets into a read only mode and does not allow input changes
Definition nuklear.h:5492
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
misc
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
filled shades
@ NK_WIDGET_STATE_LEFT
!< widget is currently activated
Definition nuklear.h:3093
@ NK_WIDGET_STATE_ACTIVED
!< widget is being hovered
Definition nuklear.h:3092
@ NK_WIDGET_STATE_ENTERED
!< widget is neither active nor hovered
Definition nuklear.h:3090
@ NK_WIDGET_STATE_HOVER
!< widget has been hovered on the current frame
Definition nuklear.h:3091
@ NK_WIDGET_STATE_ACTIVE
!< widget is being hovered
Definition nuklear.h:3095
nk_widget_layout_states
Definition nuklear.h:3081
@ NK_WIDGET_DISABLED
The widget is manually disabled and acts like NK_WIDGET_ROM.
Definition nuklear.h:3085
@ NK_WIDGET_ROM
The widget is partially visible and cannot be updated.
Definition nuklear.h:3084
float height
!< user provided font handle
Definition nuklear.h:4008