added tiled layout for widget and windows
This commit is contained in:
parent
8a7f19fef3
commit
fc8969dfd5
12
Readme.md
12
Readme.md
@ -14,7 +14,7 @@ application and does not have any direct dependencies.
|
||||
- No direct dependencies (not even libc!)
|
||||
- Configurable style and colors
|
||||
- UTF-8 support
|
||||
- Optional vertex output
|
||||
- Optional vertex buffer output
|
||||
|
||||
## Gallery
|
||||
![gui demo](/screen/demo.png?raw=true)
|
||||
@ -23,11 +23,6 @@ application and does not have any direct dependencies.
|
||||
|
||||
## Example
|
||||
```c
|
||||
/* allocate memory to hold the draw commands */
|
||||
struct gui_command_queue queue;
|
||||
void *memory = malloc(MEMORY_SIZE);
|
||||
gui_command_queue_init_fixed(&queue, memory, MEMORY_SIZE);
|
||||
|
||||
/* setup configuration */
|
||||
struct gui_font font;
|
||||
struct gui_style style;
|
||||
@ -36,6 +31,11 @@ font.height = your_font_data.height;
|
||||
font.width = your_font_string_width_callback_function;
|
||||
gui_style_default(&style, GUI_DEFAULT_ALL, &font);
|
||||
|
||||
/* allocate memory to hold draw commands */
|
||||
struct gui_command_queue queue;
|
||||
void *memory = malloc(MEMORY_SIZE);
|
||||
gui_command_queue_init_fixed(&queue, memory, MEMORY_SIZE);
|
||||
|
||||
/* initialize panel */
|
||||
struct gui_window panel;
|
||||
gui_window_init(&panel, 50, 50, 220, 180,
|
||||
|
46
demo/demo.c
46
demo/demo.c
@ -289,10 +289,11 @@ color_picker(struct gui_context *panel, struct color_picker* control,
|
||||
iter = &control->color.r;
|
||||
gui_layout_row_dynamic(&popup, 30, 2);
|
||||
for (i = 0; i < 4; ++i, iter++) {
|
||||
gui_float t = *iter;
|
||||
gui_float t;
|
||||
*iter = (gui_byte)gui_spinner(&popup, 0, *iter, 255, 1, NULL);
|
||||
t = *iter;
|
||||
t = gui_slider(&popup, 0, t, 255, 10);
|
||||
*iter = (gui_byte)t;
|
||||
*iter = (gui_byte)gui_spinner(&popup, 0, *iter, 255, 1, NULL);
|
||||
}
|
||||
|
||||
gui_layout_row_dynamic(&popup, 30, 3);
|
||||
@ -444,6 +445,7 @@ struct state {
|
||||
struct test_tree test;
|
||||
|
||||
/* widgets state */
|
||||
gui_bool list[4];
|
||||
gui_size prog_values[4];
|
||||
gui_bool check_values[WEAPON_MAX];
|
||||
gui_bool scaleable;
|
||||
@ -528,7 +530,7 @@ widget_panel(struct gui_context *panel, struct state *demo)
|
||||
/* custom row layout by array */
|
||||
const gui_float ratio[] = {0.8f, 0.2f};
|
||||
const gui_float pixel[] = {150.0f, 30.0f};
|
||||
enum gui_row_layout_format fmt = (demo->scaleable) ? GUI_DYNAMIC : GUI_STATIC;
|
||||
enum gui_layout_format fmt = (demo->scaleable) ? GUI_DYNAMIC : GUI_STATIC;
|
||||
gui_layout_row(panel, fmt, 30, 2, (fmt == GUI_DYNAMIC) ? ratio: pixel);
|
||||
demo->slider = gui_slider(panel, 0, demo->slider, 10, 1.0f);
|
||||
gui_labelf(panel, GUI_TEXT_LEFT, "%.2f", demo->slider);
|
||||
@ -536,8 +538,41 @@ widget_panel(struct gui_context *panel, struct state *demo)
|
||||
gui_labelf(panel, GUI_TEXT_LEFT, "%lu", demo->progressbar);
|
||||
}
|
||||
|
||||
{
|
||||
/* tiled widgets layout */
|
||||
gui_uint i = 0;
|
||||
struct gui_tiled_layout tiled;
|
||||
const char *items[] = {"item0", "item1", "item2", "item3"};
|
||||
enum gui_layout_format fmt = (demo->scaleable) ? GUI_DYNAMIC : GUI_STATIC;
|
||||
|
||||
/* setup tiled layout */
|
||||
gui_tiled_begin(&tiled, fmt, 300, 150);
|
||||
if (!demo->scaleable) {
|
||||
gui_tiled_slot(&tiled, GUI_SLOT_LEFT, 150, GUI_SLOT_VERTICAL, 4);
|
||||
gui_tiled_slot(&tiled, GUI_SLOT_RIGHT, 150, GUI_SLOT_VERTICAL, 4);
|
||||
} else {
|
||||
gui_tiled_slot(&tiled, GUI_SLOT_LEFT, 0.50, GUI_SLOT_VERTICAL, 4);
|
||||
gui_tiled_slot(&tiled, GUI_SLOT_RIGHT, 0.50, GUI_SLOT_VERTICAL, 4);
|
||||
}
|
||||
gui_tiled_end(&tiled);
|
||||
|
||||
/* setup widgets with tiled layout */
|
||||
gui_layout_row_tiled_begin(panel, &tiled);
|
||||
{
|
||||
for (i = 0; i < 4; ++i) {
|
||||
gui_layout_row_tiled_push(panel, GUI_SLOT_LEFT, i);
|
||||
demo->list[i] = gui_button_toggle(panel, items[i], demo->list[i]);
|
||||
}
|
||||
gui_layout_row_tiled_push(panel, GUI_SLOT_RIGHT, 1);
|
||||
gui_label(panel, "Test0", GUI_TEXT_CENTERED);
|
||||
gui_layout_row_tiled_push(panel, GUI_SLOT_RIGHT, 2);
|
||||
gui_label(panel, "Test1", GUI_TEXT_CENTERED);
|
||||
}
|
||||
gui_layout_row_tiled_end(panel);
|
||||
}
|
||||
|
||||
/* item selection */
|
||||
if (!demo->scaleable) gui_layout_row_static(panel, 30, 150, 1);
|
||||
if (!demo->scaleable) gui_layout_row_static(panel, 30, 30, 1);
|
||||
else gui_layout_row_dynamic(panel, 30, 1);
|
||||
demo->spinner = gui_spinner(panel, 0, demo->spinner, 250, 10, &demo->spinner_active);
|
||||
|
||||
@ -551,7 +586,7 @@ widget_panel(struct gui_context *panel, struct state *demo)
|
||||
|
||||
{
|
||||
/* immediate mode custom row layout */
|
||||
enum gui_row_layout_format fmt = (demo->scaleable) ? GUI_DYNAMIC : GUI_STATIC;
|
||||
enum gui_layout_format fmt = (demo->scaleable) ? GUI_DYNAMIC : GUI_STATIC;
|
||||
gui_layout_row_begin(panel, fmt, 30, 2);
|
||||
{
|
||||
gui_layout_row_push(panel,(fmt == GUI_DYNAMIC) ? 0.7f : 100);
|
||||
@ -705,6 +740,7 @@ init_demo(struct demo_gui *gui)
|
||||
win->slider = 2.0f;
|
||||
win->progressbar = 50;
|
||||
win->spinner = 100;
|
||||
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
|
280
gui.c
280
gui.c
@ -3826,7 +3826,6 @@ gui_widget_spinner_base(struct gui_command_buffer *out, struct gui_rect r,
|
||||
bounds.h = r.h / 2;
|
||||
bounds.w = r.h - s->padding.x;
|
||||
bounds.x = r.x + r.w - bounds.w;
|
||||
|
||||
button_up_clicked = gui_widget_button_symbol(out, bounds, GUI_SYMBOL_TRIANGLE_UP,
|
||||
GUI_BUTTON_DEFAULT, &s->button, in, font);
|
||||
if (button_up_clicked) ret = 1;
|
||||
@ -4089,7 +4088,124 @@ gui_style_reset(struct gui_style *style)
|
||||
gui_style_reset_colors(style);
|
||||
gui_style_reset_properties(style);
|
||||
}
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* Tiling
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
void
|
||||
gui_tiled_begin(struct gui_tiled_layout *layout, enum gui_layout_format fmt,
|
||||
gui_float width, gui_float height)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout) return;
|
||||
gui_zero(layout->slots, sizeof(layout->slots));
|
||||
layout->fmt = fmt;
|
||||
layout->width = width;
|
||||
layout->height = height;
|
||||
}
|
||||
|
||||
void
|
||||
gui_tiled_slot(struct gui_tiled_layout *layout,
|
||||
enum gui_tiled_layout_slot_index slot, gui_float ratio,
|
||||
enum gui_tiled_slot_format fmt, gui_uint widget_count)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout) return;
|
||||
layout->slots[slot].capacity = widget_count;
|
||||
layout->slots[slot].format = fmt;
|
||||
layout->slots[slot].value = ratio;
|
||||
}
|
||||
|
||||
void
|
||||
gui_tiled_slot_bounds(struct gui_rect *bounds,
|
||||
const struct gui_tiled_layout *layout, enum gui_tiled_layout_slot_index slot)
|
||||
{
|
||||
gui_float width, height;
|
||||
const struct gui_tiled_slot *s;
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout) return;
|
||||
|
||||
s = &layout->slots[slot];
|
||||
if (layout->fmt == GUI_DYNAMIC) {
|
||||
bounds->x = s->pos.x * (gui_float)layout->width;
|
||||
bounds->y = s->pos.y * (gui_float)layout->height;
|
||||
bounds->w = s->size.x * (gui_float)layout->width;
|
||||
bounds->h = s->size.y * (gui_float)layout->height;
|
||||
} else {
|
||||
bounds->x = s->pos.x;
|
||||
bounds->y = s->pos.y;
|
||||
bounds->w = s->size.x;
|
||||
bounds->h = s->size.y;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gui_tiled_bounds(struct gui_rect *bounds, const struct gui_tiled_layout *layout,
|
||||
enum gui_tiled_layout_slot_index slot, gui_uint index)
|
||||
{
|
||||
struct gui_rect slot_bounds;
|
||||
const struct gui_tiled_slot *s;
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout) return;
|
||||
|
||||
GUI_ASSERT(slot < GUI_SLOT_MAX);
|
||||
s = &layout->slots[slot];
|
||||
GUI_ASSERT(index < s->capacity);
|
||||
gui_tiled_slot_bounds(&slot_bounds, layout, slot);
|
||||
if (s->format == GUI_SLOT_HORIZONTAL) {
|
||||
bounds->h = slot_bounds.h;
|
||||
bounds->y = slot_bounds.y;
|
||||
bounds->w = slot_bounds.w / (gui_float)s->capacity;
|
||||
bounds->x = slot_bounds.x + (gui_float)index * bounds->w;
|
||||
} else {
|
||||
bounds->x = slot_bounds.x;
|
||||
bounds->w = slot_bounds.w;
|
||||
bounds->h = slot_bounds.h/(gui_float)s->capacity;
|
||||
bounds->y = slot_bounds.y + (gui_float)index * bounds->h;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gui_tiled_end(struct gui_tiled_layout *layout)
|
||||
{
|
||||
gui_float w;
|
||||
gui_float centerh, centerv;
|
||||
const struct gui_tiled_slot *top, *bottom;
|
||||
const struct gui_tiled_slot *left, *right;
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout) return;
|
||||
|
||||
top = &layout->slots[GUI_SLOT_TOP];
|
||||
bottom = &layout->slots[GUI_SLOT_BOTTOM];
|
||||
left = &layout->slots[GUI_SLOT_LEFT];
|
||||
right = &layout->slots[GUI_SLOT_RIGHT];
|
||||
|
||||
if (layout->fmt == GUI_DYNAMIC) {
|
||||
layout->width = 1.0f;
|
||||
centerh = MAX(0.0f, 1.0f - (left->value + right->value));
|
||||
centerv = MAX(0.0f, 1.0f - (top->value + bottom->value));
|
||||
} else {
|
||||
centerh = MAX(0.0f, layout->width - (left->value + right->value));
|
||||
centerv = MAX(0.0f, layout->height - (top->value + bottom->value));
|
||||
}
|
||||
|
||||
/* calculate the slot size */
|
||||
layout->slots[GUI_SLOT_CENTER].size = gui_vec2(centerh, centerv);
|
||||
layout->slots[GUI_SLOT_TOP].size = gui_vec2(layout->width, top->value);
|
||||
layout->slots[GUI_SLOT_LEFT].size = gui_vec2(left->value, centerv);
|
||||
layout->slots[GUI_SLOT_BOTTOM].size = gui_vec2(layout->width, bottom->value);
|
||||
layout->slots[GUI_SLOT_RIGHT].size = gui_vec2(right->value, centerv);
|
||||
|
||||
/* calculate the slot window position */
|
||||
layout->slots[GUI_SLOT_TOP].pos = gui_vec2(0.0f, 0.0f);
|
||||
layout->slots[GUI_SLOT_LEFT].pos = gui_vec2(0.0f, top->value);
|
||||
layout->slots[GUI_SLOT_BOTTOM].pos = gui_vec2(0.0f, top->value + centerv);
|
||||
layout->slots[GUI_SLOT_RIGHT].pos = gui_vec2(left->value + centerh, top->value);
|
||||
layout->slots[GUI_SLOT_CENTER].pos = gui_vec2(left->value, top->value);
|
||||
}
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
@ -4222,7 +4338,7 @@ gui_window_is_minimized(struct gui_window *panel)
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* Window
|
||||
* Context
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
@ -4381,6 +4497,31 @@ gui_begin(struct gui_context *context, struct gui_window *window)
|
||||
gui_command_buffer_push_scissor(out, context->clip);
|
||||
}
|
||||
|
||||
void
|
||||
gui_begin_tiled(struct gui_context *context, struct gui_window *window,
|
||||
struct gui_tiled_layout *tiled, enum gui_tiled_layout_slot_index slot,
|
||||
gui_uint index)
|
||||
{
|
||||
struct gui_command_queue *queue;
|
||||
GUI_ASSERT(context);
|
||||
GUI_ASSERT(window);
|
||||
GUI_ASSERT(tiled);
|
||||
GUI_ASSERT(slot < GUI_SLOT_MAX);
|
||||
GUI_ASSERT(index < tiled->slots[slot].capacity);
|
||||
if (!context || !window || !tiled) return;
|
||||
|
||||
/* make sure that correct flags are set */
|
||||
window->flags &= (gui_flags)~GUI_WINDOW_MOVEABLE;
|
||||
window->flags &= (gui_flags)~GUI_WINDOW_SCALEABLE;
|
||||
window->flags &= (gui_flags)~GUI_WINDOW_DYNAMIC;
|
||||
|
||||
/* place window inside layout and set window to background */
|
||||
gui_tiled_bounds(&window->bounds, tiled, slot, index);
|
||||
gui_begin(context, window);
|
||||
gui_command_queue_remove(window->queue, &window->buffer);
|
||||
gui_command_queue_insert_front(window->queue, &window->buffer);
|
||||
}
|
||||
|
||||
void
|
||||
gui_end(struct gui_context *layout, struct gui_window *window)
|
||||
{
|
||||
@ -4740,10 +4881,10 @@ gui_header_button(struct gui_context *layout,
|
||||
|
||||
/* check if the icon has been pressed */
|
||||
if (!(layout->flags & GUI_WINDOW_ROM)) {
|
||||
gui_float clicked_x = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.x;
|
||||
gui_float clicked_y = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.y;
|
||||
gui_float mouse_x = layout->input->mouse.pos.x;
|
||||
gui_float mouse_y = layout->input->mouse.pos.y;
|
||||
gui_float clicked_x = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.x;
|
||||
gui_float clicked_y = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.y;
|
||||
if (GUI_INBOX(mouse_x, mouse_y, sym.x, sym.y, sym_bw, sym.h)) {
|
||||
if (GUI_INBOX(clicked_x, clicked_y, sym.x, sym.y, sym_bw, sym.h))
|
||||
ret = (layout->input->mouse.buttons[GUI_BUTTON_LEFT].down &&
|
||||
@ -4883,7 +5024,6 @@ gui_header(struct gui_context *layout, const char *title,
|
||||
{
|
||||
gui_flags ret = 0;
|
||||
gui_flags old = layout->flags;
|
||||
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout || layout->flags & GUI_WINDOW_HIDDEN)
|
||||
return gui_false;
|
||||
@ -4957,7 +5097,6 @@ gui_menubar_end(struct gui_context *layout)
|
||||
layout->clip.h -= (panel_padding.y + item_padding.y);
|
||||
gui_command_buffer_push_scissor(out, layout->clip);
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
@ -5001,7 +5140,7 @@ gui_panel_layout(struct gui_context *layout, gui_float height, gui_size cols)
|
||||
|
||||
static void
|
||||
gui_row_layout(struct gui_context *layout,
|
||||
enum gui_row_layout_format fmt, gui_float height, gui_size cols,
|
||||
enum gui_layout_format fmt, gui_float height, gui_size cols,
|
||||
gui_size width)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
@ -5034,7 +5173,7 @@ gui_layout_row_static(struct gui_context *layout, gui_float height,
|
||||
|
||||
void
|
||||
gui_layout_row_begin(struct gui_context *layout,
|
||||
enum gui_row_layout_format fmt, gui_float row_height, gui_size cols)
|
||||
enum gui_layout_format fmt, gui_float row_height, gui_size cols)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
GUI_ASSERT(layout->style);
|
||||
@ -5082,7 +5221,7 @@ gui_layout_row_end(struct gui_context *layout)
|
||||
}
|
||||
|
||||
void
|
||||
gui_layout_row(struct gui_context *layout, enum gui_row_layout_format fmt,
|
||||
gui_layout_row(struct gui_context *layout, enum gui_layout_format fmt,
|
||||
gui_float height, gui_size cols, const gui_float *ratio)
|
||||
{
|
||||
gui_size i;
|
||||
@ -5121,7 +5260,7 @@ gui_layout_row(struct gui_context *layout, enum gui_row_layout_format fmt,
|
||||
|
||||
void
|
||||
gui_layout_row_space_begin(struct gui_context *layout,
|
||||
enum gui_row_layout_format fmt, gui_float height, gui_size widget_count)
|
||||
enum gui_layout_format fmt, gui_float height, gui_size widget_count)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
GUI_ASSERT(layout->style);
|
||||
@ -5223,10 +5362,107 @@ gui_layout_row_space_end(struct gui_context *layout)
|
||||
layout->row.item_width = 0;
|
||||
layout->row.item_height = 0;
|
||||
layout->row.item_offset = 0;
|
||||
gui_zero(&layout->row.item, sizeof(layout->row.item));
|
||||
if (layout->row.type == GUI_LAYOUT_STATIC_FREE)
|
||||
gui_command_buffer_push_scissor(layout->buffer, layout->clip);
|
||||
}
|
||||
|
||||
void
|
||||
gui_layout_row_tiled_begin(struct gui_context *layout,
|
||||
struct gui_tiled_layout *tiled)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout) return;
|
||||
if (!layout->valid) return;
|
||||
|
||||
layout->row.tiled = tiled;
|
||||
gui_panel_layout(layout, (gui_size)tiled->height, 2);
|
||||
if (tiled->fmt == GUI_STATIC) {
|
||||
/* calculate bounds of the tiled layout */
|
||||
struct gui_rect clip, space;
|
||||
space.x = layout->at_x;
|
||||
space.y = layout->at_y;
|
||||
space.w = layout->width;
|
||||
space.h = layout->row.height;
|
||||
|
||||
/* setup clipping rect for the free space to prevent overdraw */
|
||||
gui_unify(&clip, &layout->clip, space.x, space.y, space.x + space.w, space.y + space.h);
|
||||
gui_command_buffer_push_scissor(layout->buffer, clip);
|
||||
layout->row.clip = layout->clip;
|
||||
layout->clip = clip;
|
||||
layout->row.type = GUI_LAYOUT_STATIC_TILED;
|
||||
} else layout->row.type = GUI_LAYOUT_DYNAMIC_TILED;
|
||||
|
||||
layout->row.ratio = 0;
|
||||
layout->row.item_width = 0;
|
||||
layout->row.item_offset = 0;
|
||||
layout->row.filled = 0;
|
||||
}
|
||||
|
||||
void
|
||||
gui_layout_row_tiled_push(struct gui_context *layout,
|
||||
enum gui_tiled_layout_slot_index slot, gui_uint index)
|
||||
{
|
||||
struct gui_rect slot_bounds;
|
||||
const struct gui_tiled_slot *s;
|
||||
struct gui_vec2 spacing;
|
||||
const struct gui_style *config;
|
||||
struct gui_tiled_layout *tiled;
|
||||
|
||||
GUI_ASSERT(layout);
|
||||
GUI_ASSERT(layout->style);
|
||||
GUI_ASSERT(layout->buffer);
|
||||
GUI_ASSERT(layout->row.tiled);
|
||||
if (!layout) return;
|
||||
if (!layout->valid) return;
|
||||
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout) return;
|
||||
|
||||
tiled = layout->row.tiled;
|
||||
s = &tiled->slots[slot];
|
||||
GUI_ASSERT(index < s->capacity);
|
||||
|
||||
if (tiled->fmt == GUI_DYNAMIC)
|
||||
tiled->width = layout->width;
|
||||
gui_tiled_slot_bounds(&slot_bounds, tiled, slot);
|
||||
|
||||
config = layout->style;
|
||||
spacing = config->properties[GUI_PROPERTY_ITEM_SPACING];
|
||||
if (s->format == GUI_SLOT_HORIZONTAL) {
|
||||
slot_bounds.h -= (2 * spacing.y);
|
||||
slot_bounds.w -= s->capacity * spacing.x;
|
||||
|
||||
layout->row.item.h = slot_bounds.h;
|
||||
layout->row.item.y = slot_bounds.y;
|
||||
layout->row.item.w = slot_bounds.w / (gui_float)s->capacity;
|
||||
layout->row.item.x = slot_bounds.x + (gui_float)index * layout->row.item.w;
|
||||
} else {
|
||||
layout->row.item.x = slot_bounds.x + spacing.x;
|
||||
layout->row.item.w = slot_bounds.w - (2 * spacing.x);
|
||||
layout->row.item.h = (slot_bounds.h - s->capacity * spacing.y)/(gui_float)s->capacity;
|
||||
layout->row.item.y = slot_bounds.y + (gui_float)index * layout->row.item.h;
|
||||
layout->row.item.y += (index * spacing.y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gui_layout_row_tiled_end(struct gui_context *layout)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
GUI_ASSERT(layout->style);
|
||||
if (!layout) return;
|
||||
if (!layout->valid) return;
|
||||
|
||||
layout->row.item_width = 0;
|
||||
layout->row.item_height = 0;
|
||||
layout->row.item_offset = 0;
|
||||
gui_zero(&layout->row.item, sizeof(layout->row.item));
|
||||
if (layout->row.tiled->fmt == GUI_STATIC)
|
||||
gui_command_buffer_push_scissor(layout->buffer, layout->clip);
|
||||
layout->row.tiled = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gui_panel_alloc_row(struct gui_context *layout)
|
||||
{
|
||||
@ -5283,8 +5519,21 @@ gui_panel_alloc_space(struct gui_rect *bounds, struct gui_context *layout)
|
||||
layout->row.filled += layout->row.item_width;
|
||||
layout->row.index = 0;
|
||||
} break;
|
||||
case GUI_LAYOUT_DYNAMIC_TILED: {
|
||||
/* dynamic tiled layout widget placing */
|
||||
bounds->x = layout->at_x + layout->row.item.x + padding.x;
|
||||
bounds->x -= layout->offset.x;
|
||||
bounds->y = layout->at_y + layout->row.item.y;
|
||||
bounds->y -= layout->offset.y;
|
||||
bounds->w = layout->row.item.w;
|
||||
bounds->h = layout->row.item.h;
|
||||
layout->row.index = 0;
|
||||
if ((bounds->x + bounds->w) > layout->max_x)
|
||||
layout->max_x = bounds->x + bounds->w;
|
||||
return;
|
||||
} break;
|
||||
case GUI_LAYOUT_DYNAMIC_FREE: {
|
||||
/*panel width depended free widget placing */
|
||||
/* panel width depended free widget placing */
|
||||
bounds->x = layout->at_x + (layout->width * layout->row.item.x);
|
||||
bounds->x -= layout->offset.x;
|
||||
bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
|
||||
@ -5322,6 +5571,9 @@ gui_panel_alloc_space(struct gui_rect *bounds, struct gui_context *layout)
|
||||
layout->row.item_offset += item_width + spacing.x;
|
||||
layout->row.index = 0;
|
||||
} break;
|
||||
case GUI_LAYOUT_STATIC_TILED:
|
||||
/* static tiled layout widget placing */
|
||||
layout->row.index = 0;
|
||||
case GUI_LAYOUT_STATIC_FREE: {
|
||||
/* free widget placing */
|
||||
bounds->x = layout->clip.x + layout->row.item.x;
|
||||
@ -5428,10 +5680,10 @@ gui_layout_push(struct gui_context *layout,
|
||||
|
||||
/* update node state */
|
||||
if (!(layout->flags & GUI_WINDOW_ROM)) {
|
||||
gui_float clicked_x = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.x;
|
||||
gui_float clicked_y = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.y;
|
||||
gui_float mouse_x = layout->input->mouse.pos.x;
|
||||
gui_float mouse_y = layout->input->mouse.pos.y;
|
||||
gui_float clicked_x = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.x;
|
||||
gui_float clicked_y = layout->input->mouse.buttons[GUI_BUTTON_LEFT].clicked_pos.y;
|
||||
if (GUI_INBOX(mouse_x, mouse_y, sym.x, sym.y, sym.w, sym.h)) {
|
||||
if (GUI_INBOX(clicked_x, clicked_y, sym.x, sym.y, sym.w, sym.h)) {
|
||||
if (layout->input->mouse.buttons[GUI_BUTTON_LEFT].down &&
|
||||
@ -5479,7 +5731,6 @@ gui_layout_pop(struct gui_context *layout)
|
||||
layout->at_x -= panel_padding.x;
|
||||
layout->width += 2 * panel_padding.x;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
@ -7248,3 +7499,4 @@ gui_shelf_end(struct gui_context *p, struct gui_context *s)
|
||||
return pan.offset;
|
||||
}
|
||||
|
||||
|
||||
|
188
gui.h
188
gui.h
@ -2234,6 +2234,103 @@ void gui_style_reset(struct gui_style*);
|
||||
Input:
|
||||
- Configuration structure to pop the change from and to
|
||||
*/
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* Tiling
|
||||
*
|
||||
* ===============================================================
|
||||
TILING
|
||||
|
||||
tiling API
|
||||
----------------------------
|
||||
gui_tiled_begin -- starts the definition of a tiled layout
|
||||
gui_tiled_slot_bounds -- returns the bounds of a slot in the tiled layout
|
||||
gui_tiled_bounds -- returns the bounds of a widget in the tiled layout
|
||||
gui_tiled_slot -- activates and setups a slot inside the tile layout
|
||||
gui_tiled_end -- ends the definiition of the tiled layout slots
|
||||
*/
|
||||
enum gui_tiled_layout_slot_index {
|
||||
GUI_SLOT_TOP,
|
||||
GUI_SLOT_BOTTOM,
|
||||
GUI_SLOT_LEFT,
|
||||
GUI_SLOT_CENTER,
|
||||
GUI_SLOT_RIGHT,
|
||||
GUI_SLOT_MAX
|
||||
};
|
||||
|
||||
enum gui_layout_format {
|
||||
GUI_DYNAMIC, /* row layout which scales with the window */
|
||||
GUI_STATIC /* row layout with fixed pixel width */
|
||||
};
|
||||
|
||||
enum gui_tiled_slot_format {
|
||||
GUI_SLOT_HORIZONTAL,
|
||||
/* widgets in slots are added left to right */
|
||||
GUI_SLOT_VERTICAL
|
||||
/* widgets in slots are added top to bottom */
|
||||
};
|
||||
|
||||
struct gui_tiled_slot {
|
||||
gui_uint capacity;
|
||||
/* number of widget inside the slot */
|
||||
gui_float value;
|
||||
/* temp value for layout build up */
|
||||
struct gui_vec2 size;
|
||||
/* horizontal and vertical window (ratio/width) */
|
||||
struct gui_vec2 pos;
|
||||
/* position of the slot in the window */
|
||||
enum gui_tiled_slot_format format;
|
||||
/* layout filling format */
|
||||
};
|
||||
|
||||
struct gui_tiled_layout {
|
||||
struct gui_tiled_slot slots[GUI_SLOT_MAX];
|
||||
/* tiled layout slots */
|
||||
enum gui_layout_format fmt;
|
||||
/* row layout format */
|
||||
gui_float width, height;
|
||||
/* width/height of the layout */
|
||||
};
|
||||
|
||||
void gui_tiled_begin(struct gui_tiled_layout*, enum gui_layout_format,
|
||||
gui_float width, gui_float height);
|
||||
/* this functions begins the definitions of a tiled layout
|
||||
Input:
|
||||
- layout format with either dynamic ratio based or fixed pixel based slots
|
||||
- pixel width of the tiled layout space
|
||||
- pixel height of the tiled layout space
|
||||
*/
|
||||
void gui_tiled_slot_bounds(struct gui_rect*, const struct gui_tiled_layout*,
|
||||
enum gui_tiled_layout_slot_index);
|
||||
/* this functions queries the bounds (position + size) of a tiled layout slot
|
||||
Input:
|
||||
- slot identifier
|
||||
Output:
|
||||
- rectangle with position and size of the slot
|
||||
*/
|
||||
void gui_tiled_bounds(struct gui_rect*, const struct gui_tiled_layout*,
|
||||
enum gui_tiled_layout_slot_index, gui_uint);
|
||||
/* this functions queries the bounds (position + size) of a tiled layout slot entry
|
||||
Input:
|
||||
- slot identifier
|
||||
- index of the widget inside the slot
|
||||
Output:
|
||||
- rectangle with position and size of the slot entry
|
||||
*/
|
||||
void gui_tiled_slot(struct gui_tiled_layout *layout,
|
||||
enum gui_tiled_layout_slot_index, gui_float ratio,
|
||||
enum gui_tiled_slot_format, gui_uint widget_count);
|
||||
/* this functions defines a slot in the tiled layout which then can be filled
|
||||
* with widgets
|
||||
Input:
|
||||
- slot identifier
|
||||
- either ratio or pixel size of the slot
|
||||
- slot filling format with either horizontal or vertical filling
|
||||
- number of widgets inside the slot
|
||||
*/
|
||||
void gui_tiled_end(struct gui_tiled_layout*);
|
||||
/* this functions ends the definitions of the tiled layout slots */
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
@ -2433,6 +2530,8 @@ enum gui_row_layout_type {
|
||||
/* immediate mode widget specific widget width ratio layout */
|
||||
GUI_LAYOUT_DYNAMIC_FREE,
|
||||
/* free ratio based placing of widget in a local space */
|
||||
GUI_LAYOUT_DYNAMIC_TILED,
|
||||
/* dynamic Border layout */
|
||||
GUI_LAYOUT_DYNAMIC,
|
||||
/* retain mode widget specific widget ratio width*/
|
||||
GUI_LAYOUT_STATIC_FIXED,
|
||||
@ -2441,17 +2540,12 @@ enum gui_row_layout_type {
|
||||
/* immediate mode widget specific widget pixel width layout */
|
||||
GUI_LAYOUT_STATIC_FREE,
|
||||
/* free pixel based placing of widget in a local space */
|
||||
GUI_LAYOUT_STATIC_TILED,
|
||||
/* static Border layout */
|
||||
GUI_LAYOUT_STATIC
|
||||
/* retain mode widget specific widget pixel width layout */
|
||||
};
|
||||
|
||||
enum gui_layout_node_type {
|
||||
GUI_LAYOUT_NODE,
|
||||
/* a node is a space which can be minimized or maximized */
|
||||
GUI_LAYOUT_TAB
|
||||
/* a tab is a node with a header */
|
||||
};
|
||||
|
||||
#define GUI_UNDEFINED (-1.0f)
|
||||
struct gui_row_layout {
|
||||
enum gui_row_layout_type type;
|
||||
@ -2474,6 +2568,8 @@ struct gui_row_layout {
|
||||
/* item bounds */
|
||||
struct gui_rect clip;
|
||||
/* temporary clipping rect */
|
||||
struct gui_tiled_layout *tiled;
|
||||
/* tiled border layout */
|
||||
};
|
||||
|
||||
struct gui_header {
|
||||
@ -2524,7 +2620,16 @@ struct gui_context {
|
||||
};
|
||||
|
||||
void gui_begin(struct gui_context*, struct gui_window*);
|
||||
/* this function begins the window build up process by creating context to fill
|
||||
/* this function begins the window build up process by creating a context to fill
|
||||
Input:
|
||||
- input structure holding all user generated state changes
|
||||
Output:
|
||||
- window context to fill up with widgets
|
||||
*/
|
||||
void gui_begin_tiled(struct gui_context*, struct gui_window*, struct gui_tiled_layout*,
|
||||
enum gui_tiled_layout_slot_index slot, gui_uint index);
|
||||
/* this function begins the window build up process by creating a context to fill
|
||||
and placing the window inside a tiled layout on the screen.
|
||||
Input:
|
||||
- input structure holding all user generated state changes
|
||||
Output:
|
||||
@ -2654,13 +2759,14 @@ void gui_menubar_begin(struct gui_context*);
|
||||
/* this function begins the window menubar build up process */
|
||||
void gui_menubar_end(struct gui_context*);
|
||||
/* this function ends the window menubar build up process */
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
* LAYOUT
|
||||
* Layout
|
||||
* --------------------------------------------------------------
|
||||
LAYOUT
|
||||
The layout API is for positioning of widget inside a window context. In general there
|
||||
are three different ways to position widget. The first one is a table with
|
||||
are four different ways to position widget. The first one is a table with
|
||||
fixed size columns. This like the other three comes in two flavors. First
|
||||
the scaleable width as a ratio of the window width and the other is a
|
||||
non-scaleable fixed pixel value for static windows.
|
||||
@ -2669,34 +2775,49 @@ void gui_menubar_end(struct gui_context*);
|
||||
in an immediate mode API which sets each size of a widget directly before
|
||||
it is called or a retain mode API which stores the size of every widget as
|
||||
an array.
|
||||
The final way to position widgets is by allocating a fixed space from
|
||||
The third way to position widgets is by allocating a fixed space from
|
||||
the window and directly positioning each widget with position and size.
|
||||
This requires the least amount of work for the API and the most for the user,
|
||||
but offers the most positioning freedom.
|
||||
The final row layout is a tiled layout which divides a space in the panel
|
||||
into a Top, Left, Center, Right and Bottom slot. Each slot can be filled
|
||||
with widgets either horizontally or vertically.
|
||||
|
||||
window layout function API
|
||||
gui_layout_row -- user defined widget row layout
|
||||
fixed width widget layout API
|
||||
gui_layout_row_dynamic -- scaling fixed column row layout
|
||||
gui_layout_row_static -- fixed width fixed column row layout
|
||||
|
||||
custom width widget layout API
|
||||
gui_layout_row -- user defined widget row layout
|
||||
gui_layout_row_begin -- begins the row build up process
|
||||
gui_layout_row_push -- pushes the next widget width
|
||||
gui_layout_row_end -- ends the row build up process
|
||||
|
||||
custom widget placing layout API
|
||||
gui_layout_row_space_begin -- creates a free placing space in the window
|
||||
gui_layout_row_space_widget -- pushes a widget into the space
|
||||
gui_layout_row_space_to_screen -- converts from local space to screen
|
||||
gui_layout_row_space_to_local -- conversts from screen to local space
|
||||
gui_layout_row_space_rect_to_screen -- converts from local space to screen
|
||||
gui_layout_row_space_rect_to_local -- conversts from screen to local space
|
||||
gui_layout_row_space_to_local -- converts from screen to local space
|
||||
gui_layout_row_space_rect_to_screen -- converts rect from local space to screen
|
||||
gui_layout_row_space_rect_to_local -- converts rect from screen to local space
|
||||
gui_layout_row_space_push -- pushes a widget into the space
|
||||
gui_layout_row_space_end -- finishes the free drawingp process
|
||||
|
||||
window tree layout function API
|
||||
gui_layout_push -- pushes a new node/collapseable header/tab
|
||||
gui_layout_pop -- pops the the previously added node
|
||||
tiled widget placing layout API
|
||||
gui_layout_row_tiled_begin -- begins tiled layout based placing of widgets
|
||||
gui_layout_row_tiled_slot_bounds -- returns the bounds of a slot in the tiled layout
|
||||
gui_layout_row_tiled_bounds -- returns the bounds of a widget in the tiled layout
|
||||
gui_layout_row_tiled_push -- pushes a widget into a slot in the tiled layout
|
||||
gui_layout_row_tiled_end -- ends tiled layout based placing of widgets
|
||||
|
||||
window tree layout function API
|
||||
gui_layout_push -- pushes a new node/collapseable header/tab
|
||||
gui_layout_pop -- pops the the previously added node
|
||||
*/
|
||||
enum gui_row_layout_format {
|
||||
GUI_DYNAMIC, /* row layout which scales with the window */
|
||||
GUI_STATIC /* row layout with fixed pixel width */
|
||||
enum gui_layout_node_type {
|
||||
GUI_LAYOUT_NODE,
|
||||
/* a node is a space which can be minimized or maximized */
|
||||
GUI_LAYOUT_TAB
|
||||
/* a tab is a node with a header */
|
||||
};
|
||||
|
||||
void gui_layout_row_dynamic(struct gui_context*, gui_float height, gui_size cols);
|
||||
@ -2714,7 +2835,7 @@ void gui_layout_row_static(struct gui_context*, gui_float row_height,
|
||||
- number of widget inside the row that will divide the space
|
||||
*/
|
||||
void gui_layout_row_begin(struct gui_context*,
|
||||
enum gui_row_layout_format,
|
||||
enum gui_layout_format,
|
||||
gui_float row_height, gui_size cols);
|
||||
/* this function start a new scaleable row that can be filled with different
|
||||
sized widget
|
||||
@ -2731,7 +2852,7 @@ void gui_layout_row_push(struct gui_context*, gui_float value);
|
||||
*/
|
||||
void gui_layout_row_end(struct gui_context*);
|
||||
/* this function ends the previously started scaleable row */
|
||||
void gui_layout_row(struct gui_context*, enum gui_row_layout_format,
|
||||
void gui_layout_row(struct gui_context*, enum gui_layout_format,
|
||||
gui_float height, gui_size cols, const gui_float *ratio);
|
||||
/* this function sets the row layout as an array of ratios/width for
|
||||
every widget that will be inserted into that row
|
||||
@ -2742,7 +2863,7 @@ void gui_layout_row(struct gui_context*, enum gui_row_layout_format,
|
||||
- window ratio/pixel width array for each widget
|
||||
*/
|
||||
void gui_layout_row_space_begin(struct gui_context*,
|
||||
enum gui_row_layout_format,
|
||||
enum gui_layout_format,
|
||||
gui_float height, gui_size widget_count);
|
||||
/* this functions starts a space where widgets can be added
|
||||
at any given position and the user has to make sure no overlap occures
|
||||
@ -2788,6 +2909,20 @@ struct gui_rect gui_layout_row_space_rect_to_local(struct gui_context*, struct g
|
||||
*/
|
||||
void gui_layout_row_space_end(struct gui_context*);
|
||||
/* this functions finishes the scaleable space filling process */
|
||||
void gui_layout_row_tiled_begin(struct gui_context*, struct gui_tiled_layout*);
|
||||
/* this functions begins the tiled layout
|
||||
Input:
|
||||
- row height of the complete layout to allocate from the window
|
||||
*/
|
||||
void gui_layout_row_tiled_push(struct gui_context*, enum gui_tiled_layout_slot_index,
|
||||
gui_uint index);
|
||||
/* this functions pushes a widget into a tiled layout slot
|
||||
Input:
|
||||
- slot identifier
|
||||
- widget index in the slot
|
||||
*/
|
||||
void gui_layout_row_tiled_end(struct gui_context*);
|
||||
/* this functions ends the tiled layout */
|
||||
gui_bool gui_layout_push(struct gui_context*, enum gui_layout_node_type,
|
||||
const char *title, gui_state*);
|
||||
/* this functions pushes either a tree node or collapseable header into
|
||||
@ -3190,6 +3325,7 @@ enum gui_popup_type {
|
||||
GUI_POPUP_DYNAMIC
|
||||
/* dynamically growing popup with maximum height */
|
||||
};
|
||||
|
||||
gui_flags gui_popup_begin(struct gui_context *parent,
|
||||
struct gui_context *popup, enum gui_popup_type,
|
||||
gui_flags, struct gui_rect bounds,
|
||||
|
Loading…
Reference in New Issue
Block a user