that did not work

This commit is contained in:
vurtun 2015-05-07 15:52:35 +02:00
parent fa2c7a7c28
commit 90d536f7bf
4 changed files with 154 additions and 20 deletions

View File

@ -277,6 +277,62 @@ while (1) {
}
```
### Stack
While using basic panels is fine for a single movable panel or a big number of
static panels, it has rather limited support for overlapping movable panels. For
that to change the panel stack was introduced. The panel stack holds the basic
drawing order of each panel so instead of drawing each panel individually they
have to be drawn in a certain order. The biggest problem while creating the API
was that the buffer has to saved with the panel, but the type of the buffer is
not known beforehand since it is possible to create your own buffer type.
Therefore just the sequence of panels is managed and you either have to cast
from the panel to your own type, use inheritance in C++ or use the `container_of`
macro from the Linux kernel. For the standard buffer there is already a type
`gui_window` which contains the panel and the buffer output `gui_command_list`,
which can be used to implement overlapping panels.
```c
struct gui_window window;
struct gui_memory memory = {...};
struct gui_memory_status status;
struct gui_command_buffer buffer;
struct gui_config config;
struct gui_font font = {...}
struct gui_input input = {0};
struct gui_stack stack;
gui_buffer_init_fixed(buffer, &memory);
gui_default_config(&config);
gui_panel_init(&win.panel, 50, 50, 300, 200, 0, &config, &font);
gui_stack_clear(&stack);
gui_stack_push(&stack, &win.panel);
while (1) {
struct gui_panel_layout layout;
struct gui_canvas canvas;
gui_buffer_begin(&canvas, &buffer, window_width, window_height);
gui_panel_begin_stacked(&layout, &win.panel, &stack, "Demo", &canvas, &input);
gui_panel_row(&layout, 30, 1);
if (gui_panel_button_text(&layout, "button", GUI_BUTTON_DEFAULT))
fprintf(stdout, "button pressed!\n");
gui_panel_end(&layout, &win.panel);
gui_buffer_end(&win.list, buffer, &status);
/* draw each panel */
struct gui_panel *iter = stack.begin;
while (iter) {
const struct gui_window *w = iter;
const struct gui_command *cmd = gui_list_begin(&w->list);
while (cmd) {
/* execute command */
cmd = gui_list_next(&w->list, cmd);
}
iter = iter->next;
}
}
```
## FAQ
#### Where is the demo/example code?
The demo and example code can be found in the demo folder.

View File

@ -479,12 +479,9 @@ main(int argc, char *argv[])
struct gui_config config;
struct gui_canvas canvas;
struct gui_command_buffer buffer;
struct gui_command_buffer sub;
struct gui_command_list panel_list;
struct gui_command_list msg_list;
struct gui_command_list list;
struct gui_panel_layout layout;
struct gui_panel panel;
struct gui_panel msg;
/* Window */
UNUSED(argc); UNUSED(argv);
@ -523,8 +520,6 @@ main(int argc, char *argv[])
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|
GUI_PANEL_CLOSEABLE|GUI_PANEL_SCALEABLE|
GUI_PANEL_MINIMIZABLE, &config, &font);
gui_panel_init(&msg, 150, 150, 200, 80,
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE, &config, &font);
/* Demo */
memset(&demo, 0, sizeof(demo));
@ -551,27 +546,16 @@ main(int argc, char *argv[])
gui_input_end(&in);
/* GUI */
gui_buffer_begin(NULL, &buffer, xw.width, xw.height);
gui_buffer_lock(&canvas, &buffer, &sub, 0, xw.width, xw.height);
gui_buffer_begin(&canvas, &buffer, xw.width, xw.height);
running = gui_panel_begin(&layout, &panel, "Demo", &canvas, &in);
demo_panel(&layout, &demo);
gui_panel_end(&layout, &panel);
gui_buffer_unlock(&panel_list, &buffer, &sub, &canvas, NULL);
gui_buffer_lock(&canvas, &buffer, &sub, 0, xw.width, xw.height);
gui_panel_begin(&layout, &msg, "Demo", &canvas, &in);
gui_panel_row(&layout, 30, 2);
if (gui_panel_button_text(&layout, "ok", GUI_BUTTON_DEFAULT)) break;
if (gui_panel_button_text(&layout, "cancel", GUI_BUTTON_DEFAULT)) break;
gui_panel_end(&layout, &msg);
gui_buffer_unlock(&msg_list, &buffer, &sub, &canvas, NULL);
gui_buffer_end(NULL, &buffer, NULL, NULL);
gui_buffer_end(&list, &buffer, &canvas, &status);
/* Draw */
XClearWindow(xw.dpy, xw.win);
surface_clear(xw.surf, 0x00646464);
draw(xw.surf, &panel_list);
draw(xw.surf, &msg_list);
draw(xw.surf, &list);
surface_blit(xw.win, xw.surf, xw.width, xw.height);
XFlush(xw.dpy);

72
gui.c
View File

@ -1482,6 +1482,36 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
return ret;
}
gui_bool
gui_panel_begin_stacked(struct gui_panel_layout *layout, struct gui_panel *panel,
struct gui_panel_stack *stack, const char *title, const struct gui_canvas *canvas,
const struct gui_input *in)
{
gui_bool inpanel;
assert(layout);
assert(panel);
assert(stack);
assert(canvas);
if (!layout || !panel || !stack || !canvas)
return gui_false;
inpanel = INBOX(in->mouse_prev.x, in->mouse_prev.y, panel->x, panel->y, panel->w, panel->h);
if (in->mouse_down && in->mouse_clicked && inpanel && panel != stack->end) {
struct gui_panel *iter = panel->next;
while (iter) {
if (!iter->minimized)
if (INBOX(in->mouse_prev.x, in->mouse_prev.y, iter->x, iter->y,
iter->w, iter->h)) break;
iter = iter->next;
}
if (!iter) {
gui_stack_pop(stack, panel);
gui_stack_push(stack, panel);
}
}
return gui_panel_begin(layout, panel, title, canvas, (stack->end == panel) ? in : NULL);
}
void
gui_panel_row(struct gui_panel_layout *layout, gui_float height, gui_size cols)
{
@ -2742,3 +2772,45 @@ gui_panel_end(struct gui_panel_layout *layout, struct gui_panel *panel)
canvas->scissor(canvas->userdata, 0, 0, (gui_float)canvas->width, (gui_float)canvas->height);
}
void
gui_stack_clear(struct gui_panel_stack *stack)
{
stack->begin = NULL;
stack->end = NULL;
stack->count = 0;
}
void
gui_stack_push(struct gui_panel_stack *stack, struct gui_panel *panel)
{
if (!stack->begin) {
panel->next = NULL;
panel->prev = NULL;
stack->begin = panel;
stack->end = panel;
stack->count = 1;
return;
}
stack->end->next = panel;
panel->prev = stack->end;
panel->next = NULL;
stack->end = panel;
stack->count++;
}
void
gui_stack_pop(struct gui_panel_stack *stack, struct gui_panel *panel)
{
if (panel->prev)
panel->prev->next = panel->next;
if (panel->next)
panel->next->prev = panel->prev;
if (stack->begin == panel)
stack->begin = panel->next;
if (stack->end == panel)
stack->end = panel->prev;
panel->next = NULL;
panel->prev = NULL;
}

22
gui.h
View File

@ -395,6 +395,13 @@ struct gui_panel {
gui_bool minimized;
struct gui_font font;
const struct gui_config *config;
struct gui_panel *next;
struct gui_panel *prev;
};
struct gui_window {
struct gui_panel panel;
struct gui_command_list list;
};
struct gui_panel_layout {
@ -417,6 +424,12 @@ struct gui_panel_layout {
const struct gui_canvas *canvas;
};
struct gui_panel_stack {
gui_size count;
struct gui_panel *begin;
struct gui_panel *end;
};
/* Input */
gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size);
gui_size gui_utf_encode(gui_long, gui_char*, gui_size);
@ -505,6 +518,9 @@ void gui_panel_init(struct gui_panel*, gui_float x, gui_float y, gui_float w, gu
gui_flags, const struct gui_config *config, const struct gui_font*);
gui_bool gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel*,
const char *title, const struct gui_canvas*, const struct gui_input*);
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*);
void gui_panel_row(struct gui_panel_layout*, gui_float height, gui_size cols);
void gui_panel_alloc_space(struct gui_rect*, struct gui_panel_layout*);
void gui_panel_seperator(struct gui_panel_layout*, gui_size cols);
@ -559,6 +575,12 @@ 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*);
/* Stack */
void gui_stack_clear(struct gui_panel_stack*);
void gui_stack_push(struct gui_panel_stack*, struct gui_panel*);
void gui_stack_pop(struct gui_panel_stack*, struct gui_panel*);
#ifdef __cplusplus
}
#endif