More scrollable improvements
This commit is contained in:
+2
-2
@@ -50,9 +50,9 @@ uiman_init ()
|
||||
Widget_add_child_weighed (debug_menu, chkboxes, 1);
|
||||
|
||||
Widget *content = Widget_label_new ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", TEXT_ALIGN_LEFT);
|
||||
VEC2_SETI (content->size, 3000, 100);
|
||||
VEC2_SETI (content->size, 3000, 500);
|
||||
|
||||
Widget *scrollable_window = Widget_composite_scrollable_make (TRUE, content);
|
||||
Widget *scrollable_window = Widget_composite_scrollable_make (content);
|
||||
Widget_set_background_image (scrollable_window, RESTEX ("terrain4"));
|
||||
VEC2_SETI (scrollable_window->position, 390, 32);
|
||||
VEC2_SETI (scrollable_window->size, 350, 350);
|
||||
|
||||
+100
-64
@@ -42,10 +42,9 @@ Widget_label_new (const char *text, TextAlignment alignment)
|
||||
}
|
||||
|
||||
Widget *
|
||||
Widget_scrollable_new (gboolean horizontal)
|
||||
Widget_scrollable_new ()
|
||||
{
|
||||
Widget *e = ui_el_new_internal (WIDGET_SCROLLABLE);
|
||||
e->scrollable.horizontal = horizontal;
|
||||
e->scrollable.scroll_amount = 5.0;
|
||||
return e;
|
||||
}
|
||||
@@ -71,10 +70,10 @@ Widget_add_child_weighed (Widget *parent, Widget *child, float layout_weight)
|
||||
}
|
||||
|
||||
void
|
||||
Widget_set_icon (Widget *widget, unsigned int icon_index)
|
||||
Widget_set_icon (Widget *widget, WidgetIcon icon)
|
||||
{
|
||||
widget->has_icon = TRUE;
|
||||
widget->icon_index = icon_index;
|
||||
widget->icon = icon;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -118,11 +117,15 @@ Widget_label_printf (Widget *widget, const char *format, ...)
|
||||
}
|
||||
|
||||
void
|
||||
Widget_scrollable_scroll (Widget *widget, bool up)
|
||||
Widget_scrollable_scroll (Widget *widget, vec2 direction)
|
||||
{
|
||||
widget->scrollable.scroll_position += up ? widget->scrollable.scroll_amount : -widget->scrollable.scroll_amount;
|
||||
float max_scroll = glm_max (0.0f, widget->scrollable.content_size - (widget->scrollable.horizontal ? widget->size[0] : widget->size[1]));
|
||||
widget->scrollable.scroll_position = glm_clamp (widget->scrollable.scroll_position, 0.0f, max_scroll);
|
||||
glm_vec2_muladds (direction, widget->scrollable.scroll_amount, widget->scrollable.scroll_position);
|
||||
widget->scrollable.scroll_position[0] =
|
||||
glm_clamp (widget->scrollable.scroll_position[0], 0.0f,
|
||||
glm_max (0.0f, widget->scrollable.content_size[0] - widget->size[0]));
|
||||
widget->scrollable.scroll_position[1] =
|
||||
glm_clamp (widget->scrollable.scroll_position[1], 0.0f,
|
||||
glm_max (0.0f, widget->scrollable.content_size[1] - widget->size[1]));
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -148,20 +151,15 @@ Widget_find_xy (Widget *widget, vec2 pos)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec2 pos_scrolled = { pos[0], pos[1] };
|
||||
vec2 pos_scrolled;
|
||||
glm_vec2_copy (pos, pos_scrolled);
|
||||
|
||||
if (widget->kind == WIDGET_SCROLLABLE)
|
||||
{
|
||||
if (widget->scrollable.horizontal)
|
||||
{
|
||||
pos_scrolled[0] += widget->scrollable.scroll_position;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos_scrolled[1] += widget->scrollable.scroll_position;
|
||||
}
|
||||
glm_vec2_add (pos_scrolled, widget->scrollable.scroll_position, pos_scrolled);
|
||||
}
|
||||
|
||||
if (!Widget_hit_test (widget, pos))
|
||||
if (!Widget_hit_test (widget, pos_scrolled))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -169,7 +167,7 @@ Widget_find_xy (Widget *widget, vec2 pos)
|
||||
for (int i = widget->children->len - 1; i >= 0; --i)
|
||||
{
|
||||
Widget *child = g_array_index (widget->children, Widget *, i);
|
||||
Widget *found = Widget_find_xy (child, pos);
|
||||
Widget *found = Widget_find_xy (child, pos_scrolled);
|
||||
|
||||
if (found != NULL)
|
||||
{
|
||||
@@ -247,42 +245,36 @@ Widget_label_render_text (Widget *widget, mat4 projection)
|
||||
}
|
||||
|
||||
void
|
||||
Widget_scrollable_layout (Widget *parent, gboolean horizontal)
|
||||
Widget_scrollable_layout (Widget *parent)
|
||||
{
|
||||
float content_size = 0.0f;
|
||||
vec2 content_size = { 0.0 };
|
||||
Widget *child;
|
||||
|
||||
WIDGET_FOREACH_CHILD (parent, i, child)
|
||||
{
|
||||
if (horizontal)
|
||||
{
|
||||
child->position[1] = parent->position[1];
|
||||
child->size[1] = parent->size[1];
|
||||
|
||||
if (child->layout_weight > 0)
|
||||
{
|
||||
child->size[0] = child->layout_weight * parent->size[0];
|
||||
}
|
||||
|
||||
child->position[0] = parent->position[0] + content_size - parent->scrollable.scroll_position;
|
||||
content_size += child->size[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
child->position[0] = parent->position[0];
|
||||
child->size[0] = parent->size[0];
|
||||
child->position[0] = parent->position[0] - parent->scrollable.scroll_position[0];
|
||||
child->position[1] = parent->position[1] - parent->scrollable.scroll_position[1];
|
||||
|
||||
if (child->layout_weight > 0)
|
||||
{
|
||||
child->size[1] = child->layout_weight * parent->size[1];
|
||||
}
|
||||
if (child->layout_weight > 0.0)
|
||||
{
|
||||
child->size[0] = child->layout_weight * parent->size[0];
|
||||
child->size[1] = child->layout_weight * parent->size[1];
|
||||
}
|
||||
|
||||
child->position[1] = parent->position[1] + content_size - parent->scrollable.scroll_position;
|
||||
content_size += child->size[1];
|
||||
}
|
||||
float right = child->position[0] + child->size[0];
|
||||
float bottom = child->position[1] + child->size[1];
|
||||
|
||||
if (right > content_size[0])
|
||||
{
|
||||
content_size[0] = right;
|
||||
}
|
||||
if (bottom > content_size[1])
|
||||
{
|
||||
content_size[1] = bottom;
|
||||
}
|
||||
}
|
||||
|
||||
parent->scrollable.content_size = content_size;
|
||||
glm_vec2_copy (content_size, parent->scrollable.content_size);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -398,7 +390,7 @@ Widget_render (Widget *widget, mat4 projection, int window_height)
|
||||
|
||||
if (widget->kind == WIDGET_SCROLLABLE)
|
||||
{
|
||||
Widget_scrollable_layout (widget, widget->scrollable.horizontal);
|
||||
Widget_scrollable_layout (widget);
|
||||
}
|
||||
|
||||
program_use (RESPRG ("uiwidget"));
|
||||
@@ -421,7 +413,7 @@ Widget_render (Widget *widget, mat4 projection, int window_height)
|
||||
}
|
||||
|
||||
program_set_int (RESPRG ("uiwidget"), "has_icon", widget->has_icon);
|
||||
program_set_float (RESPRG ("uiwidget"), "icon_index", widget->icon_index);
|
||||
program_set_float (RESPRG ("uiwidget"), "icon_index", widget->icon);
|
||||
texture_use (RESTEX ("icons"), 1);
|
||||
|
||||
mat3 model;
|
||||
@@ -520,7 +512,7 @@ void
|
||||
uicb_checkbox_show_flag (Widget *self, void *userdata)
|
||||
{
|
||||
char *flag = userdata;
|
||||
self->icon_index = flags_get (flag) ? ICON_CHECKBOX_CHECKED : ICON_CHECKBOX_UNCHECKED;
|
||||
self->icon = flags_get (flag) ? ICON_CHECKBOX_CHECKED : ICON_CHECKBOX_UNCHECKED;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -544,7 +536,7 @@ uicb_scrollable_scroll_down (Widget *self, void *userdata)
|
||||
{
|
||||
UNUSED (self);
|
||||
Widget *scrollable = userdata;
|
||||
Widget_scrollable_scroll (scrollable, FALSE);
|
||||
Widget_scrollable_scroll (scrollable, (vec2) { 0.0, 1.0 });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -552,7 +544,23 @@ uicb_scrollable_scroll_up (Widget *self, void *userdata)
|
||||
{
|
||||
UNUSED (self);
|
||||
Widget *scrollable = userdata;
|
||||
Widget_scrollable_scroll (scrollable, TRUE);
|
||||
Widget_scrollable_scroll (scrollable, (vec2) { 0.0, -1.0 });
|
||||
}
|
||||
|
||||
void
|
||||
uicb_scrollable_scroll_left (Widget *self, void *userdata)
|
||||
{
|
||||
UNUSED (self);
|
||||
Widget *scrollable = userdata;
|
||||
Widget_scrollable_scroll (scrollable, (vec2) { -1.0, 0.0 });
|
||||
}
|
||||
|
||||
void
|
||||
uicb_scrollable_scroll_right (Widget *self, void *userdata)
|
||||
{
|
||||
UNUSED (self);
|
||||
Widget *scrollable = userdata;
|
||||
Widget_scrollable_scroll (scrollable, (vec2) { 1.0, 0.0 });
|
||||
}
|
||||
|
||||
Widget *
|
||||
@@ -613,29 +621,57 @@ Widget_composite_checkbox_make (const char *label, char *flag)
|
||||
}
|
||||
|
||||
Widget *
|
||||
Widget_composite_scrollable_make (gboolean horizontal, Widget *content)
|
||||
Widget_composite_scrollable_make (Widget *content)
|
||||
{
|
||||
Widget *cont1 = Widget_container_new (!horizontal, 8, 4);
|
||||
Widget *scrollable = Widget_scrollable_new (horizontal);
|
||||
Widget *cont_main = Widget_container_new (FALSE, 8, 4);
|
||||
Widget *scrollable = Widget_scrollable_new ();
|
||||
Widget_add_child (scrollable, content);
|
||||
|
||||
Widget *scrollbarcont = Widget_container_new (horizontal, 0, 0);
|
||||
Widget *scroll_down = Widget_plain_new ();
|
||||
Widget *scroll_up = Widget_plain_new ();
|
||||
Widget *scroll_down = Widget_plain_new ();
|
||||
|
||||
Widget_set_icon (scroll_up, ICON_SPINNER_RIGHT);
|
||||
Widget_set_icon (scroll_up, ICON_SPINNER_LEFT);
|
||||
Widget_set_on_left_click (scroll_up, uicb_scrollable_scroll_up, scrollable);
|
||||
scroll_up->aspect_ratio = 1.0;
|
||||
Widget_set_icon (scroll_down, ICON_SPINNER_LEFT);
|
||||
|
||||
Widget_set_icon (scroll_down, ICON_SPINNER_RIGHT);
|
||||
Widget_set_on_left_click (scroll_down, uicb_scrollable_scroll_down, scrollable);
|
||||
scroll_down->aspect_ratio = 1.0;
|
||||
|
||||
Widget_add_child_weighed (scrollbarcont, scroll_down, 1.0);
|
||||
Widget_add_child_weighed (scrollbarcont, Widget_plain_new (), 1.0);
|
||||
Widget_add_child_weighed (scrollbarcont, scroll_up, 1.0);
|
||||
Widget *cont_horiz = Widget_container_new (TRUE, 0, 4);
|
||||
Widget *scrollbar_vertical = Widget_container_new (FALSE, 0, 0);
|
||||
|
||||
Widget_add_child_weighed (cont1, scrollable, 0.93);
|
||||
Widget_add_child_weighed (cont1, scrollbarcont, 0.07);
|
||||
Widget_add_child_weighed (scrollbar_vertical, scroll_up, 1);
|
||||
Widget_add_child_weighed (scrollbar_vertical, Widget_plain_new (), 1);
|
||||
Widget_add_child_weighed (scrollbar_vertical, scroll_down, 1);
|
||||
|
||||
Widget_add_child_weighed (cont_horiz, scrollable, 0.93);
|
||||
Widget_add_child_weighed (cont_horiz, scrollbar_vertical, 0.07);
|
||||
|
||||
Widget_add_child_weighed (cont_main, cont_horiz, 0.93);
|
||||
|
||||
Widget *scroll_left = Widget_plain_new ();
|
||||
Widget *scroll_right = Widget_plain_new ();
|
||||
|
||||
Widget_set_icon (scroll_left, ICON_SPINNER_LEFT);
|
||||
Widget_set_on_left_click (scroll_left, uicb_scrollable_scroll_left, scrollable);
|
||||
scroll_left->aspect_ratio = 1.0;
|
||||
|
||||
Widget_set_icon (scroll_right, ICON_SPINNER_RIGHT);
|
||||
Widget_set_on_left_click (scroll_right, uicb_scrollable_scroll_right, scrollable);
|
||||
scroll_right->aspect_ratio = 1.0;
|
||||
|
||||
Widget *scrollbar_horizontal = Widget_container_new (TRUE, 0, 0);
|
||||
|
||||
Widget *padding = Widget_plain_new ();
|
||||
padding->aspect_ratio = 1.0;
|
||||
|
||||
return cont1;
|
||||
Widget_add_child_weighed (scrollbar_horizontal, scroll_left, 1);
|
||||
Widget_add_child_weighed (scrollbar_horizontal, Widget_plain_new (), 1);
|
||||
Widget_add_child_weighed (scrollbar_horizontal, scroll_right, 1);
|
||||
Widget_add_child_weighed (scrollbar_horizontal, padding, 1);
|
||||
|
||||
Widget_add_child_weighed (cont_main, scrollbar_horizontal, 0.07);
|
||||
|
||||
return cont_main;
|
||||
}
|
||||
|
||||
+18
-12
@@ -13,10 +13,7 @@
|
||||
for (unsigned int i = 0; i < widget->children->len && \
|
||||
((child = g_array_index(widget->children, Widget *, i)), 1); ++i)
|
||||
|
||||
#define ICON_CHECKBOX_UNCHECKED 0
|
||||
#define ICON_CHECKBOX_CHECKED 1
|
||||
#define ICON_SPINNER_LEFT 2
|
||||
#define ICON_SPINNER_RIGHT 3
|
||||
|
||||
|
||||
typedef enum WidgetKind
|
||||
{
|
||||
@@ -49,12 +46,19 @@ typedef struct LabelWidget
|
||||
|
||||
typedef struct ScrollableWidget
|
||||
{
|
||||
gboolean horizontal;
|
||||
float scroll_position;
|
||||
float scroll_amount;
|
||||
float content_size;
|
||||
vec2 scroll_position;
|
||||
vec2 content_size;
|
||||
} ScrollableWidget;
|
||||
|
||||
typedef enum WidgetIcon
|
||||
{
|
||||
ICON_CHECKBOX_UNCHECKED = 0,
|
||||
ICON_CHECKBOX_CHECKED,
|
||||
ICON_SPINNER_LEFT,
|
||||
ICON_SPINNER_RIGHT
|
||||
} WidgetIcon;
|
||||
|
||||
typedef struct Widget
|
||||
{
|
||||
struct Widget *parent;
|
||||
@@ -83,7 +87,7 @@ typedef struct Widget
|
||||
unsigned int background_image;
|
||||
|
||||
gboolean has_icon;
|
||||
unsigned int icon_index;
|
||||
WidgetIcon icon;
|
||||
|
||||
float border_width;
|
||||
vec4 border_color;
|
||||
@@ -99,21 +103,21 @@ typedef struct Widget
|
||||
Widget *Widget_plain_new ();
|
||||
Widget *Widget_container_new (gboolean horizontal, float padding, float child_spacing);
|
||||
Widget *Widget_label_new (const char *text, TextAlignment alignment);
|
||||
Widget *Widget_scrollable_new (gboolean horizontal);
|
||||
Widget *Widget_scrollable_new ();
|
||||
|
||||
void Widget_add_child (Widget *parent, Widget *child);
|
||||
void Widget_add_child_weighed (Widget *parent, Widget *child,
|
||||
float layout_weight);
|
||||
|
||||
void Widget_set_background_image (Widget *widget, unsigned int image);
|
||||
void Widget_set_icon (Widget *widget, unsigned int icon_index);
|
||||
void Widget_set_icon (Widget *widget, WidgetIcon icon);
|
||||
void Widget_set_on_tick (Widget *widget, void (*on_tick) (Widget *, void *), void *userdata);
|
||||
void Widget_set_on_left_click (Widget *widget, void (*on_left_click) (Widget *, void *), void *userdata);
|
||||
|
||||
void Widget_label_set_text (Widget *widget, const char *text);
|
||||
void Widget_label_printf (Widget *widget, const char *format, ...);
|
||||
|
||||
void Widget_scrollable_scroll (Widget *widget, bool up);
|
||||
void Widget_scrollable_scroll (Widget *widget, vec2 direction);
|
||||
|
||||
Widget *Widget_find_xy (Widget *widget, vec2 point);
|
||||
|
||||
@@ -143,10 +147,12 @@ void uicb_decrement_int (Widget *self, void *userdata);
|
||||
|
||||
void uicb_scrollable_scroll_down (Widget *self, void *userdata);
|
||||
void uicb_scrollable_scroll_up (Widget *self, void *userdata);
|
||||
void uicb_scrollable_scroll_left (Widget *self, void *userdata);
|
||||
void uicb_scrollable_scroll_right (Widget *self, void *userdata);
|
||||
|
||||
Widget *Widget_label_make_int (const char *fmt, int *ptr, TextAlignment alignment);
|
||||
Widget *Widget_label_make_float (const char *fmt, float *ptr, TextAlignment alignment);
|
||||
|
||||
Widget *Widget_composite_spinner_make_int (const char *format, int *ptr);
|
||||
Widget *Widget_composite_checkbox_make (const char *label, char *flag);
|
||||
Widget *Widget_composite_scrollable_make (gboolean horizontal, Widget *content);
|
||||
Widget *Widget_composite_scrollable_make (Widget *content);
|
||||
|
||||
Reference in New Issue
Block a user