1 #include "nuklear.h"
2 #include "nuklear_internal.h"
3
4 /* ===============================================================
5 *
6 * TOGGLE
7 *
8 * ===============================================================*/
9 NK_LIB int
nk_toggle_behavior(const struct nk_input * in,struct nk_rect select,nk_flags * state,int active)10 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
11 nk_flags *state, int active)
12 {
13 nk_widget_state_reset(state);
14 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
15 *state = NK_WIDGET_STATE_ACTIVE;
16 active = !active;
17 }
18 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
19 *state |= NK_WIDGET_STATE_ENTERED;
20 else if (nk_input_is_mouse_prev_hovering_rect(in, select))
21 *state |= NK_WIDGET_STATE_LEFT;
22 return active;
23 }
24 NK_LIB void
nk_draw_checkbox(struct nk_command_buffer * out,nk_flags state,const struct nk_style_toggle * style,int active,const struct nk_rect * label,const struct nk_rect * selector,const struct nk_rect * cursors,const char * string,int len,const struct nk_user_font * font)25 nk_draw_checkbox(struct nk_command_buffer *out,
26 nk_flags state, const struct nk_style_toggle *style, int 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)
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 /* draw background and cursor */
51 if (background->type == NK_STYLE_ITEM_COLOR) {
52 nk_fill_rect(out, *selector, 0, style->border_color);
53 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
54 } else nk_draw_image(out, *selector, &background->data.image, nk_white);
55 if (active) {
56 if (cursor->type == NK_STYLE_ITEM_IMAGE)
57 nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
58 else nk_fill_rect(out, *cursors, 0, cursor->data.color);
59 }
60
61 text.padding.x = 0;
62 text.padding.y = 0;
63 text.background = style->text_background;
64 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
65 }
66 NK_LIB void
nk_draw_option(struct nk_command_buffer * out,nk_flags state,const struct nk_style_toggle * style,int active,const struct nk_rect * label,const struct nk_rect * selector,const struct nk_rect * cursors,const char * string,int len,const struct nk_user_font * font)67 nk_draw_option(struct nk_command_buffer *out,
68 nk_flags state, const struct nk_style_toggle *style, int active,
69 const struct nk_rect *label, const struct nk_rect *selector,
70 const struct nk_rect *cursors, const char *string, int len,
71 const struct nk_user_font *font)
72 {
73 const struct nk_style_item *background;
74 const struct nk_style_item *cursor;
75 struct nk_text text;
76
77 /* select correct colors/images */
78 if (state & NK_WIDGET_STATE_HOVER) {
79 background = &style->hover;
80 cursor = &style->cursor_hover;
81 text.text = style->text_hover;
82 } else if (state & NK_WIDGET_STATE_ACTIVED) {
83 background = &style->hover;
84 cursor = &style->cursor_hover;
85 text.text = style->text_active;
86 } else {
87 background = &style->normal;
88 cursor = &style->cursor_normal;
89 text.text = style->text_normal;
90 }
91
92 /* draw background and cursor */
93 if (background->type == NK_STYLE_ITEM_COLOR) {
94 nk_fill_circle(out, *selector, style->border_color);
95 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
96 } else nk_draw_image(out, *selector, &background->data.image, nk_white);
97 if (active) {
98 if (cursor->type == NK_STYLE_ITEM_IMAGE)
99 nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
100 else nk_fill_circle(out, *cursors, cursor->data.color);
101 }
102
103 text.padding.x = 0;
104 text.padding.y = 0;
105 text.background = style->text_background;
106 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
107 }
108 NK_LIB int
nk_do_toggle(nk_flags * state,struct nk_command_buffer * out,struct nk_rect r,int * active,const char * str,int len,enum nk_toggle_type type,const struct nk_style_toggle * style,const struct nk_input * in,const struct nk_user_font * font)109 nk_do_toggle(nk_flags *state,
110 struct nk_command_buffer *out, struct nk_rect r,
111 int *active, const char *str, int len, enum nk_toggle_type type,
112 const struct nk_style_toggle *style, const struct nk_input *in,
113 const struct nk_user_font *font)
114 {
115 int was_active;
116 struct nk_rect bounds;
117 struct nk_rect select;
118 struct nk_rect cursor;
119 struct nk_rect label;
120
121 NK_ASSERT(style);
122 NK_ASSERT(out);
123 NK_ASSERT(font);
124 if (!out || !style || !font || !active)
125 return 0;
126
127 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
128 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
129
130 /* add additional touch padding for touch screen devices */
131 bounds.x = r.x - style->touch_padding.x;
132 bounds.y = r.y - style->touch_padding.y;
133 bounds.w = r.w + 2 * style->touch_padding.x;
134 bounds.h = r.h + 2 * style->touch_padding.y;
135
136 /* calculate the selector space */
137 select.w = font->height;
138 select.h = select.w;
139 select.y = r.y + r.h/2.0f - select.h/2.0f;
140 select.x = r.x;
141
142 /* calculate the bounds of the cursor inside the selector */
143 cursor.x = select.x + style->padding.x + style->border;
144 cursor.y = select.y + style->padding.y + style->border;
145 cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
146 cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
147
148 /* label behind the selector */
149 label.x = select.x + select.w + style->spacing;
150 label.y = select.y;
151 label.w = NK_MAX(r.x + r.w, label.x) - label.x;
152 label.h = select.w;
153
154 /* update selector */
155 was_active = *active;
156 *active = nk_toggle_behavior(in, bounds, state, *active);
157
158 /* draw selector */
159 if (style->draw_begin)
160 style->draw_begin(out, style->userdata);
161 if (type == NK_TOGGLE_CHECK) {
162 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
163 } else {
164 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
165 }
166 if (style->draw_end)
167 style->draw_end(out, style->userdata);
168 return (was_active != *active);
169 }
170 /*----------------------------------------------------------------
171 *
172 * CHECKBOX
173 *
174 * --------------------------------------------------------------*/
175 NK_API int
nk_check_text(struct nk_context * ctx,const char * text,int len,int active)176 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
177 {
178 struct nk_window *win;
179 struct nk_panel *layout;
180 const struct nk_input *in;
181 const struct nk_style *style;
182
183 struct nk_rect bounds;
184 enum nk_widget_layout_states state;
185
186 NK_ASSERT(ctx);
187 NK_ASSERT(ctx->current);
188 NK_ASSERT(ctx->current->layout);
189 if (!ctx || !ctx->current || !ctx->current->layout)
190 return active;
191
192 win = ctx->current;
193 style = &ctx->style;
194 layout = win->layout;
195
196 state = nk_widget(&bounds, ctx);
197 if (!state) return active;
198 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
199 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
200 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
201 return active;
202 }
203 NK_API unsigned int
nk_check_flags_text(struct nk_context * ctx,const char * text,int len,unsigned int flags,unsigned int value)204 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
205 unsigned int flags, unsigned int value)
206 {
207 int old_active;
208 NK_ASSERT(ctx);
209 NK_ASSERT(text);
210 if (!ctx || !text) return flags;
211 old_active = (int)((flags & value) & value);
212 if (nk_check_text(ctx, text, len, old_active))
213 flags |= value;
214 else flags &= ~value;
215 return flags;
216 }
217 NK_API int
nk_checkbox_text(struct nk_context * ctx,const char * text,int len,int * active)218 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
219 {
220 int old_val;
221 NK_ASSERT(ctx);
222 NK_ASSERT(text);
223 NK_ASSERT(active);
224 if (!ctx || !text || !active) return 0;
225 old_val = *active;
226 *active = nk_check_text(ctx, text, len, *active);
227 return old_val != *active;
228 }
229 NK_API int
nk_checkbox_flags_text(struct nk_context * ctx,const char * text,int len,unsigned int * flags,unsigned int value)230 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
231 unsigned int *flags, unsigned int value)
232 {
233 int active;
234 NK_ASSERT(ctx);
235 NK_ASSERT(text);
236 NK_ASSERT(flags);
237 if (!ctx || !text || !flags) return 0;
238
239 active = (int)((*flags & value) & value);
240 if (nk_checkbox_text(ctx, text, len, &active)) {
241 if (active) *flags |= value;
242 else *flags &= ~value;
243 return 1;
244 }
245 return 0;
246 }
nk_check_label(struct nk_context * ctx,const char * label,int active)247 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
248 {
249 return nk_check_text(ctx, label, nk_strlen(label), active);
250 }
nk_check_flags_label(struct nk_context * ctx,const char * label,unsigned int flags,unsigned int value)251 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
252 unsigned int flags, unsigned int value)
253 {
254 return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);
255 }
nk_checkbox_label(struct nk_context * ctx,const char * label,int * active)256 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
257 {
258 return nk_checkbox_text(ctx, label, nk_strlen(label), active);
259 }
nk_checkbox_flags_label(struct nk_context * ctx,const char * label,unsigned int * flags,unsigned int value)260 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
261 unsigned int *flags, unsigned int value)
262 {
263 return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);
264 }
265 /*----------------------------------------------------------------
266 *
267 * OPTION
268 *
269 * --------------------------------------------------------------*/
270 NK_API int
nk_option_text(struct nk_context * ctx,const char * text,int len,int is_active)271 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
272 {
273 struct nk_window *win;
274 struct nk_panel *layout;
275 const struct nk_input *in;
276 const struct nk_style *style;
277
278 struct nk_rect bounds;
279 enum nk_widget_layout_states state;
280
281 NK_ASSERT(ctx);
282 NK_ASSERT(ctx->current);
283 NK_ASSERT(ctx->current->layout);
284 if (!ctx || !ctx->current || !ctx->current->layout)
285 return is_active;
286
287 win = ctx->current;
288 style = &ctx->style;
289 layout = win->layout;
290
291 state = nk_widget(&bounds, ctx);
292 if (!state) return (int)state;
293 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
294 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
295 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
296 return is_active;
297 }
298 NK_API int
nk_radio_text(struct nk_context * ctx,const char * text,int len,int * active)299 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
300 {
301 int old_value;
302 NK_ASSERT(ctx);
303 NK_ASSERT(text);
304 NK_ASSERT(active);
305 if (!ctx || !text || !active) return 0;
306 old_value = *active;
307 *active = nk_option_text(ctx, text, len, old_value);
308 return old_value != *active;
309 }
310 NK_API int
nk_option_label(struct nk_context * ctx,const char * label,int active)311 nk_option_label(struct nk_context *ctx, const char *label, int active)
312 {
313 return nk_option_text(ctx, label, nk_strlen(label), active);
314 }
315 NK_API int
nk_radio_label(struct nk_context * ctx,const char * label,int * active)316 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
317 {
318 return nk_radio_text(ctx, label, nk_strlen(label), active);
319 }
320
321