aboutsummaryrefslogtreecommitdiff
path: root/src/mgui/list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mgui/list.c')
-rw-r--r--src/mgui/list.c130
1 files changed, 84 insertions, 46 deletions
diff --git a/src/mgui/list.c b/src/mgui/list.c
index 58fc964..687906d 100644
--- a/src/mgui/list.c
+++ b/src/mgui/list.c
@@ -8,12 +8,15 @@
if num_items <= 2.
*/
+static int max_int(int a, int b) {
+ return a >= b ? a : b;
+}
+
mgui_list* mgui_list_create(mgui_list_direction direction) {
mgui_list *list = mgui_alloc(sizeof(mgui_list));
mgui_widget_init(&list->widget, MGUI_WIDGET_LIST);
list->direction = direction;
list->position = (mgl_vec2i){ 0, 0 };
- list->background_color = (mgl_color){ 0, 0, 0, 0 };
list->items = NULL;
list->items_capacity = 0;
list->num_items = 0;
@@ -22,7 +25,7 @@ mgui_list* mgui_list_create(mgui_list_direction direction) {
void mgui_list_destroy(mgui_list *list) {
for(size_t i = 0; i < list->num_items; ++i) {
- mgui_widget_destroy(list->items[i]);
+ mgui_widget_destroy(list->items[i].widget);
}
mgui_free(list->items);
mgui_free(list);
@@ -41,19 +44,71 @@ void mgui_list_set_position(mgui_list *self, mgl_vec2i position) {
self->position = position;
}
-void mgui_list_set_width(mgui_list *self, int width) {
- /* TODO: if direction is horizontal then put the widget in the center of its area */
- /* TODO: put the widget in the center for vertical as well, for items with a max size */
- /* TODO: support max size for widgets */
- if(self->direction == MGUI_LIST_VERTICAL) {
- for(size_t i = 0; i < self->num_items; ++i) {
- mgui_widget_set_width(self->items[i], width);
+void mgui_list_calculate_size(mgui_list *self, mgl_vec2i max_size) {
+ mgl_vec2i size = (mgl_vec2i){ 0, 0 };
+ switch(self->direction) {
+ case MGUI_LIST_HORIZONITAL: {
+ int num_expanded_widgets = 0;
+ for(size_t i = 0; i < self->num_items; ++i) {
+ mgui_widget *widget = self->items[i].widget;
+ if(widget->flags & MGUI_WIDGET_EXPAND_HORIZONTAL) {
+ ++num_expanded_widgets;
+ } else {
+ mgui_widget_calculate_size(widget, max_size);
+ size.x += widget->size.x;
+ size.y = max_int(size.y, widget->size.y);
+ max_size.x -= widget->size.x;
+ }
+ }
+
+ if(num_expanded_widgets == 0)
+ break;
+
+ max_size.x = max_size.x / num_expanded_widgets;
+
+ for(size_t i = 0; i < self->num_items; ++i) {
+ mgui_widget *widget = self->items[i].widget;
+ if(widget->flags & MGUI_WIDGET_EXPAND_HORIZONTAL) {
+ mgui_widget_calculate_size(widget, max_size);
+ widget->size = max_size;
+ size.x += widget->size.x;
+ size.y = max_int(size.y, widget->size.y);
+ }
+ }
+ break;
}
- }
-}
+ case MGUI_LIST_VERTICAL: {
+ int num_expanded_widgets = 0;
+ for(size_t i = 0; i < self->num_items; ++i) {
+ mgui_widget *widget = self->items[i].widget;
+ if(widget->flags & MGUI_WIDGET_EXPAND_VERTICAL) {
+ ++num_expanded_widgets;
+ } else {
+ mgui_widget_calculate_size(widget, max_size);
+ size.x = max_int(size.x, widget->size.x);
+ size.y += widget->size.y;
+ max_size.y -= widget->size.y;
+ }
+ }
+
+ if(num_expanded_widgets == 0)
+ break;
-void mgui_list_set_background_color(mgui_list *self, mgl_color color) {
- self->background_color = color;
+ max_size.y = max_size.y / num_expanded_widgets;
+
+ for(size_t i = 0; i < self->num_items; ++i) {
+ mgui_widget *widget = self->items[i].widget;
+ if(widget->flags & MGUI_WIDGET_EXPAND_VERTICAL) {
+ mgui_widget_calculate_size(widget, max_size);
+ widget->size = max_size;
+ size.x = max_int(size.x, widget->size.x);
+ size.y += widget->size.y;
+ }
+ }
+ break;
+ }
+ }
+ self->widget.size = size;
}
static void mgui_list_ensure_capacity(mgui_list *self, size_t new_capacity) {
@@ -73,63 +128,46 @@ static void mgui_list_ensure_capacity(mgui_list *self, size_t new_capacity) {
}
void mgui_list_append(mgui_list *self, mgui_widget *widget) {
- mgui_list_ensure_capacity(self, (self->num_items + 1) * sizeof(mgui_widget*));
- self->items[self->num_items] = widget;
+ mgui_widget_set_has_parent(widget);
+ mgui_list_ensure_capacity(self, (self->num_items + 1) * sizeof(mgui_list_item));
+ self->items[self->num_items].widget = widget;
++self->num_items;
}
void mgui_list_on_event(mgui_list *self, mgl_window *window, mgl_event *event) {
for(size_t i = 0; i < self->num_items; ++i) {
- mgui_widget_on_event(self->items[i], window, event);
+ mgui_widget_on_event(self->items[i].widget, window, event);
}
}
-static int max_int(int a, int b) {
- return a >= b ? a : b;
-}
-
/* TODO: Check if visible in scissor */
-mgl_vec2i mgui_list_draw(mgui_list *self, mgl_window *window) {
+void mgui_list_draw(mgui_list *self, mgl_window *window) {
mgl_vec2i position = self->position;
- /* TODO: */
- mgl_vec2i size = (mgl_vec2i){ 0, 0 };
-
- /* TODO:
- if(self->background_color.a > 0) {
- mgl_rectangle rect = {
- .position = { self->position.x, self->position.y },
- .size = { self->size.x, self->size.y },
- .color = self->background_color
- };
- mgl_rectangle_draw(mgl_get_context(), &rect);
- }
- */
/* TODO: Set scissor for each draw widget */
+ /* TODO: Only do this when a direct child widget is dirty */
+ //mgui_list_calculate_size(self);
+
switch(self->direction) {
case MGUI_LIST_HORIZONITAL: {
for(size_t i = 0; i < self->num_items; ++i) {
- mgui_widget_set_position(self->items[i], position);
- const mgl_vec2i widget_size = mgui_widget_draw(self->items[i], window);
- size.x += widget_size.x;
- size.y = max_int(size.y, widget_size.y);
- position.x += widget_size.x;
+ mgui_widget *widget = self->items[i].widget;
+ mgui_widget_set_position(widget, position);
+ mgui_widget_draw(widget, window);
+ position.x += widget->size.x;
}
break;
}
case MGUI_LIST_VERTICAL: {
for(size_t i = 0; i < self->num_items; ++i) {
- mgui_widget_set_position(self->items[i], position);
- const mgl_vec2i widget_size = mgui_widget_draw(self->items[i], window);
- size.x = max_int(size.x, widget_size.x);
- size.y += widget_size.y;
- position.y += widget_size.y;
+ mgui_widget *widget = self->items[i].widget;
+ mgui_widget_set_position(widget, position);
+ mgui_widget_draw(widget, window);
+ position.y += widget->size.y;
}
break;
}
}
-
- return size;
}