123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737 |
- #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);
- }
- }
|