766 lines
23 KiB
C
766 lines
23 KiB
C
#include "nuklear.h"
|
|
#include "nuklear_internal.h"
|
|
|
|
/* ===============================================================
|
|
*
|
|
* LAYOUT
|
|
*
|
|
* ===============================================================*/
|
|
NK_API void
|
|
nk_layout_set_min_row_height(struct nk_context *ctx, float height)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
layout->row.min_height = height;
|
|
}
|
|
NK_API void
|
|
nk_layout_reset_min_row_height(struct nk_context *ctx)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
layout->row.min_height = ctx->style.font->height;
|
|
layout->row.min_height += ctx->style.text.padding.y*2;
|
|
layout->row.min_height += ctx->style.window.min_row_height_padding*2;
|
|
}
|
|
NK_LIB float
|
|
nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
|
|
float total_space, int columns)
|
|
{
|
|
float panel_padding;
|
|
float panel_spacing;
|
|
float panel_space;
|
|
|
|
struct nk_vec2 spacing;
|
|
struct nk_vec2 padding;
|
|
|
|
spacing = style->window.spacing;
|
|
padding = nk_panel_get_padding(style, type);
|
|
|
|
/* calculate the usable panel space */
|
|
panel_padding = 2 * padding.x;
|
|
panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
|
|
panel_space = total_space - panel_padding - panel_spacing;
|
|
return panel_space;
|
|
}
|
|
NK_LIB void
|
|
nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
|
|
float height, int cols)
|
|
{
|
|
struct nk_panel *layout;
|
|
const struct nk_style *style;
|
|
struct nk_command_buffer *out;
|
|
|
|
struct nk_vec2 item_spacing;
|
|
struct nk_color color;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
/* prefetch some configuration data */
|
|
layout = win->layout;
|
|
style = &ctx->style;
|
|
out = &win->buffer;
|
|
color = style->window.background;
|
|
item_spacing = style->window.spacing;
|
|
|
|
/* if one of these triggers you forgot to add an `if` condition around either
|
|
a window, group, popup, combobox or contextual menu `begin` and `end` block.
|
|
Example:
|
|
if (nk_begin(...) {...} nk_end(...); or
|
|
if (nk_group_begin(...) { nk_group_end(...);} */
|
|
NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
|
|
NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
|
|
NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
|
|
|
|
/* update the current row and set the current row layout */
|
|
layout->row.index = 0;
|
|
layout->at_y += layout->row.height;
|
|
layout->row.columns = cols;
|
|
if (height == 0.0f)
|
|
layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
|
|
else layout->row.height = height + item_spacing.y;
|
|
|
|
layout->row.item_offset = 0;
|
|
if (layout->flags & NK_WINDOW_DYNAMIC) {
|
|
/* draw background for dynamic panels */
|
|
struct nk_rect background;
|
|
background.x = win->bounds.x;
|
|
background.w = win->bounds.w;
|
|
background.y = layout->at_y - 1.0f;
|
|
background.h = layout->row.height + 1.0f;
|
|
nk_fill_rect(out, background, 0, color);
|
|
}
|
|
}
|
|
NK_LIB void
|
|
nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
|
|
float height, int cols, int width)
|
|
{
|
|
/* update the current row and set the current row layout */
|
|
struct nk_window *win;
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
nk_panel_layout(ctx, win, height, cols);
|
|
if (fmt == NK_DYNAMIC)
|
|
win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED;
|
|
else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
|
|
|
|
win->layout->row.ratio = 0;
|
|
win->layout->row.filled = 0;
|
|
win->layout->row.item_offset = 0;
|
|
win->layout->row.item_width = (float)width;
|
|
}
|
|
NK_API float
|
|
nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
|
|
{
|
|
struct nk_window *win;
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(pixel_width);
|
|
if (!ctx || !ctx->current || !ctx->current->layout) return 0;
|
|
win = ctx->current;
|
|
return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
|
|
}
|
|
NK_API void
|
|
nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
|
|
{
|
|
nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
|
|
}
|
|
NK_API void
|
|
nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
|
|
{
|
|
nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
|
|
}
|
|
NK_API void
|
|
nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
|
|
float row_height, int cols)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
nk_panel_layout(ctx, win, row_height, cols);
|
|
if (fmt == NK_DYNAMIC)
|
|
layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
|
|
else layout->row.type = NK_LAYOUT_STATIC_ROW;
|
|
|
|
layout->row.ratio = 0;
|
|
layout->row.filled = 0;
|
|
layout->row.item_width = 0;
|
|
layout->row.item_offset = 0;
|
|
layout->row.columns = cols;
|
|
}
|
|
NK_API void
|
|
nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
|
|
if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
|
|
return;
|
|
|
|
if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
|
|
float ratio = ratio_or_width;
|
|
if ((ratio + layout->row.filled) > 1.0f) return;
|
|
if (ratio > 0.0f)
|
|
layout->row.item_width = NK_SATURATE(ratio);
|
|
else layout->row.item_width = 1.0f - layout->row.filled;
|
|
} else layout->row.item_width = ratio_or_width;
|
|
}
|
|
NK_API void
|
|
nk_layout_row_end(struct nk_context *ctx)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
|
|
if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
|
|
return;
|
|
layout->row.item_width = 0;
|
|
layout->row.item_offset = 0;
|
|
}
|
|
NK_API void
|
|
nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
|
|
float height, int cols, const float *ratio)
|
|
{
|
|
int i;
|
|
int n_undef = 0;
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
nk_panel_layout(ctx, win, height, cols);
|
|
if (fmt == NK_DYNAMIC) {
|
|
/* calculate width of undefined widget ratios */
|
|
float r = 0;
|
|
layout->row.ratio = ratio;
|
|
for (i = 0; i < cols; ++i) {
|
|
if (ratio[i] < 0.0f)
|
|
n_undef++;
|
|
else r += ratio[i];
|
|
}
|
|
r = NK_SATURATE(1.0f - r);
|
|
layout->row.type = NK_LAYOUT_DYNAMIC;
|
|
layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
|
|
} else {
|
|
layout->row.ratio = ratio;
|
|
layout->row.type = NK_LAYOUT_STATIC;
|
|
layout->row.item_width = 0;
|
|
layout->row.item_offset = 0;
|
|
}
|
|
layout->row.item_offset = 0;
|
|
layout->row.filled = 0;
|
|
}
|
|
NK_API void
|
|
nk_layout_row_template_begin(struct nk_context *ctx, float height)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
nk_panel_layout(ctx, win, height, 1);
|
|
layout->row.type = NK_LAYOUT_TEMPLATE;
|
|
layout->row.columns = 0;
|
|
layout->row.ratio = 0;
|
|
layout->row.item_width = 0;
|
|
layout->row.item_height = 0;
|
|
layout->row.item_offset = 0;
|
|
layout->row.filled = 0;
|
|
layout->row.item.x = 0;
|
|
layout->row.item.y = 0;
|
|
layout->row.item.w = 0;
|
|
layout->row.item.h = 0;
|
|
}
|
|
NK_API void
|
|
nk_layout_row_template_push_dynamic(struct nk_context *ctx)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
|
|
NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
|
|
if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
|
|
if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
|
|
layout->row.templates[layout->row.columns++] = -1.0f;
|
|
}
|
|
NK_API void
|
|
nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
|
|
NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
|
|
if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
|
|
if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
|
|
layout->row.templates[layout->row.columns++] = -min_width;
|
|
}
|
|
NK_API void
|
|
nk_layout_row_template_push_static(struct nk_context *ctx, float width)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
|
|
NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
|
|
if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
|
|
if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
|
|
layout->row.templates[layout->row.columns++] = width;
|
|
}
|
|
NK_API void
|
|
nk_layout_row_template_end(struct nk_context *ctx)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
int i = 0;
|
|
int variable_count = 0;
|
|
int min_variable_count = 0;
|
|
float min_fixed_width = 0.0f;
|
|
float total_fixed_width = 0.0f;
|
|
float max_variable_width = 0.0f;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
|
|
if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
|
|
for (i = 0; i < layout->row.columns; ++i) {
|
|
float width = layout->row.templates[i];
|
|
if (width >= 0.0f) {
|
|
total_fixed_width += width;
|
|
min_fixed_width += width;
|
|
} else if (width < -1.0f) {
|
|
width = -width;
|
|
total_fixed_width += width;
|
|
max_variable_width = NK_MAX(max_variable_width, width);
|
|
variable_count++;
|
|
} else {
|
|
min_variable_count++;
|
|
variable_count++;
|
|
}
|
|
}
|
|
if (variable_count) {
|
|
float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
|
|
layout->bounds.w, layout->row.columns);
|
|
float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
|
|
int enough_space = var_width >= max_variable_width;
|
|
if (!enough_space)
|
|
var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
|
|
for (i = 0; i < layout->row.columns; ++i) {
|
|
float *width = &layout->row.templates[i];
|
|
*width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
|
|
}
|
|
}
|
|
}
|
|
NK_API void
|
|
nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
|
|
float height, int widget_count)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
nk_panel_layout(ctx, win, height, widget_count);
|
|
if (fmt == NK_STATIC)
|
|
layout->row.type = NK_LAYOUT_STATIC_FREE;
|
|
else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
|
|
|
|
layout->row.ratio = 0;
|
|
layout->row.filled = 0;
|
|
layout->row.item_width = 0;
|
|
layout->row.item_offset = 0;
|
|
}
|
|
NK_API void
|
|
nk_layout_space_end(struct nk_context *ctx)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
layout->row.item_width = 0;
|
|
layout->row.item_height = 0;
|
|
layout->row.item_offset = 0;
|
|
nk_zero(&layout->row.item, sizeof(layout->row.item));
|
|
}
|
|
NK_API void
|
|
nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
layout->row.item = rect;
|
|
}
|
|
NK_API struct nk_rect
|
|
nk_layout_space_bounds(struct nk_context *ctx)
|
|
{
|
|
struct nk_rect ret;
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
|
|
ret.x = layout->clip.x;
|
|
ret.y = layout->clip.y;
|
|
ret.w = layout->clip.w;
|
|
ret.h = layout->row.height;
|
|
return ret;
|
|
}
|
|
NK_API struct nk_rect
|
|
nk_layout_widget_bounds(struct nk_context *ctx)
|
|
{
|
|
struct nk_rect ret;
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
|
|
ret.x = layout->at_x;
|
|
ret.y = layout->at_y;
|
|
ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
|
|
ret.h = layout->row.height;
|
|
return ret;
|
|
}
|
|
NK_API struct nk_vec2
|
|
nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
|
|
ret.x += layout->at_x - (float)*layout->offset_x;
|
|
ret.y += layout->at_y - (float)*layout->offset_y;
|
|
return ret;
|
|
}
|
|
NK_API struct nk_vec2
|
|
nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
|
|
ret.x += -layout->at_x + (float)*layout->offset_x;
|
|
ret.y += -layout->at_y + (float)*layout->offset_y;
|
|
return ret;
|
|
}
|
|
NK_API struct nk_rect
|
|
nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
|
|
ret.x += layout->at_x - (float)*layout->offset_x;
|
|
ret.y += layout->at_y - (float)*layout->offset_y;
|
|
return ret;
|
|
}
|
|
NK_API struct nk_rect
|
|
nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
|
|
ret.x += -layout->at_x + (float)*layout->offset_x;
|
|
ret.y += -layout->at_y + (float)*layout->offset_y;
|
|
return ret;
|
|
}
|
|
NK_LIB void
|
|
nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
|
|
{
|
|
struct nk_panel *layout = win->layout;
|
|
struct nk_vec2 spacing = ctx->style.window.spacing;
|
|
const float row_height = layout->row.height - spacing.y;
|
|
nk_panel_layout(ctx, win, row_height, layout->row.columns);
|
|
}
|
|
NK_LIB void
|
|
nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
|
|
struct nk_window *win, int modify)
|
|
{
|
|
struct nk_panel *layout;
|
|
const struct nk_style *style;
|
|
|
|
struct nk_vec2 spacing;
|
|
struct nk_vec2 padding;
|
|
|
|
float item_offset = 0;
|
|
float item_width = 0;
|
|
float item_spacing = 0;
|
|
float panel_space = 0;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
style = &ctx->style;
|
|
NK_ASSERT(bounds);
|
|
|
|
spacing = style->window.spacing;
|
|
padding = nk_panel_get_padding(style, layout->type);
|
|
panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
|
|
layout->bounds.w, layout->row.columns);
|
|
|
|
#define NK_FRAC(x) (x - (int)x) /* will be used to remove fookin gaps */
|
|
/* calculate the width of one item inside the current layout space */
|
|
switch (layout->row.type) {
|
|
case NK_LAYOUT_DYNAMIC_FIXED: {
|
|
/* scaling fixed size widgets item width */
|
|
float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns;
|
|
item_offset = (float)layout->row.index * w;
|
|
item_width = w + NK_FRAC(item_offset);
|
|
item_spacing = (float)layout->row.index * spacing.x;
|
|
} break;
|
|
case NK_LAYOUT_DYNAMIC_ROW: {
|
|
/* scaling single ratio widget width */
|
|
float w = layout->row.item_width * panel_space;
|
|
item_offset = layout->row.item_offset;
|
|
item_width = w + NK_FRAC(item_offset);
|
|
item_spacing = 0;
|
|
|
|
if (modify) {
|
|
layout->row.item_offset += w + spacing.x;
|
|
layout->row.filled += layout->row.item_width;
|
|
layout->row.index = 0;
|
|
}
|
|
} break;
|
|
case NK_LAYOUT_DYNAMIC_FREE: {
|
|
/* panel width depended free widget placing */
|
|
bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
|
|
bounds->x -= (float)*layout->offset_x;
|
|
bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
|
|
bounds->y -= (float)*layout->offset_y;
|
|
bounds->w = layout->bounds.w * layout->row.item.w + NK_FRAC(bounds->x);
|
|
bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y);
|
|
return;
|
|
}
|
|
case NK_LAYOUT_DYNAMIC: {
|
|
/* scaling arrays of panel width ratios for every widget */
|
|
float ratio, w;
|
|
NK_ASSERT(layout->row.ratio);
|
|
ratio = (layout->row.ratio[layout->row.index] < 0) ?
|
|
layout->row.item_width : layout->row.ratio[layout->row.index];
|
|
|
|
w = (ratio * panel_space);
|
|
item_spacing = (float)layout->row.index * spacing.x;
|
|
item_offset = layout->row.item_offset;
|
|
item_width = w + NK_FRAC(item_offset);
|
|
|
|
if (modify) {
|
|
layout->row.item_offset += w;
|
|
layout->row.filled += ratio;
|
|
}
|
|
} break;
|
|
case NK_LAYOUT_STATIC_FIXED: {
|
|
/* non-scaling fixed widgets item width */
|
|
item_width = layout->row.item_width;
|
|
item_offset = (float)layout->row.index * item_width;
|
|
item_spacing = (float)layout->row.index * spacing.x;
|
|
} break;
|
|
case NK_LAYOUT_STATIC_ROW: {
|
|
/* scaling single ratio widget width */
|
|
item_width = layout->row.item_width;
|
|
item_offset = layout->row.item_offset;
|
|
item_spacing = (float)layout->row.index * spacing.x;
|
|
if (modify) layout->row.item_offset += item_width;
|
|
} break;
|
|
case NK_LAYOUT_STATIC_FREE: {
|
|
/* free widget placing */
|
|
bounds->x = layout->at_x + layout->row.item.x;
|
|
bounds->w = layout->row.item.w;
|
|
if (((bounds->x + bounds->w) > layout->max_x) && modify)
|
|
layout->max_x = (bounds->x + bounds->w);
|
|
bounds->x -= (float)*layout->offset_x;
|
|
bounds->y = layout->at_y + layout->row.item.y;
|
|
bounds->y -= (float)*layout->offset_y;
|
|
bounds->h = layout->row.item.h;
|
|
return;
|
|
}
|
|
case NK_LAYOUT_STATIC: {
|
|
/* non-scaling array of panel pixel width for every widget */
|
|
item_spacing = (float)layout->row.index * spacing.x;
|
|
item_width = layout->row.ratio[layout->row.index];
|
|
item_offset = layout->row.item_offset;
|
|
if (modify) layout->row.item_offset += item_width;
|
|
} break;
|
|
case NK_LAYOUT_TEMPLATE: {
|
|
/* stretchy row layout with combined dynamic/static widget width*/
|
|
float w;
|
|
NK_ASSERT(layout->row.index < layout->row.columns);
|
|
NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
|
|
w = layout->row.templates[layout->row.index];
|
|
item_offset = layout->row.item_offset;
|
|
item_width = w + NK_FRAC(item_offset);
|
|
item_spacing = (float)layout->row.index * spacing.x;
|
|
if (modify) layout->row.item_offset += w;
|
|
} break;
|
|
#undef NK_FRAC
|
|
default: NK_ASSERT(0); break;
|
|
};
|
|
|
|
/* set the bounds of the newly allocated widget */
|
|
bounds->w = item_width;
|
|
bounds->h = layout->row.height - spacing.y;
|
|
bounds->y = layout->at_y - (float)*layout->offset_y;
|
|
bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
|
|
if (((bounds->x + bounds->w) > layout->max_x) && modify)
|
|
layout->max_x = bounds->x + bounds->w;
|
|
bounds->x -= (float)*layout->offset_x;
|
|
}
|
|
NK_LIB void
|
|
nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
|
|
{
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
/* check if the end of the row has been hit and begin new row if so */
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
if (layout->row.index >= layout->row.columns)
|
|
nk_panel_alloc_row(ctx, win);
|
|
|
|
/* calculate widget position and size */
|
|
nk_layout_widget_space(bounds, ctx, win, nk_true);
|
|
layout->row.index++;
|
|
}
|
|
NK_LIB void
|
|
nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
|
|
{
|
|
float y;
|
|
int index;
|
|
struct nk_window *win;
|
|
struct nk_panel *layout;
|
|
|
|
NK_ASSERT(ctx);
|
|
NK_ASSERT(ctx->current);
|
|
NK_ASSERT(ctx->current->layout);
|
|
if (!ctx || !ctx->current || !ctx->current->layout)
|
|
return;
|
|
|
|
win = ctx->current;
|
|
layout = win->layout;
|
|
y = layout->at_y;
|
|
index = layout->row.index;
|
|
if (layout->row.index >= layout->row.columns) {
|
|
layout->at_y += layout->row.height;
|
|
layout->row.index = 0;
|
|
}
|
|
nk_layout_widget_space(bounds, ctx, win, nk_false);
|
|
if (!layout->row.index) {
|
|
bounds->x -= layout->row.item_offset;
|
|
}
|
|
layout->at_y = y;
|
|
layout->row.index = index;
|
|
}
|
|
|