commit - 86de45269288906cd51d0b8d6d87bd0dca48e65c
commit + 8a5e9b3a1aa94d81042445f7bf7d8249bc96b3ba
blob - 8b61cd2a318aec2f93ebbb799ddd1ff423e21a8c
blob + 6459d7e0ee558315dd667e8f5aeae620a782e001
--- layout.c
+++ layout.c
break;
}
/*
- * As far as I'm aware of, Tk's pack is just a rectangle that shrinks
- * depending on the side of the widget being added.
- *
- * The fill attribute is a bit tricky. You can set it to x, y and both
- * but you have to keep in mind that x only works on side top and bottom
- * and y works on side left and right.
- *
- * Keep in mind that expand can make the fill atributte that doesn't
- * usually work on a side to changes its geometry.
- *
- * Expand is pretty much dividing the remaining space among children.
+ * Lots of suffering into implementing this one :D
*/
case AUI_LAYOUT_PACK: {
struct aui_geometry space = widget->geom;
unsigned int vexpand = 0;
unsigned int req_w = 0;
unsigned int req_h = 0;
+ int extra_w = 0;
+ int extra_h = 0;
+ int hextra = 0;
+ int vextra = 0;
+ /*
+ * Compute requested and extra space. hextra and vextra are only set
+ * if there is no top/bottom widgets succeeding it. This guarantees
+ * a proper request size.
+ */
TAILQ_FOREACH(child, &widget->queue, entries) {
if (child->mapped == 0)
continue;
struct aui_geometry cgeom = child->in_ops->get_min_size(child);
+ switch (child->packpar.side) {
+ case AUI_SIDE_TOP:
+ case AUI_SIDE_BOTTOM:
+ vexpand = (child->packpar.expand) ? vexpand + 1 : vexpand;
+ if (vextra) vextra = 0;
+ req_h += cgeom.height;
+ hextra = (cgeom.width > hextra) ? cgeom.width : hextra;
+ break;
+ case AUI_SIDE_LEFT:
+ case AUI_SIDE_RIGHT:
+ hexpand = (child->packpar.expand) ? hexpand + 1 : hexpand;
+ if (hextra) hextra = 0;
+ vextra = (cgeom.height > vextra) ? cgeom.height : vextra;
+ req_w += cgeom.width;
+ break;
+ default:
+ break;
+ }
+ }
+ req_w += hextra;
+ req_h += vextra;
+
+ if (req_w > space.width)
+ req_w = space.width;
+
+ if (req_h > space.height)
+ req_h = space.height;
+
+ extra_w = space.width - req_w;
+ extra_h = space.height - req_h;
+
+ /*
+ * Making sure each widget consume space before expension
+ * for their area.
+ */
+ TAILQ_FOREACH(child, &widget->queue, entries) {
+ if (child->mapped == 0)
+ continue;
+
+ struct aui_geometry min = child->in_ops->get_min_size(child);
+
switch (child->packpar.side) {
case AUI_SIDE_TOP:
- cgeom.width = (cgeom.width > space.width) ? space.width : cgeom.width;
- cgeom.height = (cgeom.height > space.height) ? space.height : cgeom.height;
+ child->packarea = (struct aui_geometry) {
+ .x = space.x,
+ .y = space.y,
+ .width = space.width,
+ .height = min.height,
+ };
- vexpand = (child->packpar.expand) ? vexpand + 1 : vexpand;
+ if (child->packarea.height > space.height) {
+ child->packarea.height = space.height;
+ }
- switch (child->packpar.fill) {
- case AUI_FILL_X:
- cgeom.width = space.width;
- break;
- case AUI_FILL_BOTH:
- cgeom.width = space.width;
- break;
- case AUI_FILL_NONE:
- default:
- break;
+ space.y += child->packarea.height;
+ space.height -= child->packarea.height;
+ break;
+ case AUI_SIDE_BOTTOM:
+ child->packarea = (struct aui_geometry) {
+ .x = space.x,
+ .y = space.y,
+ .width = space.width,
+ .height = min.height
+ };
+
+ if (child->packarea.height > space.height) {
+ child->packarea.height = space.height;
}
- switch (child->packpar.anchor) {
- case AUI_ANCHOR_CENTER:
- case AUI_ANCHOR_N:
- case AUI_ANCHOR_S:
- cgeom.x = space.x + space.width / 2 - cgeom.width / 2;
- cgeom.y = space.y;
- break;
- case AUI_ANCHOR_NW:
- case AUI_ANCHOR_SW:
- case AUI_ANCHOR_W:
- cgeom.x = space.x;
- cgeom.y = space.y;
- break;
- case AUI_ANCHOR_NE:
- case AUI_ANCHOR_SE:
- case AUI_ANCHOR_E:
- cgeom.x = space.x + space.width - cgeom.width;
- cgeom.y = space.y;
- break;
- default:
- break;
- }
- space.y += cgeom.height;
- space.height -= cgeom.height;
+
+ child->packarea.y = space.y + space.height - child->packarea.height;
+
+ space.height -= child->packarea.height;
break;
case AUI_SIDE_LEFT:
- cgeom.width = (cgeom.width > space.width) ? space.width : cgeom.width;
- cgeom.height = (cgeom.height > space.height) ? space.height : cgeom.height;
- cgeom.x = space.x;
- cgeom.y = space.y + space.height / 2 - cgeom.height / 2;
+ child->packarea = (struct aui_geometry) {
+ .x = space.x,
+ .y = space.y,
+ .width = min.width,
+ .height = space.height
+ };
- hexpand = (child->packpar.expand) ? hexpand + 1 : hexpand;
-
- switch (child->packpar.fill) {
- case AUI_FILL_Y:
- cgeom.height = space.height;
- break;
- case AUI_FILL_BOTH:
- cgeom.height = space.height;
- break;
- case AUI_FILL_NONE:
- default:
- break;
+ if (child->packarea.width > space.width) {
+ child->packarea.width = space.width;
}
- switch (child->packpar.anchor) {
- case AUI_ANCHOR_CENTER:
- case AUI_ANCHOR_E:
- case AUI_ANCHOR_W:
- cgeom.x = space.x;
- cgeom.y = space.y + space.height / 2 - cgeom.height / 2;
- break;
- case AUI_ANCHOR_N:
- case AUI_ANCHOR_NE:
- case AUI_ANCHOR_NW:
- cgeom.x = space.x;
- cgeom.y = space.y;
- break;
- case AUI_ANCHOR_S:
- case AUI_ANCHOR_SE:
- case AUI_ANCHOR_SW:
- cgeom.x = space.x;
- cgeom.y = space.y + space.height - cgeom.height;
- break;
- default:
- break;
- }
- space.width -= cgeom.width;
- space.x += cgeom.width;
+
+ space.x += child->packarea.width;
+ space.width -= child->packarea.width;
break;
case AUI_SIDE_RIGHT:
- cgeom.width = (cgeom.width > space.width) ? space.width : cgeom.width;
- cgeom.height = (cgeom.height > space.height) ? space.height : cgeom.height;
+ child->packarea = (struct aui_geometry) {
+ .x = space.x,
+ .y = space.y,
+ .width = min.width,
+ .height = space.height
+ };
- hexpand = (child->packpar.expand) ? hexpand + 1 : hexpand;
+ if (child->packarea.width > space.width) {
+ child->packarea.width = space.width;
+ }
- switch (child->packpar.fill) {
- case AUI_FILL_Y:
- cgeom.height = space.height;
- break;
- case AUI_FILL_BOTH:
- cgeom.height = space.height;
- break;
- case AUI_FILL_NONE:
- default:
- break;
+ child->packarea.x = space.x + space.width - child->packarea.width;
+
+ space.width -= child->packarea.width;
+ break;
+ default:
+ break;
+ }
+ }
+
+ int top = 0;
+ int bottom = 0;
+ int right = 0;
+ int left = 0;
+
+ /*
+ * Consuming the remaining space if expanded
+ */
+ TAILQ_FOREACH(child, &widget->queue, entries) {
+ if (child->mapped == 0)
+ continue;
+
+ if (space.width == 0 && space.height == 0)
+ break;
+
+ struct aui_geometry *area = &child->packarea;
+
+ switch (child->packpar.side) {
+ case AUI_SIDE_TOP:
+ area->x += left;
+ area->y += top;
+ area->width -= left;
+
+ area->width -= right;
+
+ if (child->packpar.expand == 1) {
+ if (vexpand) {
+ top += extra_h / vexpand;
+ area->height += extra_h / vexpand;
+ extra_h -= extra_h / vexpand;
+ vexpand--;
+ }
}
- switch (child->packpar.anchor) {
- case AUI_ANCHOR_CENTER:
- case AUI_ANCHOR_E:
- case AUI_ANCHOR_W:
- cgeom.x = space.x + space.width - cgeom.width;
- cgeom.y = space.y + space.height / 2 - cgeom.height / 2;
- break;
- case AUI_ANCHOR_N:
- case AUI_ANCHOR_NE:
- case AUI_ANCHOR_NW:
- cgeom.x = space.x + space.width - cgeom.width;
- cgeom.y = space.y;
- break;
- case AUI_ANCHOR_S:
- case AUI_ANCHOR_SE:
- case AUI_ANCHOR_SW:
- cgeom.x = space.x + space.width - cgeom.width;
- cgeom.y = space.y + space.height - cgeom.height;
- break;
- default:
- break;
- }
- space.width -= cgeom.width;
break;
+
case AUI_SIDE_BOTTOM:
- cgeom.width = (cgeom.width > space.width) ? space.width : cgeom.width;
- cgeom.height = (cgeom.height > space.height) ? space.height : cgeom.height;
+ area->x += left;
+ area->width -= left;
- vexpand = (child->packpar.expand) ? vexpand + 1 : vexpand;
+ area->width -= right;
+ if (child->packpar.expand == 1) {
+ if (vexpand) {
+ bottom += extra_h / vexpand;
+ area->height += extra_h / vexpand;
+ area->y -= extra_h / vexpand;
+ extra_h -= extra_h / vexpand;
+ vexpand--;
+ }
+ }
+ break;
+ case AUI_SIDE_LEFT:
+ area->y += top;
+ area->x += left;
+ area->height -= top;
+ area->height -= bottom;
- switch (child->packpar.fill) {
- case AUI_FILL_X:
- cgeom.width = space.width;
- break;
- case AUI_FILL_BOTH:
- cgeom.width = space.width;
- break;
- case AUI_FILL_NONE:
- default:
- break;
+ if (child->packpar.expand == 1) {
+ if (hexpand) {
+ left += extra_w / hexpand;
+ area->width += extra_w / hexpand;
+ extra_w -= extra_w / hexpand;
+ hexpand--;
+ }
}
- switch (child->packpar.anchor) {
- case AUI_ANCHOR_CENTER:
- case AUI_ANCHOR_N:
- case AUI_ANCHOR_S:
- cgeom.x = space.x + space.width / 2 - cgeom.width / 2;
- cgeom.y = space.y + space.height - cgeom.height;
- break;
- case AUI_ANCHOR_NW:
- case AUI_ANCHOR_SW:
- case AUI_ANCHOR_W:
- cgeom.x = space.x;
- cgeom.y = space.y + space.height - cgeom.height;
- break;
- case AUI_ANCHOR_NE:
- case AUI_ANCHOR_SE:
- case AUI_ANCHOR_E:
- cgeom.x = space.x + space.width - cgeom.width;
- cgeom.y = space.y + space.height - cgeom.height;
- break;
- default:
- break;
- }
- space.height -= cgeom.height;
break;
+ case AUI_SIDE_RIGHT:
+ area->y += top;
+ area->height -= top;
+ area->height -= bottom;
+
+ if (child->packpar.expand == 1) {
+ if (hexpand) {
+ right += extra_w / hexpand;
+ area->x -= extra_w / hexpand;
+ area->width += extra_w / hexpand;
+ extra_w -= extra_w / hexpand;
+ hexpand--;
+ }
+ }
default:
+ break;
+ }
+ }
+
+ /*
+ * Setting geometry
+ */
+ TAILQ_FOREACH(child, &widget->queue, entries) {
+ if (child->mapped == 0)
continue;
+
+ struct aui_geometry min = child->in_ops->get_min_size(child);
+ struct aui_geometry *area = &child->packarea;
+
+ switch (child->packpar.fill) {
+ case AUI_FILL_NONE:
+ child->geom.width = (min.width > area->width) ? area->width : min.width;
+ child->geom.height = (min.height > area->height) ? area->height : min.height;
+ break;
+ case AUI_FILL_X:
+ child->geom.width = area->width;
+ child->geom.height = (min.height > area->height) ? area->height : min.height;
+ break;
+ case AUI_FILL_Y:
+ child->geom.width = (min.width > area->width) ? area->width : min.width;
+ child->geom.height = area->height;
+ break;
+ case AUI_FILL_BOTH:
+ child->geom.width = area->width;
+ child->geom.height = area->height;
+ break;
+ default:
+ break;
}
- child->in_ops->set_geometry(child, &cgeom);
+
+ switch (child->packpar.anchor) {
+ case AUI_ANCHOR_NW:
+ child->geom.x = area->x;
+ child->geom.y = area->y;
+ break;
+ case AUI_ANCHOR_N:
+ child->geom.x = area->x + area->width / 2 - child->geom.width / 2;
+ child->geom.y = area->y;
+ break;
+ case AUI_ANCHOR_NE:
+ child->geom.x = area->x + area->width - child->geom.width;
+ child->geom.y = area->y;
+ break;
+ case AUI_ANCHOR_CENTER:
+ child->geom.x = area->x + area->width / 2 - child->geom.width / 2;
+ child->geom.y = area->y + area->height / 2 - child->geom.height / 2;
+ break;
+ case AUI_ANCHOR_SE:
+ child->geom.x = area->x + area->width - child->geom.width;
+ child->geom.y = area->y + area->height - child->geom.height;
+ break;
+ case AUI_ANCHOR_S:
+ child->geom.x = area->x + area->width / 2 - child->geom.width / 2;
+ child->geom.y = area->y + area->height - child->geom.height;
+ break;
+ case AUI_ANCHOR_SW:
+ child->geom.x = area->x;
+ child->geom.y = area->y + area->height - child->geom.height;
+ break;
+ case AUI_ANCHOR_W:
+ child->geom.x = area->x;
+ child->geom.y = area->y + area->height / 2 - child->geom.height / 2;
+ break;
+ case AUI_ANCHOR_E:
+ child->geom.x = area->x + area->width - child->geom.width;
+ child->geom.y = area->y + area->height / 2 - child->geom.height / 2;
+ break;
+ default:
+ break;
+ break;
+ }
+
+ child->in_ops->set_geometry(child, &child->geom);
}
TAILQ_FOREACH(child, &widget->queue, entries) {
widget->mapped = 1;
con->map_count++;
+ /*
+ * This is important for packing order
+ */
+ widget_lead(widget->parent, widget);
+
layout_organize(parent);
return 0;
blob - 4804212e7cd8b12619f03db0f4fce2852bfe5b29
blob + 8aca33ab8d6a7d052137366229bb00cb080fe870
--- widget.c
+++ widget.c
}
void
+widget_lead(struct aui_widget *parent, struct aui_widget *child)
+{
+ TAILQ_REMOVE(&parent->queue, child, entries);
+ TAILQ_INSERT_TAIL(&parent->queue, child, entries);
+}
+
+void
widget_remove(struct aui_widget *parent, struct aui_widget *child)
{
TAILQ_REMOVE(&parent->queue, child, entries);
return;
struct primitive *prim;
+
+ if (widget->geom.width == 0 || widget->geom.height == 0)
+ return;
+
for (int i = 0; i < widget->primitives.count; i++) {
prim = widget->primitives.list[i];
blob - 841d4a6f6dcc8401e886327bf1226c5c7d7bbac2
blob + 57105def4f591701235448adc822f9681a83ba45
--- widget.h
+++ widget.h
struct aui_placepar placepar;
struct aui_gridpar gridpar;
struct aui_packpar packpar;
+ struct aui_geometry packarea;
unsigned int mapped;
void widget_draw(struct aui_widget *);
void widget_add(struct aui_widget *, struct aui_widget *);
void widget_remove(struct aui_widget *, struct aui_widget *);
+void widget_lead(struct aui_widget *, struct aui_widget *);
int widget_collides_with_point(struct aui_widget*, uint16_t, uint16_t);
#endif