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_contextual.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ==============================================================
5 *
6 * CONTEXTUAL
7 *
8 * ===============================================================*/
9NK_API nk_bool
10nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
11 struct nk_rect trigger_bounds)
12{
13 struct nk_window *win;
14 struct nk_window *popup;
15 struct nk_rect body;
16 struct nk_input* in;
17
18 NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0};
19 int is_clicked = 0;
20 int is_open = 0;
21 int ret = 0;
22
23 NK_ASSERT(ctx);
24 NK_ASSERT(ctx->current);
25 NK_ASSERT(ctx->current->layout);
26 if (!ctx || !ctx->current || !ctx->current->layout)
27 return 0;
28
29 win = ctx->current;
30 ++win->popup.con_count;
31 if (ctx->current != ctx->active)
32 return 0;
33
34 /* check if currently active contextual is active */
35 popup = win->popup.win;
36 is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
37 in = win->widgets_disabled ? 0 : &ctx->input;
38 if (in) {
39 is_clicked = nk_input_mouse_clicked(in, NK_BUTTON_RIGHT, trigger_bounds);
40 if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
41 return 0;
42 if (!is_open && win->popup.active_con)
43 win->popup.active_con = 0;
44 if ((!is_open && !is_clicked))
45 return 0;
46
47 /* calculate contextual position on click */
48 win->popup.active_con = win->popup.con_count;
49 if (is_clicked) {
50 body.x = in->mouse.pos.x;
51 body.y = in->mouse.pos.y;
52 } else {
53 body.x = popup->bounds.x;
54 body.y = popup->bounds.y;
55 }
56
57 body.w = size.x;
58 body.h = size.y;
59
60 /* start nonblocking contextual popup */
61 ret = nk_nonblock_begin(ctx, flags | NK_WINDOW_NO_SCROLLBAR, body,
62 null_rect, NK_PANEL_CONTEXTUAL);
63 if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
64 else {
65 win->popup.active_con = 0;
66 win->popup.type = NK_PANEL_NONE;
67 if (win->popup.win)
68 win->popup.win->flags = 0;
69 }
70 }
71 return ret;
72}
73NK_API nk_bool
74nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
75 nk_flags alignment)
76{
77 struct nk_window *win;
78 const struct nk_input *in;
79 const struct nk_style *style;
80
81 struct nk_rect bounds;
82 enum nk_widget_layout_states state;
83
84 NK_ASSERT(ctx);
85 NK_ASSERT(ctx->current);
86 NK_ASSERT(ctx->current->layout);
87 if (!ctx || !ctx->current || !ctx->current->layout)
88 return 0;
89
90 win = ctx->current;
91 style = &ctx->style;
92 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
93 if (!state) return nk_false;
94
95 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
96 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
97 text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
98 nk_contextual_close(ctx);
99 return nk_true;
100 }
101 return nk_false;
102}
103NK_API nk_bool
104nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
105{
106 return nk_contextual_item_text(ctx, label, nk_strlen(label), align);
107}
108NK_API nk_bool
109nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
110 const char *text, int len, nk_flags align)
111{
112 struct nk_window *win;
113 const struct nk_input *in;
114 const struct nk_style *style;
115
116 struct nk_rect bounds;
117 enum nk_widget_layout_states state;
118
119 NK_ASSERT(ctx);
120 NK_ASSERT(ctx->current);
121 NK_ASSERT(ctx->current->layout);
122 if (!ctx || !ctx->current || !ctx->current->layout)
123 return 0;
124
125 win = ctx->current;
126 style = &ctx->style;
127 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
128 if (!state) return nk_false;
129
130 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
131 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
132 img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
133 nk_contextual_close(ctx);
134 return nk_true;
135 }
136 return nk_false;
137}
138NK_API nk_bool
139nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
140 const char *label, nk_flags align)
141{
142 return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);
143}
144NK_API nk_bool
145nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
146 const char *text, int len, nk_flags align)
147{
148 struct nk_window *win;
149 const struct nk_input *in;
150 const struct nk_style *style;
151
152 struct nk_rect bounds;
153 enum nk_widget_layout_states state;
154
155 NK_ASSERT(ctx);
156 NK_ASSERT(ctx->current);
157 NK_ASSERT(ctx->current->layout);
158 if (!ctx || !ctx->current || !ctx->current->layout)
159 return 0;
160
161 win = ctx->current;
162 style = &ctx->style;
163 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
164 if (!state) return nk_false;
165
166 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
167 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
168 symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
169 nk_contextual_close(ctx);
170 return nk_true;
171 }
172 return nk_false;
173}
174NK_API nk_bool
175nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
176 const char *text, nk_flags align)
177{
178 return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);
179}
180NK_API void
181nk_contextual_close(struct nk_context *ctx)
182{
183 NK_ASSERT(ctx);
184 NK_ASSERT(ctx->current);
185 NK_ASSERT(ctx->current->layout);
186 if (!ctx || !ctx->current || !ctx->current->layout) return;
187 nk_popup_close(ctx);
188}
189NK_API void
190nk_contextual_end(struct nk_context *ctx)
191{
192 struct nk_window *popup;
193 struct nk_panel *panel;
194 NK_ASSERT(ctx);
195 NK_ASSERT(ctx->current);
196 if (!ctx || !ctx->current) return;
197
198 popup = ctx->current;
199 panel = popup->layout;
200 NK_ASSERT(popup->parent);
201 NK_ASSERT((int)panel->type & (int)NK_PANEL_SET_POPUP);
202 if (panel->flags & NK_WINDOW_DYNAMIC) {
203 /* Close behavior
204 This is a bit of a hack solution since we do not know before we end our popup
205 how big it will be. We therefore do not directly know when a
206 click outside the non-blocking popup must close it at that direct frame.
207 Instead it will be closed in the next frame.*/
208 struct nk_rect body = {0,0,0,0};
209 if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
210 struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
211 body = panel->bounds;
212 body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
213 body.h = (panel->bounds.y + panel->bounds.h) - body.y;
214 }
215 {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
216 int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
217 if (pressed && in_body)
218 popup->flags |= NK_WINDOW_HIDDEN;
219 }
220 }
221 if (popup->flags & NK_WINDOW_HIDDEN)
222 popup->seq = 0;
223 nk_popup_end(ctx);
224 return;
225}
226
main API and documentation file
@ NK_WINDOW_HIDDEN
Hides window and stops any window interaction and drawing.
Definition nuklear.h:5494
@ NK_WINDOW_ROM
sets window widgets into a read only mode and does not allow input changes
Definition nuklear.h:5492
@ NK_WINDOW_DYNAMIC
special window type growing up in height while being filled to a certain maximum height
Definition nuklear.h:5491
nk_widget_layout_states
Definition nuklear.h:3081
@ NK_WIDGET_ROM
The widget is partially visible and cannot be updated.
Definition nuklear.h:3084