瀏覽代碼

shit's in flames

vurtun 10 年之前
父節點
當前提交
06aa6a2f34
共有 4 個文件被更改,包括 326 次插入80 次删除
  1. 5 5
      Makefile
  2. 286 54
      gui.c
  3. 29 11
      gui.h
  4. 6 10
      opengl.c

+ 5 - 5
Makefile

@@ -20,16 +20,16 @@ SRC = gui.c opengl.c
 OBJ = $(SRC:.c=.o)
 
 # Modes
-.PHONY: clang
-clang: CC = clang
-clang: $(BIN)
-
 .PHONY: gcc
 gcc: CC = gcc
 gcc: $(BIN)
 
+.PHONY: clang
+clang: CC = clang
+clang: $(BIN)
+
 $(BIN):
 	@mkdir -p bin
 	rm -f bin/$(BIN) $(OBJS)
-	$(CC) $(SRC) -D_POSIX_C_SOURCE=200809L $(CFLAGS) -o bin/$(BIN) -lX11 -lGL -lGLU -lm
+	$(CC) $(SRC) -D_POSIX_C_SOURCE=200809L $(CFLAGS) -o bin/$(BIN) -lX11 -lGL -lGLU
 

+ 286 - 54
gui.c

@@ -60,6 +60,15 @@ memcopy(void *dst, const void *src, gui_size size)
     return dst;
 }
 
+static gui_size
+strsiz(const char *str)
+{
+    gui_size siz = 0;
+    const char *p = str;
+    while (p && *p++ != '\0') siz++;
+    return siz;
+}
+
 static gui_int
 strtoi(gui_int *number, const char *buffer, gui_size len)
 {
@@ -109,6 +118,8 @@ unify(const struct gui_rect *a, const struct gui_rect *b)
     clip.y = MAX(a->y, b->y);
     clip.w = MIN(a->x + a->w, b->x + b->w) - clip.x;
     clip.h = MIN(a->y + a->h, b->y + b->h) - clip.y;
+    clip.w = MAX(0, clip.w);
+    clip.h = MAX(0, clip.h);
     return clip;
 }
 
@@ -200,7 +211,7 @@ gui_make_vec2(gui_float x, gui_float y)
 static void
 gui_triangle_from_direction(struct gui_vec2 *result, gui_float x, gui_float y,
     gui_float w, gui_float h, gui_float pad_x, gui_float pad_y,
-    enum gui_direction direction)
+    enum gui_heading direction)
 {
     gui_float w_half, h_half;
     w = MAX(4 * pad_x, w);
@@ -455,6 +466,7 @@ gui_push_command(struct gui_draw_buffer *buffer, gui_size count, gui_texture tex
     const struct gui_rect *clip;
     buffer->vertex_needed += count * sizeof(struct gui_vertex);
     buffer->command_needed += sizeof(struct gui_draw_command);
+
     if (!buffer || !count) return gui_false;
     if (!buffer->commands || buffer->command_size >= buffer->command_capacity ||
         !buffer->command_capacity)
@@ -519,7 +531,6 @@ static void
 gui_draw_line(struct gui_draw_buffer *buffer, gui_float x0, gui_float y0,
     gui_float x1, gui_float y1, struct gui_color col)
 {
-    struct gui_draw_command *cmd;
     if (!buffer) return;
     if (col.a == 0) return;
     if (!gui_push_command(buffer, 6, null_tex)) return;
@@ -530,7 +541,6 @@ static void
 gui_draw_trianglef(struct gui_draw_buffer *buffer, gui_float x0, gui_float y0,
     gui_float x1, gui_float y1, gui_float x2, gui_float y2, struct gui_color c)
 {
-    struct gui_draw_command *cmd;
     if (!buffer) return;
     if (c.a == 0) return;
     if (!gui_push_command(buffer, 3, null_tex))
@@ -545,7 +555,6 @@ static void
 gui_draw_rect(struct gui_draw_buffer *buffer, gui_float x, gui_float y,
     gui_float w, gui_float h, struct gui_color col)
 {
-    struct gui_draw_command *cmd;
     if (!buffer) return;
     if (col.a == 0) return;
     if (!gui_push_command(buffer, 6 * 4, null_tex))
@@ -561,7 +570,6 @@ static void
 gui_draw_rectf(struct gui_draw_buffer *buffer, gui_float x, gui_float y,
     gui_float w, gui_float h, struct gui_color col)
 {
-    struct gui_draw_command *cmd;
     if (!buffer) return;
     if (col.a == 0) return;
     if (!gui_push_command(buffer, 6, null_tex))
@@ -735,7 +743,7 @@ gui_button_text(struct gui_draw_buffer *buffer, const struct gui_button *button,
     button_h = MAX(button->h, 2 * button->pad_x);
 
     if (INBOX(in->mouse_pos.x, in->mouse_pos.y, button->x, button->y, button_w, button_h)) {
-        font_color = button->background;
+        font_color = button->highlight_font;
         background = button->highlight;
         if (INBOX(in->mouse_clicked_pos.x, in->mouse_clicked_pos.y,
                  button->x, button->y, button_w, button_h)) {
@@ -770,13 +778,13 @@ gui_button_text(struct gui_draw_buffer *buffer, const struct gui_button *button,
 
 gui_int
 gui_button_triangle(struct gui_draw_buffer *buffer, struct gui_button* button,
-    enum gui_direction direction, const struct gui_input *in)
+    enum gui_heading heading, const struct gui_input *in)
 {
     gui_bool pressed;
     struct gui_vec2 points[3];
     pressed = gui_button_text(buffer, button, NULL, 0, NULL, in);
     gui_triangle_from_direction(points, button->x, button->y, button->w, button->h,
-        button->pad_x, button->pad_y, direction);
+        button->pad_x, button->pad_y, heading);
     gui_draw_trianglef(buffer, points[0].x, points[0].y, points[1].x, points[1].y,
         points[2].x, points[2].y, button->foreground);
     return pressed;
@@ -898,6 +906,56 @@ gui_slider(struct gui_draw_buffer *buffer, const struct gui_slider *slider,
     return slider_value;
 }
 
+gui_float
+gui_slider_vertical(struct gui_draw_buffer *buffer,
+    const struct gui_slider *slider, const struct gui_input *in)
+{
+    gui_float slider_min, slider_max;
+    gui_float slider_value, slider_steps;
+    gui_float slider_w, slider_h;
+    gui_float mouse_x, mouse_y;
+    gui_float clicked_x, clicked_y;
+    gui_float cursor_x, cursor_y;
+    gui_float cursor_w, cursor_h;
+    if (!buffer || !slider || !in)
+        return 0;
+
+    slider_w = MAX(slider->w, 2 * slider->pad_x);
+    slider_h = MAX(slider->h, 2 * slider->pad_y);
+    slider_max = MAX(slider->min, slider->max);
+    slider_min = MIN(slider->min, slider->max);
+    slider_value = CLAMP(slider_min, slider->value, slider_max);
+    slider_steps = (slider_max - slider_min) / slider->step;
+
+    cursor_w = (slider_w - 2 * slider->pad_x);
+    cursor_h = slider_h - 2 * slider->pad_y;
+    cursor_w = cursor_h / (((slider_max - slider_min) + slider->step) / slider->step);
+    cursor_y = slider->y + slider->h - slider->pad_x - (cursor_h * (slider_value - slider_min));
+    cursor_x = slider->x + slider->pad_x;
+
+    mouse_x = in->mouse_pos.x;
+    mouse_y = in->mouse_pos.y;
+    clicked_x = in->mouse_clicked_pos.x;
+    clicked_y = in->mouse_clicked_pos.y;
+
+    if (in->mouse_down &&
+        INBOX(clicked_x, clicked_y, slider->x, slider->y, slider_w, slider_h) &&
+        INBOX(mouse_x, mouse_y, slider->x, slider->y, slider_w, slider_h))
+    {
+        const float d = mouse_x - (cursor_x + cursor_w / 2.0f);
+        const float pxstep = (slider_w - 2 * slider->pad_x) / slider_steps;
+        if (ABS(d) >= pxstep) {
+            slider_value += (d < 0) ? -slider->step : slider->step;
+            slider_value = CLAMP(slider_min, slider_value, slider_max);
+            cursor_y = slider->y + slider->h - slider->pad_x;
+            cursor_y -= (cursor_h * (slider_value - slider_min));
+        }
+    }
+    gui_draw_rectf(buffer, slider->x, slider->y, slider_w, slider_h, slider->background);
+    gui_draw_rectf(buffer, cursor_x, cursor_y, cursor_w, cursor_h, slider->foreground);
+    return slider_value;
+}
+
 gui_size
 gui_progress(struct gui_draw_buffer *buffer, const struct gui_progress *prog,
     const struct gui_input *in)
@@ -933,6 +991,41 @@ gui_progress(struct gui_draw_buffer *buffer, const struct gui_progress *prog,
     return prog_value;
 }
 
+gui_size
+gui_progress_vertical(struct gui_draw_buffer *buffer, const struct gui_progress *prog,
+    const struct gui_input *in)
+{
+    gui_float prog_scale;
+    gui_float cursor_x, cursor_y;
+    gui_float cursor_w, cursor_h;
+    gui_float prog_w, prog_h;
+    gui_size prog_value;
+
+    if (!buffer || !in || !prog) return 0;
+    prog_w = MAX(prog->w, 2 * prog->pad_x + 1);
+    prog_h = MAX(prog->h, 2 * prog->pad_y + 1);
+    prog_value = MIN(prog->current, prog->max);
+
+    if (prog->modifyable && in->mouse_down &&
+        INBOX(in->mouse_pos.x, in->mouse_pos.y, prog->x, prog->y, prog_w, prog_h)){
+        gui_float ratio = (gui_float)(in->mouse_pos.y - prog->y) / (gui_float)prog_h;
+        prog_value = (gui_size)((gui_float)prog->max * ratio);
+    }
+
+    if (!prog->max) return prog_value;
+    prog_value = MIN(prog_value, prog->max);
+    prog_scale = (gui_float)prog_value / (gui_float)prog->max;
+
+    cursor_w = prog_w - 2 * prog->pad_x;
+    cursor_h = (prog_h - 2 * prog->pad_y) * prog_scale;
+    cursor_x = prog->x + prog->pad_x;
+    cursor_y = prog->y + prog->h - prog->pad_y - cursor_h;
+
+    gui_draw_rectf(buffer, prog->x, prog->y, prog_w, prog_h, prog->background);
+    gui_draw_rectf(buffer, cursor_x, cursor_y, cursor_w, cursor_h, prog->foreground);
+    return prog_value;
+}
+
 static gui_bool
 gui_filter_input(gui_long unicode, gui_size len, enum gui_input_filter filter)
 {
@@ -1359,6 +1452,7 @@ gui_default_config(struct gui_config *config)
     config->colors[GUI_COLOR_TITLEBAR] = gui_make_color(45, 45, 45, 255);
     config->colors[GUI_COLOR_BUTTON] = gui_make_color(45, 45, 45, 255);
     config->colors[GUI_COLOR_BUTTON_HOVER] = gui_make_color(100, 100, 100, 255);
+    config->colors[GUI_COLOR_BUTTON_HOVER_FONT] = gui_make_color(45, 45, 45, 255);
     config->colors[GUI_COLOR_BUTTON_BORDER] = gui_make_color(100, 100, 100, 255);
     config->colors[GUI_COLOR_TOGGLE] = gui_make_color(100, 100, 100, 255);
     config->colors[GUI_COLOR_TOGGLE_ACTIVE] = gui_make_color(45, 45, 45, 255);
@@ -1414,6 +1508,7 @@ gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *out,
     gui_size text_len = 0;
     struct gui_rect clip;
     gui_float label_x, label_y, label_w, label_h;
+    gui_float header_w = w;
 
     const struct gui_config *config = panel->config;
     const struct gui_color *header = &config->colors[GUI_COLOR_TITLEBAR];
@@ -1422,35 +1517,14 @@ gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *out,
     const gui_float clicked_x = panel->in->mouse_clicked_pos.x;
     const gui_float clicked_y = panel->in->mouse_clicked_pos.y;
 
-    if (panel->flags & GUI_PANEL_HEADER) {
-        panel->header_height = panel->font->height + 3 * config->item_padding.y;
-        panel->header_height += config->panel_padding.y;
-        gui_draw_rectf(out, x, y, w, panel->header_height, *header);
-
-        clip.x = x; clip.w = w;
-        clip.y = y + panel->header_height;
-        clip.h = h - panel->header_height;
-        if (panel->flags & GUI_PANEL_SCROLLBAR)
-            clip.h -= config->panel_padding.y;
-        gui_push_clip(out, &clip);
-    } else {
-        clip.x = x; clip.y = y;
-        clip.w = w; clip.h = h;
-        if (panel->flags & GUI_PANEL_SCROLLBAR)
-            clip.h -= config->panel_padding.y;
-        gui_push_clip(out, &clip);
-        panel->header_height = config->panel_padding.y + config->item_padding.y;
-    }
-
-    panel->out = out;
-    panel->x = x;
-    panel->y = y;
-    panel->width = w;
-    panel->at_y = y;
-    panel->flags = f;
-    panel->index = 0;
-    panel->row_columns = 0;
-    panel->row_height = panel->header_height;
+    i = text;
+    label_x = x + config->panel_padding.x + config->item_padding.x;
+    label_y = y + config->panel_padding.y;
+    label_w = w - 2 * config->panel_padding.x - 2 * config->item_padding.x;
+    label_h = panel->font->height + 2 * config->item_padding.y;
+    while (*i++ != '\0') text_len++;
+    gui_draw_string(panel->out, panel->font, label_x, label_y, label_w, label_h,
+        config->colors[GUI_COLOR_TEXT], (const gui_char*)text, text_len);
 
     if (panel->flags & (GUI_PANEL_CLOSEABLE|GUI_PANEL_HEADER)) {
         gui_size text_width;
@@ -1462,7 +1536,7 @@ gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *out,
         close_y = y + config->panel_padding.y;
         close_w = (gui_float)text_width + config->panel_padding.x;
         close_h = panel->font->height + 2 * config->item_padding.y;
-        w -= ((gui_float)text_width + config->panel_padding.x);
+        header_w -= ((gui_float)text_width + config->panel_padding.x);
 
         gui_draw_string(panel->out, panel->font, close_x, close_y, close_w, close_h,
             config->colors[GUI_COLOR_TEXT], X, 1);
@@ -1480,11 +1554,11 @@ gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *out,
             (const gui_char*)"-";
 
         text_width = gui_font_text_width(panel->font, score, 1);
-        min_x = (x + w) - ((gui_float)text_width + config->item_padding.y);
+        min_x = (x + header_w) - ((gui_float)text_width + config->item_padding.y);
         min_y = y + config->panel_padding.y;
         min_w = (gui_float)text_width;
         min_h = panel->font->height + 2 * config->item_padding.y;
-        w -= (gui_float)text_width;
+        header_w -= (gui_float)text_width;
 
         gui_draw_string(panel->out, panel->font, min_x, min_y, min_w, min_h,
             config->colors[GUI_COLOR_TEXT], score, 1);
@@ -1495,20 +1569,48 @@ gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *out,
         }
     }
 
+    if (panel->flags & GUI_PANEL_HEADER) {
+        panel->header_height = panel->font->height + 3 * config->item_padding.y;
+        panel->header_height += config->panel_padding.y;
+        gui_draw_rectf(out, x, y, w, panel->header_height, *header);
+
+        clip.x = x; clip.w = w;
+        clip.y = y + panel->header_height;
+        clip.h = h - panel->header_height;
+        if (panel->flags & GUI_PANEL_SCROLLBAR)
+            clip.h -= config->panel_padding.y;
+        gui_push_clip(out, &clip);
+    } else {
+        clip.x = x; clip.y = y;
+        clip.w = w; clip.h = h;
+        if (panel->flags & GUI_PANEL_SCROLLBAR)
+            clip.h -= config->panel_padding.y;
+        gui_push_clip(out, &clip);
+        panel->header_height = config->panel_padding.y + config->item_padding.y;
+    }
+
+    panel->out = out;
+    panel->x = x;
+    panel->y = y;
+    panel->width = w;
+    panel->at_y = y;
+    panel->flags = f;
+    panel->index = 0;
+    panel->row_columns = 0;
+    panel->row_height = panel->header_height;
+
     if (panel->flags & GUI_PANEL_SCROLLBAR) {
         panel->width -= config->scrollbar_width;
         panel->height = (panel->flags & GUI_PANEL_HEADER) ?
             (h - panel->header_height) : h;
     }
 
-    i = text;
-    label_x = x + config->panel_padding.x + config->item_padding.x;
-    label_y = y + config->panel_padding.y;
-    label_w = w - 2 * config->panel_padding.x - 2 * config->item_padding.x;
-    label_h = panel->font->height + 2 * config->item_padding.y;
-    while (*i++ != '\0') text_len++;
-    gui_draw_string(panel->out, panel->font, label_x, label_y, label_w, label_h,
-        config->colors[GUI_COLOR_TEXT], (const gui_char*)text, text_len);
+    if (panel->flags & GUI_PANEL_BORDER) {
+        const struct gui_color *color;
+        color = &config->colors[GUI_COLOR_BORDER];
+        gui_draw_line(panel->out, x, y, x + w, y, *color);
+    }
+
     return ret;
 }
 
@@ -1615,11 +1717,67 @@ gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len,
     button.foreground = config->colors[GUI_COLOR_BUTTON_BORDER];
     button.font = config->colors[GUI_COLOR_TEXT];
     button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
+    button.highlight_font = config->colors[GUI_COLOR_BUTTON_HOVER_FONT];
+    return gui_button_text(panel->out, &button, str, len, panel->font, panel->in);
+}
+
+gui_int
+gui_panel_button_invisible(struct gui_panel *panel, const char *str, gui_size len,
+    enum gui_button_behavior behavior)
+{
+    struct gui_rect bounds;
+    struct gui_button button;
+    const struct gui_config *config;
+    const struct gui_color invis = {0,0,0,255};
+
+    if (!panel || !panel->config || !panel->in || !panel->out) return 0;
+    if (!panel->font || panel->minimized) return 0;
+    gui_panel_alloc_space(&bounds, panel);
+    config = panel->config;
+
+    button.x = bounds.x;
+    button.y = bounds.y;
+    button.w = bounds.w;
+    button.h = bounds.h;
+    button.behavior = behavior;
+    button.pad_x = config->item_padding.x;
+    button.pad_y = config->item_padding.y;
+    button.background = invis;
+    button.foreground = invis;
+    button.font = config->colors[GUI_COLOR_TEXT];
+    button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
+    button.highlight_font = config->colors[GUI_COLOR_BUTTON_HOVER_FONT];
     return gui_button_text(panel->out, &button, str, len, panel->font, panel->in);
 }
 
+gui_int gui_panel_button_color(struct gui_panel *panel, const struct gui_color color,
+    enum gui_button_behavior behavior)
+{
+    struct gui_rect bounds;
+    struct gui_button button;
+    const struct gui_config *config;
+
+    if (!panel || !panel->config || !panel->in || !panel->out) return 0;
+    if (!panel->font || panel->minimized) return 0;
+    gui_panel_alloc_space(&bounds, panel);
+    config = panel->config;
+
+    button.x = bounds.x;
+    button.y = bounds.y;
+    button.w = bounds.w;
+    button.h = bounds.h;
+    button.behavior = behavior;
+    button.pad_x = config->item_padding.x;
+    button.pad_y = config->item_padding.y;
+    button.background = color;
+    button.foreground = color;
+    button.highlight = color;
+    button.highlight_font = config->colors[GUI_COLOR_BUTTON_HOVER_FONT];
+    return gui_button_text(panel->out, &button, NULL, 0, panel->font, panel->in);
+}
+
 gui_int
-gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d,
+gui_panel_button_triangle(struct gui_panel *panel, enum gui_heading heading,
     enum gui_button_behavior behavior)
 {
     struct gui_rect bounds;
@@ -1642,7 +1800,8 @@ gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d,
     button.foreground = config->colors[GUI_COLOR_BUTTON_BORDER];
     button.font = config->colors[GUI_COLOR_TEXT];
     button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
-    return gui_button_triangle(panel->out, &button, d, panel->in);
+    button.highlight_font = config->colors[GUI_COLOR_BUTTON_HOVER_FONT];
+    return gui_button_triangle(panel->out, &button, heading, panel->in);
 }
 
 gui_int
@@ -1672,6 +1831,42 @@ gui_panel_button_image(struct gui_panel *panel, gui_texture tex,
     return gui_button_image(panel->out, &button, tex, from, to, panel->in);
 }
 
+gui_int
+gui_panel_button_toggle(struct gui_panel *panel, const char *str, gui_size len,
+    gui_int value)
+{
+    struct gui_rect bounds;
+    struct gui_button button;
+    const struct gui_config *config;
+
+    if (!panel || !panel->config || !panel->in || !panel->out) return 0;
+    if (!panel->font || panel->minimized) return 0;
+    gui_panel_alloc_space(&bounds, panel);
+    config = panel->config;
+
+    button.x = bounds.x;
+    button.y = bounds.y;
+    button.w = bounds.w;
+    button.h = bounds.h;
+    button.behavior = GUI_BUTTON_SWITCH;
+    button.pad_x = config->item_padding.x;
+    button.pad_y = config->item_padding.y;
+    if (!value) {
+        button.background = config->colors[GUI_COLOR_BUTTON];
+        button.foreground = config->colors[GUI_COLOR_BUTTON_BORDER];
+        button.font = config->colors[GUI_COLOR_TEXT];
+        button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
+    } else {
+        button.background = config->colors[GUI_COLOR_BUTTON_HOVER];
+        button.foreground = config->colors[GUI_COLOR_BUTTON_BORDER];
+        button.font = config->colors[GUI_COLOR_BUTTON];
+        button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
+    }
+    if (gui_button_text(panel->out, &button, str, len, panel->font, panel->in))
+        value = !value;
+    return value;
+}
+
 gui_int
 gui_panel_toggle(struct gui_panel *panel, const char *text, gui_size length,
     gui_int is_active)
@@ -1702,7 +1897,7 @@ gui_panel_toggle(struct gui_panel *panel, const char *text, gui_size length,
 
 gui_float
 gui_panel_slider(struct gui_panel *panel, gui_float min_value, gui_float value,
-    gui_float max_value, gui_float value_step)
+    gui_float max_value, gui_float value_step, enum gui_direction direction)
 {
     struct gui_rect bounds;
     struct gui_slider slider;
@@ -1725,12 +1920,14 @@ gui_panel_slider(struct gui_panel *panel, gui_float min_value, gui_float value,
     slider.step = value_step;
     slider.background = config->colors[GUI_COLOR_SLIDER];
     slider.foreground = config->colors[GUI_COLOR_SLIDER_CURSOR];
-    return gui_slider(panel->out, &slider, panel->in);
+    if (direction == GUI_HORIZONTAL)
+        return gui_slider(panel->out, &slider, panel->in);
+    return gui_slider_vertical(panel->out, &slider, panel->in);
 }
 
 gui_size
 gui_panel_progress(struct gui_panel *panel, gui_size cur_value, gui_size max_value,
-    gui_bool is_modifyable)
+    gui_bool is_modifyable, enum gui_direction direction)
 {
     struct gui_rect bounds;
     struct gui_progress prog;
@@ -1752,7 +1949,9 @@ gui_panel_progress(struct gui_panel *panel, gui_size cur_value, gui_size max_val
     prog.modifyable = is_modifyable;
     prog.background = config->colors[GUI_COLOR_PROGRESS];
     prog.foreground = config->colors[GUI_COLOR_PROGRESS_CURSOR];
-    return gui_progress(panel->out, &prog, panel->in);
+    if (direction == GUI_HORIZONTAL)
+        return gui_progress(panel->out, &prog, panel->in);
+    return gui_progress_vertical(panel->out, &prog, panel->in);
 }
 
 gui_int
@@ -1895,6 +2094,39 @@ gui_panel_histo(struct gui_panel *panel, const gui_float *values, gui_size count
     return gui_histo(panel->out, &histo, panel->in);
 }
 
+gui_float
+gui_panel_list(struct gui_panel *panel, gui_bool *selection,
+    const char *items[], gui_size item_count, gui_float offset)
+{
+    gui_size i;
+    struct gui_panel list;
+    struct gui_config config;
+    const struct gui_config *temp = panel->config;
+    if (panel->minimized) return 0;
+    memcopy(&config, panel->config, sizeof(struct gui_config));
+    config.panel_padding.y = 0.0f;
+    config.item_padding.x = 0.0f;
+    config.item_padding.y = 0.0f;
+    config.item_spacing.x = 0.0f;
+    config.item_spacing.y = 0.0f;
+    panel->config = &config;
+
+    if (!panel || !items || !item_count || !selection) return 0;
+    gui_panel_group_begin(&list, NULL, panel);
+    list.offset = offset;
+    config.panel_padding.x = 1.0f;
+    gui_panel_layout(&list, 30, 1);
+    for (i = 0; i < item_count; i++) {
+        selection[i] = gui_panel_button_toggle(&list, items[i],
+            strsiz(items[i]), selection[i]);
+    }
+    gui_panel_group_end(&list);
+    panel->config = temp;
+    if (list.offset > 0)
+        offset = list.offset;
+    return offset;
+}
+
 void
 gui_panel_group_begin(struct gui_panel *group, const char *title, struct gui_panel *panel)
 {

+ 29 - 11
gui.h

@@ -8,14 +8,17 @@
 /*
  *  ------------- TODO-List ------------
  * - Input cursor is fucked!!!
+ * - Scrollbar is fucked!!!
+ * - Header is fucked!!!
+ * - Visual bugs!!!
  * - panel
- *      o Group (1)
+ *      o group title
+ *      o included tabs
  *      o Moveable
  *      o Scaleable
  *      o Tabs (2)
  *      o Icon
  *      o combobox
- *      o listView  (3)
  *      o treeView
  *      o textBox
  * ---------------------------------------
@@ -37,7 +40,8 @@ typedef unsigned long gui_size;
 typedef gui_char gui_glyph[GUI_UTF_SIZE];
 
 enum {gui_false, gui_true};
-enum gui_direction {GUI_UP, GUI_RIGHT, GUI_DOWN, GUI_LEFT};
+enum gui_heading {GUI_UP, GUI_RIGHT, GUI_DOWN, GUI_LEFT};
+enum gui_direction {GUI_HORIZONTAL, GUI_VERTICAL};
 struct gui_color {gui_byte r,g,b,a;};
 struct gui_colorf {gui_float r,g,b,a;};
 struct gui_texCoord {gui_float u,v;};
@@ -170,8 +174,9 @@ struct gui_button {
     enum gui_button_behavior behavior;
     struct gui_color background;
     struct gui_color foreground;
-    struct gui_color highlight;
     struct gui_color font;
+    struct gui_color highlight;
+    struct gui_color highlight_font;
 };
 
 struct gui_toggle {
@@ -286,8 +291,9 @@ enum gui_colors {
     GUI_COLOR_BORDER,
     GUI_COLOR_TITLEBAR,
     GUI_COLOR_BUTTON,
-    GUI_COLOR_BUTTON_HOVER,
     GUI_COLOR_BUTTON_BORDER,
+    GUI_COLOR_BUTTON_HOVER,
+    GUI_COLOR_BUTTON_HOVER_FONT,
     GUI_COLOR_TOGGLE,
     GUI_COLOR_TOGGLE_ACTIVE,
     GUI_COLOR_SCROLL,
@@ -374,7 +380,7 @@ gui_int gui_button_text(struct gui_draw_buffer *buf, const struct gui_button *bu
                     const char *text, gui_size len, const struct gui_font *font,
                     const struct gui_input *in);
 gui_int gui_button_triangle(struct gui_draw_buffer *buffer, struct gui_button* button,
-                    enum gui_direction direction, const struct gui_input *in);
+                    enum gui_heading heading, const struct gui_input *in);
 gui_int gui_button_image(struct gui_draw_buffer *buffer, struct gui_button* button,
                     gui_texture tex, struct gui_texCoord from, struct gui_texCoord to,
                     const struct gui_input *in);
@@ -382,8 +388,12 @@ gui_int gui_toggle(struct gui_draw_buffer *buf, const struct gui_toggle *toggle,
                     const struct gui_font *font, const struct gui_input *in);
 gui_float gui_slider(struct gui_draw_buffer *buf, const struct gui_slider *slider,
                     const struct gui_input *in);
+gui_float gui_slider_vertical(struct gui_draw_buffer *buf,
+                    const struct gui_slider *slider, const struct gui_input *in);
 gui_size gui_progress(struct gui_draw_buffer *buf, const struct gui_progress *prog,
                     const struct gui_input *in);
+gui_size gui_progress_vertical(struct gui_draw_buffer *buf, const struct gui_progress *prog,
+                    const struct gui_input *in);
 gui_int gui_input(struct gui_draw_buffer *buf,  gui_char *buffer, gui_size *length,
                     const struct gui_input_field *input,
                     const struct gui_font *font, const struct gui_input *in);
@@ -404,25 +414,31 @@ gui_int gui_plot(struct gui_draw_buffer *buf, const struct gui_plot *plot,
 void gui_default_config(struct gui_config *config);
 void gui_panel_init(struct gui_panel *panel, const struct gui_config *config,
                         const struct gui_font *font, const struct gui_input *input);
-gui_int gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *q,
-                        const char *t, gui_flags f,
+gui_int gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *buffer,
+                        const char *text, gui_flags flags,
                         gui_float x, gui_float y, gui_float w, gui_float h);
 void gui_panel_layout(struct gui_panel *panel, gui_float height, gui_size cols);
 void gui_panel_seperator(struct gui_panel *panel, gui_size cols);
 void gui_panel_text(struct gui_panel *panel, const char *str, gui_size len);
 gui_int gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len,
                         enum gui_button_behavior behavior);
-gui_int gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d,
+gui_int gui_panel_button_invisible(struct gui_panel *panel, const char *str, gui_size len,
+                        enum gui_button_behavior behavior);
+gui_int gui_panel_button_color(struct gui_panel *panel, const struct gui_color color,
+                        enum gui_button_behavior behavior);
+gui_int gui_panel_button_triangle(struct gui_panel *panel, enum gui_heading heading,
                         enum gui_button_behavior behavior);
 gui_int gui_panel_button_image(struct gui_panel *panel, gui_texture tex,
                         struct gui_texCoord from, struct gui_texCoord to,
                         enum gui_button_behavior behavior);
+gui_int gui_panel_button_toggle(struct gui_panel *panel, const char *str, gui_size len,
+                        gui_int value);
 gui_int gui_panel_toggle(struct gui_panel *panel, const char *str, gui_size len,
                         gui_int active);
 gui_float gui_panel_slider(struct gui_panel *panel, gui_float min, gui_float v,
-                        gui_float max, gui_float step);
+                        gui_float max, gui_float step, enum gui_direction d);
 gui_size gui_panel_progress(struct gui_panel *panel, gui_size cur, gui_size max,
-                        gui_bool modifyable);
+                        gui_bool modifyable, enum gui_direction d);
 gui_int gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *len,
                         gui_size max, enum gui_input_filter filter,  gui_bool active);
 gui_size gui_panel_command(struct gui_panel *panel,  gui_char *buffer, gui_size *length,
@@ -433,6 +449,8 @@ gui_int gui_panel_plot(struct gui_panel *panel, const gui_float *values,
                         gui_size value_count);
 gui_int gui_panel_histo(struct gui_panel *panel, const gui_float *values,
                         gui_size value_count);
+gui_float gui_panel_list(struct gui_panel *panel, gui_bool *selected,
+                        const char *items[], gui_size item_count, gui_float offset);
 void gui_panel_group_begin(struct gui_panel *panel, const char *t, struct gui_panel *tab);
 void gui_panel_group_end(struct gui_panel *tab);
 void gui_panel_end(struct gui_panel *panel);

+ 6 - 10
opengl.c

@@ -59,7 +59,8 @@ struct GUI {
     struct gui_font *font;
     struct gui_config config;
     struct gui_panel panel;
-    struct gui_panel group;
+    gui_bool selection[4];
+    gui_float seloff;
 
     /* State */
     gui_char input_text[INPUT_MAX];
@@ -441,6 +442,7 @@ main(int argc, char *argv[])
     static const char *s[] = {"inactive", "active"};
     static const gui_float values[] = {10.0f, 12.5f, 18.0f, 15.0f, 25.0f, 30.0f};
     static GLint att[] = {GLX_RGBA, GLX_DEPTH_SIZE,24, GLX_DOUBLEBUFFER, None};
+    static const char *sel[] = {"item0", "item1", "item2", "item3"};
 
     /* Window */
     UNUSED(argc); UNUSED(argv);
@@ -507,8 +509,8 @@ main(int argc, char *argv[])
         gui_panel_layout(&gui.panel, 30, 1);
         if (gui_panel_button_text(&gui.panel, "button", 6, GUI_BUTTON_SWITCH))
             fprintf(stdout, "button pressed!\n");
-        gui.slider = gui_panel_slider(&gui.panel, 0.0f, gui.slider, 10.0f, 1.0f);
-        gui.prog = gui_panel_progress(&gui.panel, gui.prog, 100, gui_true);
+        gui.slider = gui_panel_slider(&gui.panel, 0.0f, gui.slider, 10.0f, 1.0f, GUI_HORIZONTAL);
+        gui.prog = gui_panel_progress(&gui.panel, gui.prog, 100, gui_true, GUI_HORIZONTAL);
         gui.selected = gui_panel_toggle(&gui.panel, s[gui.selected],
                                         strlen(s[gui.selected]), gui.selected);
         gui.typing = gui_panel_input(&gui.panel, gui.input_text, &gui.input_len, INPUT_MAX,
@@ -517,15 +519,9 @@ main(int argc, char *argv[])
                                         &gui.submitting);
         gui.spinning = gui_panel_spinner(&gui.panel, 0, &gui.spinner, 250, 10, gui.spinning);
         gui_panel_layout(&gui.panel, 100, 1);
-        gui_panel_group_begin(&gui.group, NULL, &gui.panel);
-        gui_panel_layout(&gui.group, 30, 1);
-        if (gui_panel_button_text(&gui.group, "button", 6, GUI_BUTTON_SWITCH))
-            fprintf(stdout, "button group pressed!\n");
-        gui_panel_group_end(&gui.group);
-        gui_panel_layout(&gui.panel, 100, 1);
         gui_panel_plot(&gui.panel, values, LEN(values));
         gui_panel_histo(&gui.panel, values, LEN(values));
-        gui_panel_end(&gui.panel);
+        gui.seloff = gui_panel_list(&gui.panel, gui.selection, sel, LEN(sel), gui.seloff);
         gui_panel_end(&gui.panel);
         gui_end(&gui.out, &gui.draw_list, NULL);
         /* ---------------------------------------------------------*/