Nuklear
Minimal-state, immediate-mode graphical user interface toolkit written in ANSI C.
 
Loading...
Searching...
No Matches
nuklear_popup.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ===============================================================
5 *
6 * POPUP
7 *
8 * ===============================================================*/
9NK_API nk_bool
10nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
11 const char *title, nk_flags flags, struct nk_rect rect)
12{
13 struct nk_window *popup;
14 struct nk_window *win;
15 struct nk_panel *panel;
16
17 int title_len;
18 nk_hash title_hash;
19 nk_size allocated;
20
21 NK_ASSERT(ctx);
22 NK_ASSERT(title);
23 NK_ASSERT(ctx->current);
24 NK_ASSERT(ctx->current->layout);
25 if (!ctx || !ctx->current || !ctx->current->layout)
26 return 0;
27
28 win = ctx->current;
29 panel = win->layout;
30 NK_ASSERT(!((int)panel->type & (int)NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
31 (void)panel;
32 title_len = (int)nk_strlen(title);
33 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
34
35 popup = win->popup.win;
36 if (!popup) {
37 popup = (struct nk_window*)nk_create_window(ctx);
38 popup->parent = win;
39 win->popup.win = popup;
40 win->popup.active = 0;
41 win->popup.type = NK_PANEL_POPUP;
42 }
43
44 /* make sure we have correct popup */
45 if (win->popup.name != title_hash) {
46 if (!win->popup.active) {
47 nk_zero(popup, sizeof(*popup));
48 win->popup.name = title_hash;
49 win->popup.active = 1;
50 win->popup.type = NK_PANEL_POPUP;
51 } else return 0;
52 }
53
54 /* popup position is local to window */
55 ctx->current = popup;
56 rect.x += win->layout->clip.x;
57 rect.y += win->layout->clip.y;
58
59 /* setup popup data */
60 popup->parent = win;
61 popup->bounds = rect;
62 popup->seq = ctx->seq;
63 popup->layout = (struct nk_panel*)nk_create_panel(ctx);
64 popup->flags = flags;
65 popup->flags |= NK_WINDOW_BORDER;
66 if (type == NK_POPUP_DYNAMIC)
67 popup->flags |= NK_WINDOW_DYNAMIC;
68
69 popup->buffer = win->buffer;
70 nk_start_popup(ctx, win);
71 allocated = ctx->memory.allocated;
72 nk_push_scissor(&popup->buffer, nk_null_rect);
73
74 if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
75 /* popup is running therefore invalidate parent panels */
76 struct nk_panel *root;
77 root = win->layout;
78 while (root) {
79 root->flags |= NK_WINDOW_ROM;
80 root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
81 root = root->parent;
82 }
83 win->popup.active = 1;
84 popup->layout->offset_x = &popup->scrollbar.x;
85 popup->layout->offset_y = &popup->scrollbar.y;
86 popup->layout->parent = win->layout;
87 return 1;
88 } else {
89 /* popup was closed/is invalid so cleanup */
90 struct nk_panel *root;
91 root = win->layout;
92 while (root) {
93 root->flags |= NK_WINDOW_REMOVE_ROM;
94 root = root->parent;
95 }
96 win->popup.buf.active = 0;
97 win->popup.active = 0;
98 ctx->memory.allocated = allocated;
99 ctx->current = win;
100 nk_free_panel(ctx, popup->layout);
101 popup->layout = 0;
102 return 0;
103 }
104}
105NK_LIB nk_bool
106nk_nonblock_begin(struct nk_context *ctx,
107 nk_flags flags, struct nk_rect body, struct nk_rect header,
108 enum nk_panel_type panel_type)
109{
110 struct nk_window *popup;
111 struct nk_window *win;
112 struct nk_panel *panel;
113 int is_active = nk_true;
114
115 NK_ASSERT(ctx);
116 NK_ASSERT(ctx->current);
117 NK_ASSERT(ctx->current->layout);
118 if (!ctx || !ctx->current || !ctx->current->layout)
119 return 0;
120
121 /* popups cannot have popups */
122 win = ctx->current;
123 panel = win->layout;
124 NK_ASSERT(!((int)panel->type & (int)NK_PANEL_SET_POPUP));
125 (void)panel;
126 popup = win->popup.win;
127 if (!popup) {
128 /* create window for nonblocking popup */
129 popup = (struct nk_window*)nk_create_window(ctx);
130 popup->parent = win;
131 win->popup.win = popup;
132 win->popup.type = panel_type;
133 nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
134 } else {
135 /* close the popup if user pressed outside or in the header */
136 int pressed, in_body, in_header;
137#ifdef NK_BUTTON_TRIGGER_ON_RELEASE
138 pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT);
139#else
140 pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
141#endif
142 in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
143 in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
144 if (pressed && (!in_body || in_header))
145 is_active = nk_false;
146 }
147 win->popup.header = header;
148
149 if (!is_active) {
150 /* remove read only mode from all parent panels */
151 struct nk_panel *root = win->layout;
152 while (root) {
153 root->flags |= NK_WINDOW_REMOVE_ROM;
154 root = root->parent;
155 }
156 win->popup.buf.active = 0;
157 return is_active;
158 }
159 popup->bounds = body;
160 popup->parent = win;
161 popup->layout = (struct nk_panel*)nk_create_panel(ctx);
162 popup->flags = flags;
163 popup->flags |= NK_WINDOW_BORDER;
164 popup->flags |= NK_WINDOW_DYNAMIC;
165 popup->seq = ctx->seq;
166 win->popup.active = 1;
167 NK_ASSERT(popup->layout);
168
169 nk_start_popup(ctx, win);
170 popup->buffer = win->buffer;
171 nk_push_scissor(&popup->buffer, nk_null_rect);
172 ctx->current = popup;
173
174 nk_panel_begin(ctx, 0, panel_type);
175 win->buffer = popup->buffer;
176 popup->layout->parent = win->layout;
177 popup->layout->offset_x = &popup->scrollbar.x;
178 popup->layout->offset_y = &popup->scrollbar.y;
179
180 /* set read only mode to all parent panels */
181 {struct nk_panel *root;
182 root = win->layout;
183 while (root) {
184 root->flags |= NK_WINDOW_ROM;
185 root = root->parent;
186 }}
187 return is_active;
188}
189NK_API void
190nk_popup_close(struct nk_context *ctx)
191{
192 struct nk_window *popup;
193 NK_ASSERT(ctx);
194 if (!ctx || !ctx->current) return;
195
196 popup = ctx->current;
197 NK_ASSERT(popup->parent);
198 NK_ASSERT((int)popup->layout->type & (int)NK_PANEL_SET_POPUP);
199 popup->flags |= NK_WINDOW_HIDDEN;
200}
201NK_API void
202nk_popup_end(struct nk_context *ctx)
203{
204 struct nk_window *win;
205 struct nk_window *popup;
206
207 NK_ASSERT(ctx);
208 NK_ASSERT(ctx->current);
209 NK_ASSERT(ctx->current->layout);
210 if (!ctx || !ctx->current || !ctx->current->layout)
211 return;
212
213 popup = ctx->current;
214 if (!popup->parent) return;
215 win = popup->parent;
216 if (popup->flags & NK_WINDOW_HIDDEN) {
217 struct nk_panel *root;
218 root = win->layout;
219 while (root) {
220 root->flags |= NK_WINDOW_REMOVE_ROM;
221 root = root->parent;
222 }
223 win->popup.active = 0;
224 }
225 nk_push_scissor(&popup->buffer, nk_null_rect);
226 nk_end(ctx);
227
228 win->buffer = popup->buffer;
229 nk_finish_popup(ctx, win);
230 ctx->current = win;
231 nk_push_scissor(&win->buffer, win->layout->clip);
232}
233NK_API void
234nk_popup_get_scroll(const struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y)
235{
236 struct nk_window *popup;
237
238 NK_ASSERT(ctx);
239 NK_ASSERT(ctx->current);
240 NK_ASSERT(ctx->current->layout);
241 if (!ctx || !ctx->current || !ctx->current->layout)
242 return;
243
244 popup = ctx->current;
245 if (offset_x)
246 *offset_x = popup->scrollbar.x;
247 if (offset_y)
248 *offset_y = popup->scrollbar.y;
249}
250NK_API void
251nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y)
252{
253 struct nk_window *popup;
254
255 NK_ASSERT(ctx);
256 NK_ASSERT(ctx->current);
257 NK_ASSERT(ctx->current->layout);
258 if (!ctx || !ctx->current || !ctx->current->layout)
259 return;
260
261 popup = ctx->current;
262 popup->scrollbar.x = offset_x;
263 popup->scrollbar.y = offset_y;
264}
nk_size allocated
!< growing factor for dynamic memory management
Definition nuklear.h:4238