2#include "nuklear_internal.h"
13 elem = nk_create_page_element(ctx);
15 return &elem->data.pan;
22 nk_free_page_element(ctx, pe);
25nk_panel_has_header(nk_flags flags,
const char *title)
28 active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
29 active = active || (flags & NK_WINDOW_TITLE);
34nk_panel_get_padding(const struct
nk_style *style,
enum nk_panel_type type)
38 case NK_PANEL_WINDOW:
return style->window.padding;
39 case NK_PANEL_GROUP:
return style->window.group_padding;
40 case NK_PANEL_POPUP:
return style->window.popup_padding;
41 case NK_PANEL_CONTEXTUAL:
return style->window.contextual_padding;
42 case NK_PANEL_COMBO:
return style->window.combo_padding;
43 case NK_PANEL_MENU:
return style->window.menu_padding;
44 case NK_PANEL_TOOLTIP:
return style->window.menu_padding;}
47nk_panel_get_border(
const struct nk_style *style, nk_flags flags,
48 enum nk_panel_type type)
50 if (flags & NK_WINDOW_BORDER) {
53 case NK_PANEL_WINDOW:
return style->window.border;
54 case NK_PANEL_GROUP:
return style->window.group_border;
55 case NK_PANEL_POPUP:
return style->window.popup_border;
56 case NK_PANEL_CONTEXTUAL:
return style->window.contextual_border;
57 case NK_PANEL_COMBO:
return style->window.combo_border;
58 case NK_PANEL_MENU:
return style->window.menu_border;
59 case NK_PANEL_TOOLTIP:
return style->window.menu_border;
63nk_panel_get_border_color(const struct
nk_style *style,
enum nk_panel_type type)
67 case NK_PANEL_WINDOW:
return style->window.border_color;
68 case NK_PANEL_GROUP:
return style->window.group_border_color;
69 case NK_PANEL_POPUP:
return style->window.popup_border_color;
70 case NK_PANEL_CONTEXTUAL:
return style->window.contextual_border_color;
71 case NK_PANEL_COMBO:
return style->window.combo_border_color;
72 case NK_PANEL_MENU:
return style->window.menu_border_color;
73 case NK_PANEL_TOOLTIP:
return style->window.menu_border_color;}
76nk_panel_is_sub(
enum nk_panel_type type)
78 return ((
int)type & (
int)NK_PANEL_SET_SUB)?1:0;
81nk_panel_is_nonblock(
enum nk_panel_type type)
83 return ((
int)type & (
int)NK_PANEL_SET_NONBLOCK)?1:0;
86nk_panel_begin(
struct nk_context *ctx,
const char *title,
enum nk_panel_type panel_type)
99 NK_ASSERT(ctx->current);
100 NK_ASSERT(ctx->current->layout);
101 if (!ctx || !ctx->current || !ctx->current->layout)
return 0;
102 nk_zero(ctx->current->layout,
sizeof(*ctx->current->layout));
104 nk_zero(ctx->current->layout,
sizeof(
struct nk_panel));
105 ctx->current->layout->type = panel_type;
112 layout = win->layout;
114 in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
115#ifdef NK_INCLUDE_COMMAND_USERDATA
116 win->buffer.userdata = ctx->userdata;
119 scrollbar_size = style->window.scrollbar_size;
120 panel_padding = nk_panel_get_padding(style, panel_type);
123 if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags &
NK_WINDOW_ROM)) {
124 nk_bool left_mouse_down;
125 unsigned int left_mouse_clicked;
126 int left_mouse_click_in_cursor;
130 header.x = win->bounds.x;
131 header.y = win->bounds.y;
132 header.w = win->bounds.w;
133 if (nk_panel_has_header(win->flags, title)) {
134 header.h = font->
height + 2.0f * style->window.header.padding.y;
135 header.h += 2.0f * style->window.header.label_padding.y;
136 }
else header.h = panel_padding.y;
139 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
140 left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked;
141 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
142 NK_BUTTON_LEFT, header, nk_true);
143 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) {
144 win->bounds.x = win->bounds.x + in->mouse.delta.x;
145 win->bounds.y = win->bounds.y + in->mouse.delta.y;
146 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
147 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
148 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
153 layout->type = panel_type;
154 layout->flags = win->flags;
155 layout->bounds = win->bounds;
156 layout->bounds.x += panel_padding.x;
157 layout->bounds.w -= 2*panel_padding.x;
158 if (win->flags & NK_WINDOW_BORDER) {
159 layout->border = nk_panel_get_border(style, win->flags, panel_type);
160 layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
161 }
else layout->border = 0;
162 layout->at_y = layout->bounds.y;
163 layout->at_x = layout->bounds.x;
165 layout->header_height = 0;
166 layout->footer_height = 0;
168 layout->row.index = 0;
169 layout->row.columns = 0;
170 layout->row.ratio = 0;
171 layout->row.item_width = 0;
172 layout->row.tree_depth = 0;
173 layout->row.height = panel_padding.y;
174 layout->has_scrolling = nk_true;
175 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
176 layout->bounds.w -= scrollbar_size.x;
177 if (!nk_panel_is_nonblock(panel_type)) {
178 layout->footer_height = 0;
179 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
180 layout->footer_height = scrollbar_size.y;
181 layout->bounds.h -= layout->footer_height;
185 if (nk_panel_has_header(win->flags, title))
192 header.x = win->bounds.x;
193 header.y = win->bounds.y;
194 header.w = win->bounds.w;
195 header.h = font->
height + 2.0f * style->window.header.padding.y;
196 header.h += (2.0f * style->window.header.label_padding.y);
199 layout->header_height = header.h;
200 layout->bounds.y += header.h;
201 layout->bounds.h -= header.h;
202 layout->at_y += header.h;
205 if (ctx->active == win) {
206 background = &style->window.header.active;
207 text.text = style->window.header.label_active;
208 }
else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
209 background = &style->window.header.hover;
210 text.text = style->window.header.label_hover;
212 background = &style->window.header.normal;
213 text.text = style->window.header.label_normal;
219 switch(background->type) {
220 case NK_STYLE_ITEM_IMAGE:
221 text.background = nk_rgba(0,0,0,0);
222 nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
224 case NK_STYLE_ITEM_NINE_SLICE:
225 text.background = nk_rgba(0, 0, 0, 0);
226 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white);
228 case NK_STYLE_ITEM_COLOR:
229 text.background = background->data.color;
236 button.y = header.y + style->window.header.padding.y;
237 button.h = header.h - 2 * style->window.header.padding.y;
239 if (win->flags & NK_WINDOW_CLOSABLE) {
241 if (style->window.header.align == NK_HEADER_RIGHT) {
242 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
243 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
245 button.x = header.x + style->window.header.padding.x;
246 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
249 if (nk_do_button_symbol(&ws, &win->buffer, button,
250 style->window.header.close_symbol, NK_BUTTON_DEFAULT,
251 &style->window.header.close_button, in, style->font) && !(win->flags &
NK_WINDOW_ROM))
259 if (win->flags & NK_WINDOW_MINIMIZABLE) {
261 if (style->window.header.align == NK_HEADER_RIGHT) {
262 button.x = (header.w + header.x) - button.w;
263 if (!(win->flags & NK_WINDOW_CLOSABLE)) {
264 button.x -= style->window.header.padding.x;
265 header.w -= style->window.header.padding.x;
267 header.w -= button.w + style->window.header.spacing.x;
270 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
273 style->window.header.maximize_symbol: style->window.header.minimize_symbol,
274 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags &
NK_WINDOW_ROM))
281 int text_len = nk_strlen(title);
282 struct nk_rect label = {0,0,0,0};
283 float t = font->
width(font->userdata, font->
height, title, text_len);
286 label.x = header.x + style->window.header.padding.x;
287 label.x += style->window.header.label_padding.x;
288 label.y = header.y + style->window.header.label_padding.y;
289 label.h = font->
height + 2 * style->window.header.label_padding.y;
290 label.w = t + 2 * style->window.header.spacing.x;
291 label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
292 nk_widget_text(out, label, (
const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
298 body.x = win->bounds.x;
299 body.w = win->bounds.w;
300 body.y = (win->bounds.y + layout->header_height);
301 body.h = (win->bounds.h - layout->header_height);
303 switch(style->window.fixed_background.type) {
304 case NK_STYLE_ITEM_IMAGE:
305 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
307 case NK_STYLE_ITEM_NINE_SLICE:
308 nk_draw_nine_slice(out, body, &style->window.fixed_background.data.slice, nk_white);
310 case NK_STYLE_ITEM_COLOR:
311 nk_fill_rect(out, body, style->window.rounding, style->window.fixed_background.data.color);
318 layout->clip = layout->bounds;
319 nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
320 layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
321 nk_push_scissor(out, clip);
322 layout->clip = clip;}
338 NK_ASSERT(ctx->current);
339 NK_ASSERT(ctx->current->layout);
340 if (!ctx || !ctx->current || !ctx->current->layout)
343 window = ctx->current;
344 layout = window->layout;
346 out = &window->buffer;
347 in = (layout->flags &
NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
348 if (!nk_panel_is_sub(layout->type))
349 nk_push_scissor(out, nk_null_rect);
352 scrollbar_size = style->window.scrollbar_size;
353 panel_padding = nk_panel_get_padding(style, layout->type);
356 layout->at_y += layout->row.height;
363 if (layout->at_y < (layout->bounds.y + layout->bounds.h))
364 layout->bounds.h = layout->at_y - layout->bounds.y;
367 empty_space.x = window->bounds.x;
368 empty_space.y = layout->bounds.y;
369 empty_space.h = panel_padding.y;
370 empty_space.w = window->bounds.w;
371 nk_fill_rect(out, empty_space, 0, style->window.background);
374 empty_space.x = window->bounds.x;
375 empty_space.y = layout->bounds.y;
376 empty_space.w = panel_padding.x + layout->border;
377 empty_space.h = layout->bounds.h;
378 nk_fill_rect(out, empty_space, 0, style->window.background);
381 empty_space.x = layout->bounds.x + layout->bounds.w;
382 empty_space.y = layout->bounds.y;
383 empty_space.w = panel_padding.x + layout->border;
384 empty_space.h = layout->bounds.h;
385 if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
386 empty_space.w += scrollbar_size.x;
387 nk_fill_rect(out, empty_space, 0, style->window.background);
390 if (layout->footer_height > 0) {
391 empty_space.x = window->bounds.x;
392 empty_space.y = layout->bounds.y + layout->bounds.h;
393 empty_space.w = window->bounds.w;
394 empty_space.h = layout->footer_height;
395 nk_fill_rect(out, empty_space, 0, style->window.background);
400 if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
402 window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
405 int scroll_has_scrolling;
412 if (nk_panel_is_sub(layout->type))
416 struct nk_panel *root_panel = window->layout;
417 while (root_panel->parent)
418 root_panel = root_panel->parent;
419 while (root_window->parent)
420 root_window = root_window->parent;
423 scroll_has_scrolling = nk_false;
424 if ((root_window == ctx->active) && layout->has_scrolling) {
426 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
427 NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
428 root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
431 root_panel = window->layout;
432 while (root_panel->parent) {
433 root_panel->has_scrolling = nk_false;
434 root_panel = root_panel->parent;
436 root_panel->has_scrolling = nk_false;
437 scroll_has_scrolling = nk_true;
442 scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
443 if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
444 window->scrolled = nk_true;
445 else window->scrolled = nk_false;
451 scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
452 scroll.y = layout->bounds.y;
453 scroll.w = scrollbar_size.x;
454 scroll.h = layout->bounds.h;
456 scroll_offset = (float)*layout->offset_y;
457 scroll_step = scroll.h * 0.10f;
458 scroll_inc = scroll.h * 0.01f;
459 scroll_target = (float)(
int)(layout->at_y - scroll.y);
460 scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
461 scroll_offset, scroll_target, scroll_step, scroll_inc,
462 &ctx->style.scrollv, in, style->font);
463 *layout->offset_y = (nk_uint)scroll_offset;
464 if (in && scroll_has_scrolling)
465 in->mouse.scroll_delta.y = 0;
470 scroll.x = layout->bounds.x;
471 scroll.y = layout->bounds.y + layout->bounds.h;
472 scroll.w = layout->bounds.w;
473 scroll.h = scrollbar_size.y;
475 scroll_offset = (float)*layout->offset_x;
476 scroll_target = (float)(
int)(layout->max_x - scroll.x);
477 scroll_step = layout->max_x * 0.05f;
478 scroll_inc = layout->max_x * 0.005f;
479 scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
480 scroll_offset, scroll_target, scroll_step, scroll_inc,
481 &ctx->style.scrollh, in, style->font);
482 *layout->offset_x = (nk_uint)scroll_offset;
487 if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
488 int has_input = nk_input_is_mouse_moved(&ctx->input) || ctx->input.mouse.scroll_delta.y != 0;
490 int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
491 if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
492 window->scrollbar_hiding_timer += ctx->delta_time_seconds;
493 else window->scrollbar_hiding_timer = 0;
494 }
else window->scrollbar_hiding_timer = 0;
497 if (layout->flags & NK_WINDOW_BORDER)
499 struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
501 ? (style->window.border + window->bounds.y + layout->header_height)
503 ? (layout->bounds.y + layout->bounds.h + layout->footer_height)
504 : (window->bounds.y + window->bounds.h));
505 struct nk_rect b = window->bounds;
506 b.h = padding_y - window->bounds.y;
507 nk_stroke_rect(out, b, style->window.rounding, layout->border, border_color);
515 scaler.w = scrollbar_size.x;
516 scaler.h = scrollbar_size.y;
517 scaler.y = layout->bounds.y + layout->bounds.h;
518 if (layout->flags & NK_WINDOW_SCALE_LEFT)
519 scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
520 else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
521 if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
522 scaler.x -= scaler.w;
526 if (item->type == NK_STYLE_ITEM_IMAGE)
529 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
530 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
531 scaler.y + scaler.h, scaler.x + scaler.w,
532 scaler.y + scaler.h, item->data.color);
534 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
535 scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
541 struct nk_vec2 window_size = style->window.min_size;
542 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
543 int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
544 NK_BUTTON_LEFT, scaler, nk_true);
546 if (left_mouse_down && left_mouse_click_in_scaler) {
547 float delta_x = in->mouse.delta.x;
548 if (layout->flags & NK_WINDOW_SCALE_LEFT) {
550 window->bounds.x += in->mouse.delta.x;
553 if (window->bounds.w + delta_x >= window_size.x) {
554 if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
555 window->bounds.w = window->bounds.w + delta_x;
556 scaler.x += in->mouse.delta.x;
561 if (window_size.y < window->bounds.h + in->mouse.delta.y) {
562 if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
563 window->bounds.h = window->bounds.h + in->mouse.delta.y;
564 scaler.y += in->mouse.delta.y;
568 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
569 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
570 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
574 if (!nk_panel_is_sub(layout->type)) {
577 nk_command_buffer_reset(&window->buffer);
579 else nk_finish(ctx, window);
587 window->flags = layout->flags;
590 if (window->property.active && window->property.old != window->property.seq &&
591 window->property.active == window->property.prev) {
592 nk_zero(&window->property,
sizeof(window->property));
594 window->property.old = window->property.seq;
595 window->property.prev = window->property.active;
596 window->property.seq = 0;
599 if (window->edit.active && window->edit.old != window->edit.seq &&
600 window->edit.active == window->edit.prev) {
601 nk_zero(&window->edit,
sizeof(window->edit));
603 window->edit.old = window->edit.seq;
604 window->edit.prev = window->edit.active;
605 window->edit.seq = 0;
608 if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
609 window->popup.con_count = 0;
610 window->popup.con_old = 0;
611 window->popup.active_con = 0;
613 window->popup.con_old = window->popup.con_count;
614 window->popup.con_count = 0;
616 window->popup.combo_count = 0;
618 NK_ASSERT(!layout->row.tree_depth);
main API and documentation file
@ NK_WINDOW_CLOSED
Directly closes and frees the window at the end of the frame.
@ NK_WINDOW_MINIMIZED
marks the window as minimized
@ NK_WINDOW_HIDDEN
Hides window and stops any window interaction and drawing.
@ NK_WINDOW_ROM
sets window widgets into a read only mode and does not allow input changes
@ NK_WINDOW_DYNAMIC
special window type growing up in height while being filled to a certain maximum height
@ NK_WINDOW_REMOVE_ROM
Removes read only mode at the end of the window.
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
misc
NK_API nk_bool nk_window_is_hovered(const struct nk_context *ctx)
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
filled shades
NK_API void nk_layout_reset_min_row_height(struct nk_context *)
Reset the currently used minimum row height back to font_height + text_padding + padding
nk_text_width_f width
!< max height of the font
float height
!< user provided font handle