changed stack to use hook instead of panel

This commit is contained in:
vurtun 2015-05-12 17:01:02 +02:00
parent c9666d1151
commit 43f492c34a
7 changed files with 74 additions and 71 deletions

View File

@ -37,14 +37,16 @@ Summary: It is only responsible for the actual user interface
## Example
```c
struct gui_input input = {0};
struct gui_font font = {...};
/* allocate memory to hold output */
struct gui_memory memory = {...};
struct gui_command_buffer buffer;
gui_buffer_init_fixed(buffer, &memory, 0);
struct gui_panel panel;
/* initialize panel */
struct gui_config config;
struct gui_input input = {0};
struct gui_font font = {...};
struct gui_panel panel;
gui_default_config(&config);
gui_panel_init(&panel, 50, 50, 220, 170,
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|
@ -344,17 +346,15 @@ 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_panel_hook` which contains the panel and the buffer output `gui_command_list`,
which can be used to implement overlapping panels.
have to be drawn in a certain order.
```c
struct gui_panel_hook hook;
struct your_window {
struct gui_panel_hook hook;
/* your data */
}
struct your_window win;
struct gui_memory memory = {...};
struct gui_memory_status status;
struct gui_command_buffer buffer;
@ -365,30 +365,29 @@ struct gui_stack stack;
gui_buffer_init_fixed(buffer, &memory);
gui_default_config(&config);
gui_hook_init(&hook, 50, 50, 300, 200, 0, &config, &font);
gui_hook_init(&win.hook, 50, 50, 300, 200, 0, &config, &font);
gui_stack_clear(&stack);
gui_stack_push_hook(&stack, &hook);
gui_stack_push(&stack, &win.hook);
while (1) {
struct gui_panel_layout layout;
struct gui_canvas canvas;
gui_buffer_begin(&canvas, &buffer, window_width, window_height);
gui_hook_begin(&layout, &hook, &stack, "Demo", &canvas, &input);
gui_hook_begin(&layout, &win.hook, &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_hook_end(&layout, &hook);
gui_buffer_end(gui_hook_list(&hook), buffer, &status);
gui_hook_end(&layout, &win.hook);
gui_buffer_end(gui_hook_list(&win.hook), buffer, &status);
/* draw each panel */
struct gui_panel *iter = stack.begin;
while (iter) {
struct gui_panel_hook *h = gui_hook(iter);
const struct gui_command *cmd = gui_list_begin(gui_hook_list(h));
while (cmd) {
/* execute command */
cmd = gui_list_next(gui_hook_list(h), cmd);
cmd = gui_list_next(gui_hook_output(iter), cmd);
}
iter = iter->next;
}

View File

@ -3,6 +3,8 @@
struct show_window {
struct gui_panel_hook hook;
/* widget data */
gui_char in_buf[MAX_BUFFER];
gui_size in_len;
gui_bool in_act;
@ -16,22 +18,30 @@ struct show_window {
gui_bool spin_act;
gui_size item_cur;
gui_size cur;
gui_bool diff_min;
gui_bool wid_min;
gui_bool tbl_min;
gui_float shelf_off;
gui_float tbl_off;
gui_int combo_sel;
gui_bool toggle;
gui_int option;
/* tabs */
gui_bool diff_min;
gui_bool wid_min;
gui_bool tbl_min;
/* scrollbars */
gui_float shelf_off;
gui_float tbl_off;
};
struct control_window {
struct gui_panel_hook hook;
gui_flags show_flags;
/* tabs */
gui_bool flag_min;
gui_bool style_min;
gui_bool color_min;
/* color picker */
gui_bool picker_act;
gui_bool col_r_act;
gui_bool col_g_act;
@ -79,7 +89,7 @@ graph_panel(struct gui_panel_layout *panel, struct show_window *demo)
enum {HISTO, PLOT};
struct gui_panel_layout tab;
static const char *shelfs[] = {"Histogram", "Lines"};
static const gui_float values[] = {8.0f, 15.0f, 20.0f, 12.0f, 30.0f, 12.0f, 35.0f, 40.0f, 20.0f};
static const gui_float values[] = {8.0f,15.0f,20.0f,12.0f,30.0f,12.0f,35.0f,40.0f,20.0f};
gui_panel_row(panel, 180, 1);
demo->cur = gui_panel_shelf_begin(panel,&tab,shelfs,LEN(shelfs),demo->cur,demo->shelf_off);
gui_panel_row(&tab, 100, 1);
@ -169,7 +179,8 @@ flags_tab(struct gui_panel_layout *panel, struct control_window *control)
control->flag_min = gui_panel_tab_begin(panel, &tab, "Options", control->flag_min);
gui_panel_row(&tab, 30, 2);
do {
if (gui_panel_check(&tab, options[n++], (control->show_flags & i) ? gui_true : gui_false)) res |= i;
if (gui_panel_check(&tab, options[n++], (control->show_flags & i) ? gui_true : gui_false))
res |= i;
i = i << 1;
} while (i <= GUI_PANEL_SCALEABLE);
control->show_flags = res;
@ -305,9 +316,9 @@ init_demo(struct show_window *show, struct control_window *control,
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|
GUI_PANEL_CLOSEABLE|GUI_PANEL_SCALEABLE|
GUI_PANEL_MINIMIZABLE, config, font);
gui_stack_push_hook(stack, &show->hook);
gui_stack_push(stack, &show->hook);
/*show->wid_min = gui_true;*/
show->wid_min = gui_true;
show->diff_min = gui_true;
show->slider = 5.0f;
show->prog = 50;
@ -316,7 +327,7 @@ init_demo(struct show_window *show, struct control_window *control,
memset(control, 0, sizeof(*control));
gui_hook_init(&control->hook, 380, 50, 400, 350,
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|GUI_PANEL_CLOSEABLE|GUI_PANEL_SCALEABLE, config, font);
gui_stack_push_hook(stack, &control->hook);
gui_stack_push(stack, &control->hook);
control->show_flags = gui_hook_panel(&show->hook)->flags;
control->style_min = gui_true;
control->color_min = gui_true;
@ -334,14 +345,14 @@ run_demo(struct show_window *show, struct control_window *control, struct gui_pa
gui_buffer_begin(NULL, buffer, width, height);
gui_buffer_lock(&canvas, buffer, &sub, 0, width, height);
running = control_panel(control, stack, in, &canvas, config);
gui_buffer_unlock(gui_hook_list(&control->hook), buffer, &sub, &canvas, NULL);
gui_buffer_unlock(gui_hook_output(&control->hook), buffer, &sub, &canvas, NULL);
gui_hook_panel(&show->hook)->flags = control->show_flags;
gui_buffer_lock(&canvas, buffer, &sub, 0, width, height);
show_panel(show, stack, in, &canvas);
if (gui_hook_panel(&show->hook)->flags & GUI_PANEL_HIDDEN)
control->show_flags |= GUI_PANEL_HIDDEN;
gui_buffer_unlock(gui_hook_list(&show->hook), buffer, &sub, &canvas, NULL);
gui_buffer_unlock(gui_hook_output(&show->hook), buffer, &sub, &canvas, NULL);
gui_buffer_end(NULL, buffer, NULL, NULL);
return running;
}

View File

@ -480,11 +480,10 @@ 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 *iter = stack->begin;
struct gui_panel_hook *iter = stack->begin;
if (!stack->count) return;
while (iter) {
struct gui_panel_hook *hook = gui_hook(iter);
execute(&hook->list, width, height);
execute(gui_hook_output(iter), width, height);
iter = iter->next;
}
}

View File

@ -135,7 +135,7 @@ static void
font_del(XFont *font)
{
if (font->handle)
DeleteObject(font->handle);
DeleteObject(font->handle);
free(font);
}
@ -334,11 +334,10 @@ execute(XSurface *surf, struct gui_command_list *list)
static void
draw(XSurface *surf, struct gui_panel_stack *stack)
{
struct gui_panel *iter = stack->begin;
struct gui_panel_hook *iter = stack->begin;
if (!stack->count) return;
while (iter) {
struct gui_panel_hook *hook = gui_hook(iter);
execute(surf, gui_hook_list(hook));
execute(surf, gui_hook_output(iter));
iter = iter->next;
}
}

View File

@ -345,11 +345,10 @@ execute(XSurface *surf, struct gui_command_list *list)
static void
draw(XSurface *surf, struct gui_panel_stack *stack)
{
struct gui_panel *iter = stack->begin;
struct gui_panel_hook *iter = stack->begin;
if (!stack->count) return;
while (iter) {
struct gui_panel_hook *hook = gui_hook(iter);
execute(surf, gui_hook_list(hook));
execute(surf, gui_hook_output(iter));
iter = iter->next;
}
}

21
gui.c
View File

@ -1546,6 +1546,7 @@ gui_panel_begin_stacked(struct gui_panel_layout *layout, struct gui_panel *panel
const struct gui_input *in)
{
gui_bool inpanel;
struct gui_panel_hook *hook;
ASSERT(layout);
ASSERT(panel);
ASSERT(stack);
@ -1553,20 +1554,22 @@ gui_panel_begin_stacked(struct gui_panel_layout *layout, struct gui_panel *panel
if (!layout || !panel || !stack || !canvas)
return gui_false;
hook = (struct gui_panel_hook*)panel;
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;
if (in->mouse_down && in->mouse_clicked && inpanel && hook != stack->end) {
const struct gui_panel_hook *iter = hook->next;
while (iter) {
if (INBOX(in->mouse_prev.x, in->mouse_prev.y, iter->x, iter->y, iter->w, iter->h) &&
!iter->minimized) break;
const struct gui_panel *cur = gui_hook_panel(iter);
if (INBOX(in->mouse_prev.x, in->mouse_prev.y, cur->x, cur->y, cur->w, cur->h) &&
!cur->minimized) break;
iter = iter->next;
}
if (!iter) {
gui_stack_pop(stack, panel);
gui_stack_push(stack, panel);
gui_stack_pop(stack, hook);
gui_stack_push(stack, hook);
}
}
return gui_panel_begin(layout, panel, title, canvas, (stack->end == panel) ? in : NULL);
return gui_panel_begin(layout, panel, title, canvas, (stack->end == hook) ? in : NULL);
}
void
@ -2741,7 +2744,7 @@ gui_stack_clear(struct gui_panel_stack *stack)
}
void
gui_stack_push(struct gui_panel_stack *stack, struct gui_panel *panel)
gui_stack_push(struct gui_panel_stack *stack, struct gui_panel_hook *panel)
{
if (!stack->begin) {
panel->next = NULL;
@ -2760,7 +2763,7 @@ gui_stack_push(struct gui_panel_stack *stack, struct gui_panel *panel)
}
void
gui_stack_pop(struct gui_panel_stack *stack, struct gui_panel *panel)
gui_stack_pop(struct gui_panel_stack *stack, struct gui_panel_hook *panel)
{
if (panel->prev)
panel->prev->next = panel->next;

35
gui.h
View File

@ -15,9 +15,9 @@ extern "C" {
#define GUI_INPUT_MAX 16
#define GUI_UTF_INVALID 0xFFFD
#define GUI_HOOK_PANEL_NAME panel
#define GUI_HOOK_LIST_NAME list
#define GUI_HOOK_OUTPUT_NAME list
#define GUI_HOOK_ATTR(T, name) struct T name
#define GUI_HOOK_OUT gui_command_list
#define GUI_HOOK_OUTPUT gui_command_list
/* Types */
#ifdef GUI_USE_FIXED_TYPES
@ -415,8 +415,6 @@ 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_panel_layout {
@ -439,16 +437,17 @@ struct gui_panel_layout {
const struct gui_canvas *canvas;
};
struct gui_panel_stack {
gui_size count;
struct gui_panel *begin;
struct gui_panel *end;
};
struct gui_panel_hook {
GUI_HOOK_ATTR(gui_panel, GUI_HOOK_PANEL_NAME);
GUI_HOOK_ATTR(GUI_HOOK_OUT, GUI_HOOK_LIST_NAME);
GUI_HOOK_ATTR(GUI_HOOK_OUTPUT, GUI_HOOK_OUTPUT_NAME);
struct gui_panel_hook *next;
struct gui_panel_hook *prev;
};
struct gui_panel_stack {
gui_size count;
struct gui_panel_hook *begin;
struct gui_panel_hook *end;
};
/* Input */
@ -606,25 +605,19 @@ 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*);
void gui_stack_push(struct gui_panel_stack*, struct gui_panel_hook*);
void gui_stack_pop(struct gui_panel_stack*, struct gui_panel_hook*);
/* Hook */
#define gui_hook(p) ((struct gui_panel_hook*)(p))
#define gui_hook_panel(h) (&((h)->GUI_HOOK_PANEL_NAME))
#define gui_hook_list(h) (&((h)->GUI_HOOK_LIST_NAME))
#define gui_hook_output(h) (&((h)->GUI_HOOK_OUTPUT_NAME))
#define gui_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)
#define gui_hook_begin(layout, hook, stack, title, canvas, in)\
gui_panel_begin_stacked(layout, &(*(hook)).GUI_HOOK_PANEL_NAME, stack, title, canvas, in)
#define gui_hook_end(layout, hook)\
gui_panel_end((layout), &(hook)->GUI_HOOK_PANEL_NAME)
#define gui_stack_push_hook(stack, hook)\
gui_stack_push(stack, &(*(hook)).GUI_HOOK_PANEL_NAME)
#define gui_stack_pop_hook(stack, hook)\
gui_stack_pop(stack, &(*(hook)).GUI_HOOK_PANEL_NAME)
#ifdef __cplusplus
}