Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions demo/sdl3_renderer/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,113 @@ SDL_AppEvent(void *appstate, SDL_Event* event)
return SDL_APP_CONTINUE;
}

/* Visual checks for the tree-element hit box and nk_combo height cap.
* Styles are exaggerated so a regression is obvious. */
static void
layout_sizing_bugs(struct nk_context *ctx)
{
static const char *items[] = {
"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"
};
static int combo_small = 0;
static int combo_large = 0;
static nk_bool tree_selected = nk_true;

const int count = (int)NK_LEN(items);
const int item_h = 25;
const float demo_sel_pad = 14.0f;
const float demo_combo_pad = 48.0f;
const float demo_parent_pad = 48.0f;

struct nk_vec2 sel_pad_save;
struct nk_vec2 combo_pad_save;
struct nk_vec2 win_pad_save;
float spacing_y, combo_border;
float accurate, current_h;

if (!nk_begin(ctx, "Sizing bugs", nk_rect(430, 40, 400, 620),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
nk_end(ctx);
return;
}

spacing_y = ctx->style.window.spacing.y;
combo_border = ctx->style.window.combo_border;

/* ---- tree element: selectable is text + 2 * padding ---- */
nk_layout_row_dynamic(ctx, 18, 1);
nk_label(ctx, "Tree element: selectable hugs the text", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 54, 1);
nk_label_wrap(ctx, "nk_tree_element_* sizes the title to text width + 2 * selectable.padding.x so nk_do_selectable can inset both sides. Highlight should have equal pad left and right of 'Hi'.");

sel_pad_save = ctx->style.selectable.padding;
ctx->style.selectable.padding.x = demo_sel_pad;

if (nk_tree_element_push(ctx, NK_TREE_NODE, "Hi", NK_MAXIMIZED, &tree_selected)) {
nk_label(ctx, "Child row (collapse uses the triangle only).", NK_TEXT_LEFT);
nk_tree_element_pop(ctx);
}
ctx->style.selectable.padding = sel_pad_save;

nk_layout_row_dynamic(ctx, 18, 1);
nk_labelf(ctx, NK_TEXT_LEFT, "selected=%s pad.x=%.0f (box = text + 2*%.0f)",
tree_selected ? "true" : "false", demo_sel_pad, demo_sel_pad);
nk_layout_row_dynamic(ctx, 32, 1);
nk_label_wrap(ctx, "Click in the right pad (still toggles), then further right on the same row (does not).");

nk_layout_row_dynamic(ctx, 8, 1);
nk_spacing(ctx, 1);

/* ---- combo with large combo_padding: cap must include it ---- */
nk_layout_row_dynamic(ctx, 18, 1);
nk_label(ctx, "Combo + large combo_padding.y", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 54, 1);
nk_label_wrap(ctx, "Height cap includes combo_padding and border. The top band is padding; all items should fit with no scrollbar.");

accurate = (float)count * (float)item_h + (float)count * spacing_y
+ demo_combo_pad + 2.0f * combo_border;
current_h = (float)count * (float)item_h + (float)count * spacing_y
+ 2.0f * spacing_y + 2.0f * ctx->style.window.padding.y;

nk_layout_row_dynamic(ctx, 18, 1);
nk_labelf(ctx, NK_TEXT_LEFT, "nk_combo cap=%.0f old formula=%.0f", accurate, current_h);

combo_pad_save = ctx->style.window.combo_padding;
ctx->style.window.combo_padding.y = demo_combo_pad;
nk_layout_row_dynamic(ctx, (float)item_h, 1);
combo_small = nk_combo(ctx, items, count, combo_small, item_h,
nk_vec2(nk_widget_width(ctx), 400));
ctx->style.window.combo_padding = combo_pad_save;

nk_layout_row_dynamic(ctx, 8, 1);
nk_spacing(ctx, 1);

/* ---- combo with large parent padding: cap must ignore it ---- */
nk_layout_row_dynamic(ctx, 18, 1);
nk_label(ctx, "Combo + large window.padding.y", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 54, 1);
nk_label_wrap(ctx, "Height cap uses combo padding, not parent window.padding. Allocated height should match the list; a click just below the last item should close the combo.");

accurate = (float)count * (float)item_h + (float)count * spacing_y
+ ctx->style.window.combo_padding.y + 2.0f * combo_border;
current_h = (float)count * (float)item_h + (float)count * spacing_y
+ 2.0f * spacing_y + 2.0f * demo_parent_pad;

nk_layout_row_dynamic(ctx, 18, 1);
nk_labelf(ctx, NK_TEXT_LEFT, "nk_combo cap=%.0f old formula=%.0f", accurate, current_h);

win_pad_save = ctx->style.window.padding;
ctx->style.window.padding.y = demo_parent_pad;
nk_layout_row_dynamic(ctx, (float)item_h, 1);
combo_large = nk_combo(ctx, items, count, combo_large, item_h,
nk_vec2(nk_widget_width(ctx), 400));
ctx->style.window.padding = win_pad_save;

nk_end(ctx);
}

SDL_AppResult
SDL_AppIterate(void *appstate)
{
Expand Down Expand Up @@ -371,6 +478,8 @@ SDL_AppIterate(void *appstate)
}
nk_end(ctx);

layout_sizing_bugs(ctx);

/* -------------- EXAMPLES ---------------- */
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
Expand Down
59 changes: 30 additions & 29 deletions nuklear.h
Original file line number Diff line number Diff line change
Expand Up @@ -23240,10 +23240,10 @@ nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type
/* draw label */
{nk_flags dummy = 0;
struct nk_rect label;
/* calculate size of the text and tooltip */
/* selectable insets by padding on both sides */
text_len = nk_strlen(title);
text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
text_width += (4 * padding.x);
text_width += 2 * padding.x;

header.w = NK_MAX(header.w, sym.w + item_spacing.x);
label.x = sym.x + sym.w + item_spacing.x;
Expand Down Expand Up @@ -30013,6 +30013,22 @@ nk_color_picker(struct nk_context *ctx, struct nk_colorf color,
* COMBO
*
* ===============================================================*/
/* Outer popup height that fits `count` rows: each row is item_height plus
* trailing spacing, plus combo top padding and the border nk_panel_begin
* subtracts. Combos always get NK_WINDOW_BORDER from nk_nonblock_begin. */
NK_INTERN float
nk_combo_calc_max_height(const struct nk_context *ctx, int count, int item_height)
{
struct nk_vec2 spacing;
struct nk_vec2 padding;

spacing = ctx->style.window.spacing;
padding = nk_panel_get_padding(&ctx->style, NK_PANEL_COMBO);
return (float)count * (float)item_height
+ (float)count * spacing.y
+ padding.y
+ 2.0f * ctx->style.window.combo_border;
}
NK_INTERN nk_bool
nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
struct nk_vec2 size, nk_bool is_clicked, struct nk_rect header)
Expand Down Expand Up @@ -30713,21 +30729,16 @@ nk_combo(struct nk_context *ctx, const char *const *items, int count,
int selected, int item_height, struct nk_vec2 size)
{
int i = 0;
int max_height;
struct nk_vec2 item_spacing;
struct nk_vec2 window_padding;
float max_height;

NK_ASSERT(ctx);
NK_ASSERT(items);
NK_ASSERT(ctx->current);
if (!ctx || !items ||!count)
return selected;

item_spacing = ctx->style.window.spacing;
window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
max_height = count * item_height + count * (int)item_spacing.y;
max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
size.y = NK_MIN(size.y, (float)max_height);
max_height = nk_combo_calc_max_height(ctx, count, item_height);
size.y = NK_MIN(size.y, max_height);
if (nk_combo_begin_label(ctx, items[selected], size)) {
nk_layout_row_dynamic(ctx, (float)item_height, 1);
for (i = 0; i < count; ++i) {
Expand All @@ -30743,9 +30754,7 @@ nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separa
int separator, int selected, int count, int item_height, struct nk_vec2 size)
{
int i;
int max_height;
struct nk_vec2 item_spacing;
struct nk_vec2 window_padding;
float max_height;
const char *current_item;
const char *iter;
int length = 0;
Expand All @@ -30755,12 +30764,8 @@ nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separa
if (!ctx || !items_separated_by_separator)
return selected;

/* calculate popup window */
item_spacing = ctx->style.window.spacing;
window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
max_height = count * item_height + count * (int)item_spacing.y;
max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
size.y = NK_MIN(size.y, (float)max_height);
max_height = nk_combo_calc_max_height(ctx, count, item_height);
size.y = NK_MIN(size.y, max_height);

/* find selected item */
current_item = items_separated_by_separator;
Expand Down Expand Up @@ -30798,22 +30803,16 @@ nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const c
void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
{
int i;
int max_height;
struct nk_vec2 item_spacing;
struct nk_vec2 window_padding;
float max_height;
const char *item;

NK_ASSERT(ctx);
NK_ASSERT(item_getter);
if (!ctx || !item_getter)
return selected;

/* calculate popup window */
item_spacing = ctx->style.window.spacing;
window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
max_height = count * item_height + count * (int)item_spacing.y;
max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
size.y = NK_MIN(size.y, (float)max_height);
max_height = nk_combo_calc_max_height(ctx, count, item_height);
size.y = NK_MIN(size.y, max_height);

item_getter(userdata, selected, &item);
if (nk_combo_begin_label(ctx, item, size)) {
Expand Down Expand Up @@ -31031,7 +31030,9 @@ nk_tooltip_offset(struct nk_context *ctx, const char *text, enum nk_tooltip_pos
text_len = nk_strlen(text);
text_width = style->font->width(style->font->userdata,
style->font->height, text, text_len);
text_width += (4 * padding.x);
/* outer bounds: nk_panel_begin subtracts popup padding and border */
text_width += 2 * style->window.popup_padding.x;
text_width += 2 * style->window.popup_border;
text_height = (style->font->height + 2 * padding.y);

/* execute tooltip and fill with text */
Expand Down
51 changes: 25 additions & 26 deletions src/nuklear_combo.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
* COMBO
*
* ===============================================================*/
/* Outer popup height that fits `count` rows: each row is item_height plus
* trailing spacing, plus combo top padding and the border nk_panel_begin
* subtracts. Combos always get NK_WINDOW_BORDER from nk_nonblock_begin. */
NK_INTERN float
nk_combo_calc_max_height(const struct nk_context *ctx, int count, int item_height)
{
struct nk_vec2 spacing;
struct nk_vec2 padding;

spacing = ctx->style.window.spacing;
padding = nk_panel_get_padding(&ctx->style, NK_PANEL_COMBO);
return (float)count * (float)item_height
+ (float)count * spacing.y
+ padding.y
+ 2.0f * ctx->style.window.combo_border;
}
NK_INTERN nk_bool
nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
struct nk_vec2 size, nk_bool is_clicked, struct nk_rect header)
Expand Down Expand Up @@ -706,21 +722,16 @@ nk_combo(struct nk_context *ctx, const char *const *items, int count,
int selected, int item_height, struct nk_vec2 size)
{
int i = 0;
int max_height;
struct nk_vec2 item_spacing;
struct nk_vec2 window_padding;
float max_height;

NK_ASSERT(ctx);
NK_ASSERT(items);
NK_ASSERT(ctx->current);
if (!ctx || !items ||!count)
return selected;

item_spacing = ctx->style.window.spacing;
window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
max_height = count * item_height + count * (int)item_spacing.y;
max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
size.y = NK_MIN(size.y, (float)max_height);
max_height = nk_combo_calc_max_height(ctx, count, item_height);
size.y = NK_MIN(size.y, max_height);
if (nk_combo_begin_label(ctx, items[selected], size)) {
nk_layout_row_dynamic(ctx, (float)item_height, 1);
for (i = 0; i < count; ++i) {
Expand All @@ -736,9 +747,7 @@ nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separa
int separator, int selected, int count, int item_height, struct nk_vec2 size)
{
int i;
int max_height;
struct nk_vec2 item_spacing;
struct nk_vec2 window_padding;
float max_height;
const char *current_item;
const char *iter;
int length = 0;
Expand All @@ -748,12 +757,8 @@ nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separa
if (!ctx || !items_separated_by_separator)
return selected;

/* calculate popup window */
item_spacing = ctx->style.window.spacing;
window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
max_height = count * item_height + count * (int)item_spacing.y;
max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
size.y = NK_MIN(size.y, (float)max_height);
max_height = nk_combo_calc_max_height(ctx, count, item_height);
size.y = NK_MIN(size.y, max_height);

/* find selected item */
current_item = items_separated_by_separator;
Expand Down Expand Up @@ -791,22 +796,16 @@ nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const c
void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
{
int i;
int max_height;
struct nk_vec2 item_spacing;
struct nk_vec2 window_padding;
float max_height;
const char *item;

NK_ASSERT(ctx);
NK_ASSERT(item_getter);
if (!ctx || !item_getter)
return selected;

/* calculate popup window */
item_spacing = ctx->style.window.spacing;
window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
max_height = count * item_height + count * (int)item_spacing.y;
max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
size.y = NK_MIN(size.y, (float)max_height);
max_height = nk_combo_calc_max_height(ctx, count, item_height);
size.y = NK_MIN(size.y, max_height);

item_getter(userdata, selected, &item);
if (nk_combo_begin_label(ctx, item, size)) {
Expand Down
4 changes: 3 additions & 1 deletion src/nuklear_tooltip.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ nk_tooltip_offset(struct nk_context *ctx, const char *text, enum nk_tooltip_pos
text_len = nk_strlen(text);
text_width = style->font->width(style->font->userdata,
style->font->height, text, text_len);
text_width += (4 * padding.x);
/* outer bounds: nk_panel_begin subtracts popup padding and border */
text_width += 2 * style->window.popup_padding.x;
text_width += 2 * style->window.popup_border;
text_height = (style->font->height + 2 * padding.y);

/* execute tooltip and fill with text */
Expand Down
4 changes: 2 additions & 2 deletions src/nuklear_tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,10 @@ nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type
/* draw label */
{nk_flags dummy = 0;
struct nk_rect label;
/* calculate size of the text and tooltip */
/* selectable insets by padding on both sides */
text_len = nk_strlen(title);
text_width = style->font->width(style->font->userdata, style->font->height, title, text_len);
text_width += (4 * padding.x);
text_width += 2 * padding.x;

header.w = NK_MAX(header.w, sym.w + item_spacing.x);
label.x = sym.x + sym.w + item_spacing.x;
Expand Down
Loading