diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libcontrol/group.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libcontrol/group.c')
-rwxr-xr-x | sys/src/libcontrol/group.c | 737 |
1 files changed, 737 insertions, 0 deletions
diff --git a/sys/src/libcontrol/group.c b/sys/src/libcontrol/group.c new file mode 100755 index 000000000..1d13f2f68 --- /dev/null +++ b/sys/src/libcontrol/group.c @@ -0,0 +1,737 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <mouse.h> +#include <keyboard.h> +#include <control.h> +#include "group.h" + +static int debug = 0; +static int debugm = 0; +static int debugr = 0; + +enum{ + EAdd, + EBorder, + EBordercolor, + EFocus, + EHide, + EImage, + ERect, + ERemove, + EReveal, + ESeparation, + EShow, + ESize, +}; + +static char *cmds[] = { + [EAdd] = "add", + [EBorder] = "border", + [EBordercolor] = "bordercolor", + [EFocus] = "focus", + [EHide] = "hide", + [EImage] = "image", + [ERect] = "rect", + [ERemove] = "remove", + [EReveal] = "reveal", + [ESeparation] = "separation", + [EShow] = "show", + [ESize] = "size", +}; + +static void boxboxresize(Group*, Rectangle); +static void columnresize(Group*, Rectangle); +static void groupctl(Control *c, CParse *cp); +static void groupfree(Control*); +static void groupmouse(Control *, Mouse *); +static void groupsize(Control *c); +static void removegroup(Group*, int); +static void rowresize(Group*, Rectangle); +static void stackresize(Group*, Rectangle); + +static void +groupinit(Group *g) +{ + g->bordercolor = _getctlimage("black"); + g->image = _getctlimage("white"); + g->border = 0; + g->mansize = 0; + g->separation = 0; + g->selected = -1; + g->lastkid = -1; + g->kids = nil; + g->separators = nil; + g->nkids = 0; + g->nseparators = 0; + g->ctl = groupctl; + g->mouse = groupmouse; + g->exit = groupfree; +} + +static void +groupctl(Control *c, CParse *cp) +{ + int cmd, i, n; + + Rectangle r; + Group *g; + + g = (Group*)c; + cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); + switch(cmd){ + case EAdd: + for (i = 1; i < cp->nargs; i++){ + c = controlcalled(cp->args[i]); + if (c == nil) + ctlerror("%q: no such control: %s", g->name, cp->args[i]); + _ctladdgroup(g, c); + } + if (g->setsize) + g->setsize((Control*)g); + break; + case EBorder: + _ctlargcount(g, cp, 2); + if(cp->iargs[1] < 0) + ctlerror("%q: bad border: %c", g->name, cp->str); + g->border = cp->iargs[1]; + break; + case EBordercolor: + _ctlargcount(g, cp, 2); + _setctlimage(g, &g->bordercolor, cp->args[1]); + break; + case EFocus: + /* ignore focus change */ + break; + case EHide: + _ctlargcount(g, cp, 1); + for (i = 0; i < g->nkids; i++) + if (g->kids[i]->ctl) + _ctlprint(g->kids[i], "hide"); + g->hidden = 1; + break; + case EImage: + _ctlargcount(g, cp, 2); + _setctlimage(g, &g->image, cp->args[1]); + break; + case ERect: + _ctlargcount(g, cp, 5); + r.min.x = cp->iargs[1]; + r.min.y = cp->iargs[2]; + r.max.x = cp->iargs[3]; + r.max.y = cp->iargs[4]; + if(Dx(r)<=0 || Dy(r)<=0) + ctlerror("%q: bad rectangle: %s", g->name, cp->str); + g->rect = r; + r = insetrect(r, g->border); + if (g->nkids == 0) + return; + switch(g->type){ + case Ctlboxbox: + boxboxresize(g, r); + break; + case Ctlcolumn: + columnresize(g, r); + break; + case Ctlrow: + rowresize(g, r); + break; + case Ctlstack: + stackresize(g, r); + break; + } + break; + case ERemove: + _ctlargcount(g, cp, 2); + for (n = 0; n < g->nkids; n++) + if (strcmp(cp->args[1], g->kids[n]->name) == 0) + break; + if (n == g->nkids) + ctlerror("%s: remove nonexistent control: %q", g->name, cp->args[1]); + removegroup(g, n); + if (g->setsize) + g->setsize((Control*)g); + break; + case EReveal: + g->hidden = 0; + if (debugr) fprint(2, "reveal %s\n", g->name); + if (g->type == Ctlstack){ + if (cp->nargs == 2){ + if (cp->iargs[1] < 0 || cp->iargs[1] >= g->nkids) + ctlerror("%s: control out of range: %q", g->name, cp->str); + g->selected = cp->iargs[1]; + }else + _ctlargcount(g, cp, 1); + for (i = 0; i < g->nkids; i++) + if (g->kids[i]->ctl){ + if (g->selected == i){ + if (debugr) fprint(2, "reveal %s: reveal kid %s\n", g->name, g->kids[i]->name); + _ctlprint(g->kids[i], "reveal"); + }else{ + if (debugr) fprint(2, "reveal %s: hide kid %s\n", g->name, g->kids[i]->name); + _ctlprint(g->kids[i], "hide"); + } + } + break; + } + _ctlargcount(g, cp, 1); + if (debug) fprint(2, "reveal %s: border %R/%d\n", g->name, g->rect, g->border); + border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min); + r = insetrect(g->rect, g->border); + if (debug) fprint(2, "reveal %s: draw %R\n", g->name, r); + draw(g->screen, r, g->image->image, nil, g->image->image->r.min); + for (i = 0; i < g->nkids; i++) + if (g->kids[i]->ctl) + _ctlprint(g->kids[i], "reveal"); + break; + case EShow: + _ctlargcount(g, cp, 1); + if (g->hidden) + break; + // pass it on to the kiddies + if (debug) fprint(2, "show %s: border %R/%d\n", g->name, g->rect, g->border); + border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min); + r = insetrect(g->rect, g->border); + if (debug) fprint(2, "show %s: draw %R\n", g->name, r); + draw(g->screen, r, g->image->image, nil, g->image->image->r.min); + for (i = 0; i < g->nkids; i++) + if (g->kids[i]->ctl){ + if (debug) fprint(2, "show %s: kid %s: %q\n", g->name, g->kids[i]->name, cp->str); + _ctlprint(g->kids[i], "show"); + } + flushimage(display, 1); + break; + case ESize: + r.max = Pt(_Ctlmaxsize, _Ctlmaxsize); + if (g->type == Ctlboxbox) + _ctlargcount(g, cp, 5); + switch(cp->nargs){ + default: + ctlerror("%s: args of %q", g->name, cp->str); + case 1: + /* recursively set size */ + g->mansize = 0; + if (g->setsize) + g->setsize((Control*)g); + break; + case 5: + _ctlargcount(g, cp, 5); + r.max.x = cp->iargs[3]; + r.max.y = cp->iargs[4]; + /* fall through */ + case 3: + r.min.x = cp->iargs[1]; + r.min.y = cp->iargs[2]; + if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y) + ctlerror("%q: bad sizes: %s", g->name, cp->str); + g->size = r; + g->mansize = 1; + break; + } + break; + case ESeparation: + if (g->type != Ctlstack){ + _ctlargcount(g, cp, 2); + if(cp->iargs[1] < 0) + ctlerror("%q: illegal value: %c", g->name, cp->str); + g->separation = cp->iargs[1]; + break; + } + // fall through for Ctlstack + default: + ctlerror("%q: unrecognized message '%s'", g->name, cp->str); + break; + } +} + +static void +groupfree(Control *c) +{ + Group *g; + + g = (Group*)c; + _putctlimage(g->bordercolor); + free(g->kids); +} + +static void +groupmouse(Control *c, Mouse *m) +{ + Group *g; + int i, lastkid; + + g = (Group*)c; + if (g->type == Ctlstack){ + i = g->selected; + if (i >= 0 && g->kids[i]->mouse && + ( ( ((m->buttons == 0) || (g->lastbut == 0)) && + ptinrect(m->xy, g->kids[i]->rect) ) || + ( ((m->buttons != 0) || (g->lastbut != 0)) && + (g->lastkid == i) ) ) ) { + if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", + g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, + ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); + (g->kids[i]->mouse)(g->kids[i], m); + g->lastkid = i; + g->lastbut = m->buttons; + } else { + if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", + g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, + ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); + } + return; + } + + lastkid = -1; + for(i=0; i<g->nkids; i++) { + if(g->kids[i]->mouse && + ( ( ((m->buttons == 0) || (g->lastbut == 0)) && + ptinrect(m->xy, g->kids[i]->rect) ) || + ( ((m->buttons != 0) || (g->lastbut != 0)) && + (g->lastkid == i) ) ) ) { + if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", + g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, + ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); + (g->kids[i]->mouse)(g->kids[i], m); + lastkid = i; + } else { + if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", + g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, + ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); + } + } + g->lastkid = lastkid; + g->lastbut = m->buttons; + +#ifdef notdef + if(m->buttons == 0){ + /* buttons now up */ + g->lastbut = 0; + return; + } + if(g->lastbut == 0 && m->buttons != 0){ + /* button went down, start tracking border */ + switch(g->stacking){ + default: + return; + case Vertical: + p = Pt(m->xy.x, middle_of_border.y); + p0 = Pt(g->r.min.x, m->xy.y); + p1 = Pt(g->r.max.x, m->xy.y); + break; + case Horizontal: + p = Pt(middle_of_border.x, m->xy.y); + p0 = Pt(m->xy.x, g->r.min.y); + p1 = Pt(m->xy.x, g->r.max.y); + break; + } + // setcursor(); + oi = nil; + } else if (g->lastbut != 0 && s->m.buttons != 0){ + /* button is down, keep tracking border */ + if(!eqpt(s->m.xy, p)){ + p = onscreen(s->m.xy); + r = canonrect(Rpt(p0, p)); + if(Dx(r)>5 && Dy(r)>5){ + i = allocwindow(wscreen, r, Refnone, 0xEEEEEEFF); /* grey */ + freeimage(oi); + if(i == nil) + goto Rescue; + oi = i; + border(i, r, Selborder, red, ZP); + flushimage(display, 1); + } + } + } else if (g->lastbut != 0 && s->m.buttons == 0){ + /* button went up, resize kiddies */ + } + g->lastbut = s->m.buttons; +#endif +} + +static void +activategroup(Control *c, int act) +{ + int i; + Group *g; + + g = (Group*)c; + for (i = 0; i < g->nkids; i++) + if (act) + activate(g->kids[i]); + else + deactivate(g->kids[i]); +} + +Control * +createrow(Controlset *cs, char *name) +{ + Control *c; + c = _createctl(cs, "row", sizeof(Group), name); + groupinit((Group*)c); + c->setsize = groupsize; + c->activate = activategroup; + return c; +} + +Control * +createcolumn(Controlset *cs, char *name) +{ + Control *c; + c = _createctl(cs, "column", sizeof(Group), name); + groupinit((Group*)c); + c->setsize = groupsize; + c->activate = activategroup; + return c; +} + +Control * +createboxbox(Controlset *cs, char *name) +{ + Control *c; + c = _createctl(cs, "boxbox", sizeof(Group), name); + groupinit((Group*)c); + c->activate = activategroup; + return c; +} + +Control * +createstack(Controlset *cs, char *name) +{ + Control *c; + c = _createctl(cs, "stack", sizeof(Group), name); + groupinit((Group*)c); + c->setsize = groupsize; + return c; +} + +void +_ctladdgroup(Control *c, Control *q) +{ + Group *g = (Group*)c; + + g->kids = ctlrealloc(g->kids, sizeof(Group*)*(g->nkids+1)); + g->kids[g->nkids++] = q; +} + +static void +removegroup(Group *g, int n) +{ + int i; + + if (g->selected == n) + g->selected = -1; + else if (g->selected > n) + g->selected--; + + for (i = n+1; i < g->nkids; i++) + g->kids[i-1] = g->kids[i]; + g->nkids--; +} + +static void +groupsize(Control *c) +{ + Rectangle r; + int i; + Control *q; + Group *g; + + g = (Group*)c; + assert(g->type == Ctlcolumn || g->type == Ctlrow || g->type == Ctlstack); + if (g->mansize) return; + r = Rect(1, 1, 1, 1); + if (debug) fprint(2, "groupsize %q\n", g->name); + for (i = 0; i < g->nkids; i++){ + q = g->kids[i]; + if (q->setsize) + q->setsize(q); + if (q->size.min.x == 0 || q->size.min.y == 0 || q->size.max.x == 0 || q->size.max.y == 0) + ctlerror("%q: bad size %R", q->name, q->size); + if (debug) fprint(2, "groupsize %q: [%d %q]: %R\n", g->name, i, q->name, q->size); + switch(g->type){ + case Ctlrow: + if (i) + r.min.x += q->size.min.x + g->border; + else + r.min.x = q->size.min.x; + if (i) + r.max.x += q->size.max.x + g->border; + else + r.max.x = q->size.max.x; + if (r.min.y < q->size.min.y) r.min.y = q->size.min.y; + if (r.max.y < q->size.max.y) r.max.y = q->size.max.y; + break; + case Ctlcolumn: + if (r.min.x < q->size.min.x) r.min.x = q->size.min.x; + if (r.max.x < q->size.max.x) r.max.x = q->size.max.x; + if (i) + r.min.y += q->size.min.y + g->border; + else + r.min.y = q->size.min.y; + if (i) + r.max.y += q->size.max.y + g->border; + else + r.max.y = q->size.max.y; + break; + case Ctlstack: + if (r.min.x < q->size.min.x) r.min.x = q->size.min.x; + if (r.max.x < q->size.max.x) r.max.x = q->size.max.x; + if (r.min.y < q->size.min.y) r.min.y = q->size.min.y; + if (r.max.y < q->size.max.y) r.max.y = q->size.max.y; + break; + } + } + g->size = rectaddpt(r, Pt(g->border, g->border)); + if (debug) fprint(2, "groupsize %q: %R\n", g->name, g->size); +} + +static void +boxboxresize(Group *g, Rectangle r) +{ + int rows, cols, ht, wid, i, hpad, wpad; + Rectangle rr; + + if(debug) fprint(2, "boxboxresize %q %R (%d×%d) min/max %R separation %d\n", g->name, r, Dx(r), Dy(r), g->size, g->separation); + ht = 0; + for(i=0; i<g->nkids; i++){ + if (g->kids[i]->size.min.y > ht) + ht = g->kids[i]->size.min.y; + } + if (ht == 0) + ctlerror("boxboxresize: height"); + rows = Dy(r) / (ht+g->separation); + hpad = (Dy(r) % (ht+g->separation)) / g->nkids; + cols = (g->nkids+rows-1)/rows; + wid = Dx(r) / cols - g->separation; + for(i=0; i<g->nkids; i++){ + if (g->kids[i]->size.max.x < wid) + wid = g->kids[i]->size.max.x; + } + for(i=0; i<g->nkids; i++){ + if (g->kids[i]->size.min.x > wid) + wid = g->kids[i]->size.min.x; + } + if (wid > Dx(r) / cols) + ctlerror("can't fit controls in boxbox"); + wpad = (Dx(r) % (wid+g->separation)) / g->nkids; + rr = rectaddpt(Rect(0,0,wid, ht), addpt(r.min, Pt(g->separation/2, g->separation/2))); + if(debug) fprint(2, "boxboxresize rows %d, cols %d, wid %d, ht %d, wpad %d, hpad %d\n", rows, cols, wid, ht, wpad, hpad); + for(i=0; i<g->nkids; i++){ + if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, g->kids[i]->name, rr, Dx(rr), Dy(rr)); + _ctlprint(g->kids[i], "rect %R", + rectaddpt(rr, Pt((wpad+wid+g->separation)*(i/rows), (hpad+ht+g->separation)*(i%rows)))); + } + g->nseparators = rows + cols - 2; + g->separators = realloc(g->separators, g->nseparators*sizeof(Rectangle)); + rr = r; + rr.max.y = rr.min.y + g->separation+hpad; + for (i = 1; i < rows; i++){ + g->separators[i-1] = rectaddpt(rr, Pt(0, (hpad+ht+g->separation)*i-g->separation-hpad)); + if(debug) fprint(2, "row separation %d [%d]: %R\n", i, i-1, rectaddpt(rr, Pt(0, (hpad+ht+g->separation)*i-g->separation))); + } + rr = r; + rr.max.x = rr.min.x + g->separation+wpad; + for (i = 1; i < cols; i++){ + g->separators[i+rows-2] = rectaddpt(rr, Pt((wpad+wid+g->separation)*i-g->separation-wpad, 0)); + if(debug) fprint(2, "col separation %d [%d]: %R\n", i, i+rows-2, rectaddpt(rr, Pt((wpad+wid+g->separation)*i-g->separation, 0))); + } +} + +static void +columnresize(Group *g, Rectangle r) +{ + int x, y, *d, *p, i, j, t; + Rectangle rr; + Control *q; + + x = Dx(r); + y = Dy(r); + if(debug) fprint(2, "columnresize %q %R (%d×%d) min/max %R separation %d\n", g->name, r, Dx(r), Dy(r), g->size, g->separation); + if (x < g->size.min.x) { + werrstr("resize %s: too narrow: need %d, have %d", g->name, g->size.min.x, x); + r.max.x = r.min.x + g->size.min.x; + } + if (y < g->size.min.y) { + werrstr("resize %s: too short: need %d, have %d", g->name, g->size.min.y, y); + r.max.y = r.min.y + g->size.min.y; + y = Dy(r); + } + d = ctlmalloc(g->nkids*sizeof(int)); + p = ctlmalloc(g->nkids*sizeof(int)); + if(debug) fprint(2, "kiddies: "); + for (i = 0; i < g->nkids; i++) { + q = g->kids[i]; + if(debug) fprint(2, "[%q]: %d⋯%d\t", q->name, q->size.min.y, q->size.max.y); + d[i] = q->size.min.y; + y -= d[i]; + p[i] = q->size.max.y - q->size.min.y; + } + if(debug) fprint(2, "\n"); + y -= (g->nkids-1) * g->separation; + if(y < 0){ + if (debug) fprint(2, "columnresize: y == %d\n", y); + y = 0; + } + if (y >= g->size.max.y - g->size.min.y) { + // all rects can be maximum width + for (i = 0; i < g->nkids; i++) + d[i] += p[i]; + y -= g->size.max.y - g->size.min.y; + } else { + // rects can't be max width, divide up the rest + j = y; + for (i = 0; i < g->nkids; i++) { + t = p[i] * y/(g->size.max.y - g->size.min.y); + d[i] += t; + j -= t; + } + d[0] += j; + y = 0; + } + g->nseparators = g->nkids-1; + g->separators = realloc(g->separators, g->nseparators*sizeof(Rectangle)); + j = 0; + rr = r; + for (i = 0; i < g->nkids; i++) { + q = g->kids[i]; + if (i < g->nkids - 1){ + g->separators[i].min.x = r.min.x; + g->separators[i].max.x = r.max.x; + } + t = y / (g->nkids - i); + y -= t; + j += t/2; + rr.min.y = r.min.y + j; + if (i) + g->separators[i-1].max.y = rr.min.y; + j += d[i]; + rr.max.y = r.min.y + j; + if (i < g->nkids - 1) + g->separators[i].min.y = rr.max.y; + j += g->separation + t - t/2; + _ctlprint(q, "rect %R", rr); + if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, q->name, rr, Dx(rr), Dy(rr)); + } + free(d); + free(p); +} + +static void +rowresize(Group *g, Rectangle r) +{ + int x, y, *d, *p, i, j, t; + Rectangle rr; + Control *q; + + x = Dx(r); + y = Dy(r); + if(debug) fprint(2, "rowresize %q %R (%d×%d), separation %d\n", g->name, r, Dx(r), Dy(r), g->separation); + if (x < g->size.min.x) { + werrstr("resize %s: too narrow: need %d, have %d", g->name, g->size.min.x, x); + r.max.x = r.min.x + g->size.min.x; + x = Dx(r); + } + if (y < g->size.min.y) { + werrstr("resize %s: too short: need %d, have %d", g->name, g->size.min.y, y); + r.max.y = r.min.y + g->size.min.y; + } + d = ctlmalloc(g->nkids*sizeof(int)); + p = ctlmalloc(g->nkids*sizeof(int)); + if(debug) fprint(2, "kiddies: "); + for (i = 0; i < g->nkids; i++) { + q = g->kids[i]; + if(debug) fprint(2, "[%q]: %d⋯%d\t", q->name, q->size.min.x, q->size.max.x); + d[i] = q->size.min.x; + x -= d[i]; + p[i] = q->size.max.x - q->size.min.x; + } + if(debug) fprint(2, "\n"); + x -= (g->nkids-1) * g->separation; + if(x < 0){ + if (debug) fprint(2, "rowresize: x == %d\n", x); + x = 0; + } + if (x >= g->size.max.x - g->size.min.x) { + if (debug) fprint(2, "max: %d > %d - %d", x, g->size.max.x, g->size.min.x); + // all rects can be maximum width + for (i = 0; i < g->nkids; i++) + d[i] += p[i]; + x -= g->size.max.x - g->size.min.x; + } else { + if (debug) fprint(2, "divvie up: %d < %d - %d", x, g->size.max.x, g->size.min.x); + // rects can't be max width, divide up the rest + j = x; + for (i = 0; i < g->nkids; i++) { + t = p[i] * x/(g->size.max.x - g->size.min.x); + d[i] += t; + j -= t; + } + d[0] += j; + x = 0; + } + j = 0; + g->nseparators = g->nkids-1; + g->separators = realloc(g->separators, g->nseparators*sizeof(Rectangle)); + rr = r; + for (i = 0; i < g->nkids; i++) { + q = g->kids[i]; + if (i < g->nkids - 1){ + g->separators[i].min.y = r.min.y; + g->separators[i].max.y = r.max.y; + } + t = x / (g->nkids - i); + x -= t; + j += t/2; + rr.min.x = r.min.x + j; + if (i) + g->separators[i-1].max.x = rr.min.x; + j += d[i]; + rr.max.x = r.min.x + j; + if (i < g->nkids - 1) + g->separators[i].min.x = rr.max.x; + j += g->separation + t - t/2; + _ctlprint(q, "rect %R", rr); + if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, q->name, rr, Dx(rr), Dy(rr)); + } + free(d); + free(p); +} + +static void +stackresize(Group *g, Rectangle r) +{ + int x, y, i; + Control *q; + + x = Dx(r); + y = Dy(r); + if(debug) fprint(2, "stackresize %q %R (%d×%d)\n", g->name, r, Dx(r), Dy(r)); + if (x < g->size.min.x){ + werrstr("resize %s: too narrow: need %d, have %d", g->name, g->size.min.x, x); + return; + } + if (y < g->size.min.y){ + werrstr("resize %s: too short: need %d, have %d", g->name, g->size.min.y, y); + return; + } + if (x > g->size.max.x) { + x = (x - g->size.max.x)/2; + r.min.x += x; + r.max.x -= x; + } + if (y > g->size.max.y) { + y = (y - g->size.max.y)/2; + r.min.y += y; + r.max.y -= y; + } + for (i = 0; i < g->nkids; i++){ + q = g->kids[i]; + if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, q->name, r, Dx(r), Dy(r)); + } + for (i = 0; i < g->nkids; i++){ + q = g->kids[i]; + _ctlprint(q, "rect %R", r); + } +} |