diff --git a/demo/demo.c b/demo/demo.c index ae94f0b..81413fd 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -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)) { diff --git a/demo/demo.lua b/demo/demo.lua new file mode 100644 index 0000000..5e36c36 --- /dev/null +++ b/demo/demo.lua @@ -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 + diff --git a/demo/opengl.c b/demo/opengl.c index 2c25854..0df2ba2 100644 --- a/demo/opengl.c +++ b/demo/opengl.c @@ -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 diff --git a/demo/win32.c b/demo/win32.c index 44ae988..7403c45 100644 --- a/demo/win32.c +++ b/demo/win32.c @@ -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 diff --git a/demo/xlib.c b/demo/xlib.c index ebd6854..cb4e4a1 100644 --- a/demo/xlib.c +++ b/demo/xlib.c @@ -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 diff --git a/gui.c b/gui.c index ea3674c..16cd524 100644 --- a/gui.c +++ b/gui.c @@ -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; diff --git a/gui.h b/gui.h index fe3cd5e..ca04289 100644 --- a/gui.h +++ b/gui.h @@ -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