added foreach loops

This commit is contained in:
vurtun 2015-05-16 12:26:39 +02:00
parent 96fb8fa3b3
commit b91cd2d840
7 changed files with 141 additions and 51 deletions

View File

@ -267,7 +267,7 @@ color_picker(struct gui_panel_layout *panel, struct control_window *control,
b = gui_panel_slider(panel, 0, b, 255, 10);
color.b = (gui_byte)b;
color.b = (gui_byte)gui_panel_spinner(panel, 0, (gui_int)color.b, 255, 1, &control->spinner_b_active);
color.b = (gui_byte)gui_panel_spinner(panel, 0,(gui_int)color.b, 255, 1, &control->spinner_b_active);
a = gui_panel_slider(panel, 0, a, 255, 10);
color.a = (gui_byte)a;
@ -286,10 +286,11 @@ color_tab(struct gui_panel_layout *panel, struct control_window *control, struct
"Editbox Border:", "Spinner:", "Spinner Border:", "Selector:", "Selector Border:",
"Histo:", "Histo Bars:", "Histo Negative:", "Histo Hovering:", "Plot:", "Plot Lines:",
"Plot Hightlight:", "Scrollbar:", "Scrollbar Cursor:", "Scrollbar Border:",
"Table lines:", "Scaler:"
"Table lines:", "Shelf:", "Shelf Text:", "Shelf Active:", "Shelf Active Text:", "Scaler:"
};
if (control->picker_active) {
control->color = color_picker(panel, control, labels[control->current_color], control->color);
control->color = color_picker(panel,control,labels[control->current_color], control->color);
gui_panel_row(panel, 30, 3);
gui_panel_seperator(panel, 1);
if (gui_panel_button_text(panel, "ok", GUI_BUTTON_DEFAULT)) {

25
demo/demo.lua Normal file
View File

@ -0,0 +1,25 @@
gui = require(gui);
demo = {};
function init_demo(stack, font)
demo.font = font;
demo.canvas = gui.buffer.canvas();
demo.config = gui.panel.config();
demo.layout = gui.panel.layout();
demo.tab = gui.panel.layout();
demo.memory = gui.buffer.memory(8 * 1024);
demo.buffer = gui.buffer.new(demo.memory);
demo.panel = gui.hook.new(50, 50, 200, 400, demo.config, font);
gui.stack.push(stack, demo.panel);
end
function update_demo(stack, input, width, height)
gui.buffer.begin(demo.canvas, demo.buffer, width, height);
gui.panel.hook.begin(demo.layout, demo.panel, stack, "Demo", demo.canvas, input);
if gui.panel.button(demo.layout, "Button") then print("button pressed!") end
gui.panel.hook.end(demo.layout, demo.panel);
gui.buffer.end(demo.panel:output(), demo.buffer, demo.canvas);
end

View File

@ -428,29 +428,27 @@ execute(struct gui_command_list *list, int width, int height)
glPushMatrix();
glLoadIdentity();
cmd = gui_list_begin(list);
while (cmd) {
gui_list_for_each(cmd, list) {
switch (cmd->type) {
case GUI_COMMAND_NOP: break;
case GUI_COMMAND_SCISSOR: {
const struct gui_command_scissor *s = (const void*)cmd;
const struct gui_command_scissor *s = GUI_FETCH(scissor, cmd);
glScissor(s->x, height - (s->y + s->h), s->w, s->h);
} break;
case GUI_COMMAND_LINE: {
const struct gui_command_line *l = (const void*)cmd;
const struct gui_command_line *l = GUI_FETCH(line, cmd);
draw_line(l->begin[0], l->begin[1], l->end[0], l->end[1], l->color);
} break;
case GUI_COMMAND_RECT: {
const struct gui_command_rect *r = (const void*)cmd;
const struct gui_command_rect *r = GUI_FETCH(rect, cmd);
draw_rect(r->x, r->y, r->w, r->h, r->color);
} break;
case GUI_COMMAND_CIRCLE: {
unsigned i;
const struct gui_command_circle *c = (const void*)cmd;
const struct gui_command_circle *c = GUI_FETCH(circle, cmd);
draw_circle(c->x, c->y, (float)c->w / 2.0f, c->color);
} break;
case GUI_COMMAND_TRIANGLE: {
const struct gui_command_triangle *t = (const void*)cmd;
const struct gui_command_triangle *t = GUI_FETCH(triangle, cmd);
glColor4ub(t->color.r, t->color.g, t->color.b, t->color.a);
glBegin(GL_TRIANGLES);
glVertex2f(t->a[0], t->a[1]);
@ -459,14 +457,13 @@ execute(struct gui_command_list *list, int width, int height)
glEnd();
} break;
case GUI_COMMAND_TEXT: {
const struct gui_command_text *t = (const void*)cmd;
const struct gui_command_text *t = GUI_FETCH(text, cmd);
font_draw_text(t->font, t->x, t->y, t->h, t->fg, t->string, t->length);
} break;
case GUI_COMMAND_IMAGE:
case GUI_COMMAND_MAX:
default: break;
}
cmd = gui_list_next(list, cmd);
}
glBindTexture(GL_TEXTURE_2D, 0);
@ -480,12 +477,9 @@ execute(struct gui_command_list *list, int width, int height)
static void
draw(struct gui_panel_stack *stack, int width, int height)
{
struct gui_panel_hook *iter = stack->begin;
if (!stack->count) return;
while (iter) {
struct gui_panel_hook *iter;
gui_stack_for_each(iter, stack)
execute(gui_hook_output(iter), width, height);
iter = iter->next;
}
}
static void

View File

@ -272,56 +272,50 @@ static void
execute(XSurface *surf, struct gui_command_list *list)
{
const struct gui_command *cmd;
if (!list->count) return;
cmd = gui_list_begin(list);
while (cmd) {
gui_list_for_each(cmd, list) {
switch (cmd->type) {
case GUI_COMMAND_NOP: break;
case GUI_COMMAND_SCISSOR: {
const struct gui_command_scissor *s = (const void*)cmd;
const struct gui_command_scissor *s = GUI_FETCH(scissor, cmd);
surface_scissor(surf, s->x, s->y, s->w, s->h);
} break;
case GUI_COMMAND_LINE: {
const struct gui_command_line *l = (const void*)cmd;
const struct gui_command_line *l = GUI_FETCH(line, cmd);
surface_draw_line(surf, l->begin[0], l->begin[1], l->end[0],
l->end[1], l->color.r, l->color.g, l->color.b);
} break;
case GUI_COMMAND_RECT: {
const struct gui_command_rect *r = (const void*)cmd;
const struct gui_command_rect *r = GUI_FETCH(rect, cmd);
surface_draw_rect(surf, r->x, r->y, r->w, r->h,
r->color.r, r->color.g, r->color.b);
} break;
case GUI_COMMAND_CIRCLE: {
const struct gui_command_circle *c = (const void*)cmd;
const struct gui_command_circle *c = GUI_FETCH(circle, cmd);
surface_draw_circle(surf, c->x, c->y, c->w, c->h,
c->color.r, c->color.g, c->color.b);
} break;
case GUI_COMMAND_TRIANGLE: {
const struct gui_command_triangle *t = (const void*)cmd;
const struct gui_command_triangle *t = GUI_FETCH(triangle, cmd);
surface_draw_triangle(surf, t->a[0], t->a[1], t->b[0], t->b[1],
t->c[0], t->c[1], t->color.r, t->color.g, t->color.b);
} break;
case GUI_COMMAND_TEXT: {
const struct gui_command_text *t = (const void*)cmd;
const struct gui_command_text *t = GUI_FETCH(text, cmd);
XWindow *win = t->font;
surface_draw_text(surf, win->font, t->x, t->y, t->w, t->h, (const char*)t->string,
t->length, t->bg.r, t->bg.g, t->bg.b, t->fg.r, t->fg.g, t->fg.b);
} break;
default: break;
}
cmd = gui_list_next(list, cmd);
}
}
static void
draw(XSurface *surf, struct gui_panel_stack *stack)
{
struct gui_panel_hook *iter = stack->begin;
if (!stack->count) return;
while (iter) {
struct gui_panel_hook *iter;
gui_stack_for_each(iter, stack)
execute(surf, gui_hook_output(iter));
iter = iter->next;
}
}
static void

View File

@ -302,35 +302,33 @@ static void
execute(XSurface *surf, struct gui_command_list *list)
{
const struct gui_command *cmd;
if (!list->count) return;
cmd = gui_list_begin(list);
while (cmd) {
gui_list_for_each(cmd, list) {
switch (cmd->type) {
case GUI_COMMAND_NOP: break;
case GUI_COMMAND_SCISSOR: {
const struct gui_command_scissor *s = (const void*)cmd;
const struct gui_command_scissor *s = GUI_FETCH(scissor, cmd);
surface_scissor(surf, s->x, s->y, s->w, s->h);
} break;
case GUI_COMMAND_LINE: {
const struct gui_command_line *l = (const void*)cmd;
const struct gui_command_line *l = GUI_FETCH(line, cmd);
surface_draw_line(surf, l->begin[0], l->begin[1], l->end[0],
l->end[1], l->color);
} break;
case GUI_COMMAND_RECT: {
const struct gui_command_rect *r = (const void*)cmd;
const struct gui_command_rect *r = GUI_FETCH(rect, cmd);
surface_draw_rect(surf, r->x, r->y, r->w, r->h, r->color);
} break;
case GUI_COMMAND_CIRCLE: {
const struct gui_command_circle *c = (const void*)cmd;
const struct gui_command_circle *c = GUI_FETCH(circle, cmd);
surface_draw_circle(surf, c->x, c->y, c->w, c->h, c->color);
} break;
case GUI_COMMAND_TRIANGLE: {
const struct gui_command_triangle *t = (const void*)cmd;
const struct gui_command_triangle *t = GUI_FETCH(triangle, cmd);
surface_draw_triangle(surf, t->a[0], t->a[1], t->b[0], t->b[1],
t->c[0], t->c[1], t->color);
} break;
case GUI_COMMAND_TEXT: {
const struct gui_command_text *t = (const void*)cmd;
const struct gui_command_text *t = GUI_FETCH(text, cmd);
surface_draw_text(surf, t->x, t->y, t->w, t->h, (const char*)t->string,
t->length, t->font, t->bg, t->fg);
} break;
@ -338,19 +336,15 @@ execute(XSurface *surf, struct gui_command_list *list)
case GUI_COMMAND_MAX:
default: break;
}
cmd = gui_list_next(list, cmd);
}
}
static void
draw(XSurface *surf, struct gui_panel_stack *stack)
{
struct gui_panel_hook *iter = stack->begin;
if (!stack->count) return;
while (iter) {
struct gui_panel_hook *iter;
gui_stack_for_each(iter, stack)
execute(surf, gui_hook_output(iter));
iter = iter->next;
}
}
static void

29
gui.c
View File

@ -1359,6 +1359,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
ASSERT(layout);
ASSERT(canvas);
/* check arguments */
if (!panel || !canvas || !layout)
return gui_false;
if (panel->flags & GUI_PANEL_HIDDEN) {
@ -1369,10 +1370,12 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
return gui_false;
}
/* calculate header */
config = panel->config;
layout->header_height = panel->font.height + 3 * config->item_padding.y;
layout->header_height += config->panel_padding.y;
/* make sure input can be NULL */
mouse_x = (in) ? in->mouse_pos.x : -1;
mouse_y = (in) ? in->mouse_pos.y : -1;
prev_x = (in) ? in->mouse_prev.x : -1;
@ -1380,6 +1383,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
clicked_x = (in) ? in->mouse_clicked_pos.x : -1;
clicked_y = (in) ? in->mouse_clicked_pos.y : -1;
/* panel movement logic */
if (panel->flags & GUI_PANEL_MOVEABLE) {
gui_bool incursor;
const gui_float move_x = panel->x;
@ -1394,6 +1398,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
}
}
/* panel scaling logic */
if (panel->flags & GUI_PANEL_SCALEABLE) {
gui_bool incursor;
gui_float scaler_w = MAX(0, config->scaler_size.x - config->item_padding.x);
@ -1410,6 +1415,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
}
}
/* setup layout */
layout->x = panel->x;
layout->y = panel->y;
layout->w = panel->w;
@ -1427,6 +1433,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
layout->row_height = 0;
layout->offset = panel->offset;
/* special case for shelfs which do not have a header */
if (!(panel->flags & GUI_PANEL_NO_HEADER)) {
header = &config->colors[GUI_COLOR_HEADER];
header_x = panel->x + config->panel_padding.x;
@ -1436,6 +1443,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
} else layout->header_height = 1;
layout->row_height = layout->header_height + 2 * config->item_spacing.y;
/* add footer at the end of the panel */
footer_h = config->scaler_size.y + config->item_padding.y;
if ((panel->flags & GUI_PANEL_SCROLLBAR) && !panel->minimized) {
gui_float footer_x, footer_y, footer_w;
@ -1446,6 +1454,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
config->colors[GUI_COLOR_PANEL]);
}
/* update panel state which is either active or not active */
if (!(panel->flags & GUI_PANEL_TAB)) {
panel->flags |= GUI_PANEL_SCROLLBAR;
if (in && in->mouse_down) {
@ -1455,6 +1464,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
}
}
/* clipping rectangle for scrollbars */
layout->clip.x = panel->x;
layout->clip.w = panel->w;
layout->clip.y = panel->y + layout->header_height - 1;
@ -1464,6 +1474,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
}
else layout->clip.h = null_rect.h;
/* panel hidding */
if ((panel->flags & GUI_PANEL_CLOSEABLE) && (!(panel->flags & GUI_PANEL_NO_HEADER))) {
const gui_char *X = (const gui_char*)"x";
const gui_size text_width = panel->font.width(panel->font.userdata, X, 1);
@ -1474,6 +1485,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
canvas->draw_text(canvas->userdata, close_x, close_y, close_w, close_h,
X, 1, &panel->font, config->colors[GUI_COLOR_HEADER], config->colors[GUI_COLOR_TEXT]);
header_w -= close_w;
header_x += close_h - config->item_padding.x;
if (in && INBOX(mouse_x, mouse_y, close_x, close_y, close_w, close_h)) {
@ -1484,6 +1496,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
}
}
/* panel minimizing */
if ((panel->flags & GUI_PANEL_MINIMIZABLE) && (!(panel->flags & GUI_PANEL_NO_HEADER))) {
gui_size text_width;
gui_float min_x, min_y, min_w, min_h;
@ -1510,6 +1523,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
}
layout->valid = !(panel->minimized || (panel->flags & GUI_PANEL_HIDDEN));
/* panel title */
if (text && !(panel->flags & GUI_PANEL_NO_HEADER)) {
const gui_size text_len = strsiz(text);
const gui_float label_x = header_x + config->item_padding.x;
@ -1521,6 +1535,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
config->colors[GUI_COLOR_TEXT]);
}
/* panels have an empty space at the bottom that needs to be filled */
if (panel->flags & GUI_PANEL_SCROLLBAR) {
const struct gui_color *color = &config->colors[GUI_COLOR_PANEL];
layout->width = panel->w - config->scrollbar_width;
@ -1531,6 +1546,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
panel->w, panel->h - layout->header_height, *color);
}
/* draws the border of the header */
if (panel->flags & GUI_PANEL_BORDER) {
const struct gui_color *color = &config->colors[GUI_COLOR_BORDER];
const gui_float width = (panel->flags & GUI_PANEL_SCROLLBAR) ?
@ -2056,6 +2072,7 @@ gui_panel_spinner(struct gui_panel_layout *layout, gui_int min, gui_int value,
config = layout->config;
canvas = layout->canvas;
/* up button */
button.border = 1;
button_y = bounds.y;
button_h = bounds.h / 2;
@ -2070,6 +2087,8 @@ gui_panel_spinner(struct gui_panel_layout *layout, gui_int min, gui_int value,
button.highlight_content = config->colors[GUI_COLOR_TEXT];
button_up_clicked = gui_button_triangle(canvas, button_x, button_y, button_w, button_h,
GUI_UP, GUI_BUTTON_DEFAULT, &button, layout->input);
/* down button */
button_y = bounds.y + button_h;
button_down_clicked = gui_button_triangle(canvas, button_x, button_y, button_w, button_h,
GUI_DOWN, GUI_BUTTON_DEFAULT, &button, layout->input);
@ -2090,6 +2109,7 @@ gui_panel_spinner(struct gui_panel_layout *layout, gui_int min, gui_int value,
len = gui_edit(canvas, field_x, field_y, field_w, field_h, (gui_char*)string,
len, MAX_NUMBER_BUFFER, &is_active, &field,GUI_INPUT_FLOAT,
layout->input, &layout->font);
if (old_len != len)
strtoi(&value, string, len);
if (active) *active = is_active;
@ -2126,6 +2146,7 @@ gui_panel_selector(struct gui_panel_layout *layout, const char *items[],
canvas->draw_rect(canvas->userdata, bounds.x + 1, bounds.y + 1, bounds.w - 2, bounds.h - 2,
config->colors[GUI_COLOR_SELECTOR]);
/* down button */
button.border = 1;
button_y = bounds.y;
button_h = bounds.h / 2;
@ -2141,12 +2162,14 @@ gui_panel_selector(struct gui_panel_layout *layout, const char *items[],
button_down_clicked = gui_button_triangle(canvas, button_x, button_y, button_w,
button_h, GUI_UP, GUI_BUTTON_DEFAULT, &button, layout->input);
/* up button */
button_y = bounds.y + button_h;
button_up_clicked = gui_button_triangle(canvas, button_x, button_y, button_w,
button_h, GUI_DOWN, GUI_BUTTON_DEFAULT, &button, layout->input);
item_current = (button_down_clicked && item_current < item_count-1) ?
item_current+1 : (button_up_clicked && item_current > 0) ? item_current-1 : item_current;
/* current item */
label_x = bounds.x + config->item_padding.x;
label_y = bounds.y + config->item_padding.y;
label_w = bounds.w - (button_w + 2 * config->item_padding.x);
@ -2608,12 +2631,14 @@ gui_panel_shelf_begin(struct gui_panel_layout *parent, struct gui_panel_layout *
if (!INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h))
goto failed;
/* shelf header space */
header_x = bounds.x;
header_y = bounds.y;
header_w = bounds.w;
header_h = config->panel_padding.y + 3 * config->item_padding.y + parent->font.height;
item_width = (header_w - (gui_float)size) / (gui_float)size;
/* shelf selection tabs */
for (i = 0; i < size; i++) {
struct gui_button button;
gui_float button_x, button_y;
@ -2704,6 +2729,8 @@ gui_panel_end(struct gui_panel_layout *layout, struct gui_panel *panel)
if (!(panel->flags & GUI_PANEL_TAB))
canvas->scissor(canvas->userdata, layout->x, layout->y, layout->w + 1, layout->h + 1);
/* @NOTE(vurtun): panel scrollbar at the end of the panel since the final height
* of the panel is not known at the beginning of the panel and can only now be calculated. */
if (panel->flags & GUI_PANEL_SCROLLBAR && layout->valid) {
struct gui_scroll scroll;
gui_float panel_y;
@ -2732,6 +2759,7 @@ gui_panel_end(struct gui_panel_layout *layout, struct gui_panel *panel)
config->colors[GUI_COLOR_PANEL]);
} else layout->height = layout->at_y - layout->y;
/* draws the scaling triangle in the footer of the panel */
if ((panel->flags & GUI_PANEL_SCALEABLE) && layout->valid) {
struct gui_color col = config->colors[GUI_COLOR_SCALER];
gui_float scaler_w = MAX(0, config->scaler_size.x - config->item_padding.x);
@ -2742,6 +2770,7 @@ gui_panel_end(struct gui_panel_layout *layout, struct gui_panel *panel)
scaler_x + scaler_w, scaler_y + scaler_h, scaler_x, scaler_y + scaler_h, col);
}
/* draw the border for the body of the panel */
if (panel->flags & GUI_PANEL_BORDER) {
const gui_float width = (panel->flags & GUI_PANEL_SCROLLBAR) ?
layout->width + config->scrollbar_width : layout->width;

59
gui.h
View File

@ -460,6 +460,45 @@ struct gui_panel_stack {
};
/* Layout */
struct gui_layout_ratio {
gui_float left;
gui_float center;
gui_float right;
};
enum gui_layout_index {
GUI_SLOT_TOP,
GUI_SLOT_BOTTOM,
GUI_SLOT_LEFT,
GUI_SLOT_CENTER,
GUI_SLOT_RIGHT,
GUI_SLOT_MAX
};
struct gui_layout_slots {
struct gui_panel_hook *top;
struct gui_panel_hook *bottom;
struct gui_panel_hook *left;
struct gui_panel_hook *center;
struct gui_panel_hook *right;
};
union gui_layout_slot_data {
struct gui_layout_slots slot;
struct gui_panel_hook *at[GUI_SLOT_MAX];
};
struct gui_layout {
gui_size width, height;
struct gui_panel_stack stack;
struct gui_layout_ratio horizontal;
struct gui_layout_ratio vertical;
union gui_layout_slot_data slots;
};
/* Input */
gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size);
gui_size gui_utf_encode(gui_long, gui_char*, gui_size);
@ -507,6 +546,8 @@ void gui_buffer_end(struct gui_command_list*, struct gui_command_buffer*,
/* List */
#define GUI_FETCH(t,c) (const struct gui_command_##t*)c
#define gui_list_for_each(i, l) for (i = gui_list_begin(l); i != NULL; i = gui_list_next(l, i))
const struct gui_command* gui_list_begin(const struct gui_command_list*);
const struct gui_command* gui_list_next(const struct gui_command_list*,
const struct gui_command*);
@ -556,6 +597,9 @@ gui_bool gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel*,
gui_bool gui_panel_begin_stacked(struct gui_panel_layout*, struct gui_panel*,
struct gui_panel_stack*, const char*, const struct gui_canvas*,
const struct gui_input*);
gui_bool gui_panel_begin_tiled(struct gui_panel_layout*, struct gui_panel*,
struct gui_panel_layout*, const char*, const struct gui_canvas*,
const struct gui_input*);
void gui_panel_row(struct gui_panel_layout*, gui_float height, gui_size cols);
gui_bool gui_panel_widget(struct gui_rect*, struct gui_panel_layout*);
void gui_panel_seperator(struct gui_panel_layout*, gui_size cols);
@ -613,20 +657,29 @@ gui_size gui_panel_shelf_begin(struct gui_panel_layout*, struct gui_panel_layout
gui_float gui_panel_shelf_end(struct gui_panel_layout*, struct gui_panel_layout *shelf);
void gui_panel_end(struct gui_panel_layout*, struct gui_panel*);
/* Hook */
#define gui_hook_panel(h) (&((h)->GUI_HOOK_PANEL_NAME))
#define gui_hook_output(h) (&((h)->GUI_HOOK_OUTPUT_NAME))
#define gui_panel_hook_init(hook, x, y, w, h, flags, config, font)\
gui_panel_init(&(*(hook)).GUI_HOOK_PANEL_NAME, x, y, w, h, flags, config, font)
gui_panel_init(gui_hook_panel(hook), x, y, w, h, flags, config, font)
#define gui_panel_hook_begin(layout, hook, stack, title, canvas, in)\
gui_panel_begin_stacked(layout, &(*(hook)).GUI_HOOK_PANEL_NAME, stack, title, canvas, in)
gui_panel_begin_stacked(layout, gui_hook_panel(hook), stack, title, canvas, in)
#define gui_panel_hook_end(layout, hook)\
gui_panel_end((layout), &(hook)->GUI_HOOK_PANEL_NAME)
gui_panel_end((layout), gui_hook_panel(hook))
/* Stack */
#define gui_stack_begin(s) ((s)->begin)
#define gui_stack_end(s) ((s)->end)
void gui_stack_clear(struct gui_panel_stack*);
void gui_stack_push(struct gui_panel_stack*, struct gui_panel_hook*);
void gui_stack_pop(struct gui_panel_stack*, struct gui_panel_hook*);
#define gui_stack_for_each(i, s) for (i = gui_stack_begin(s); i != NULL; i = (i)->next)
/* Layout */
void gui_layout_init(struct gui_layout*);
void gui_layout_add(struct gui_layout*, struct gui_panel_hook*, enum gui_layout_index);
void gui_layout_remove(struct gui_layout*, struct gui_panel_hook*);
#ifdef __cplusplus