diff options
author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2024-02-11 16:39:26 +0000 |
---|---|---|
committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2024-02-11 16:39:26 +0000 |
commit | 0ad54d136ef33d61172658e97b538f7cd6a91c26 (patch) | |
tree | 2aa2817fbebca09ef0feffc507cb9b1b0acd654e | |
parent | 7aeae86d36a1a04e93bb4be2216cb735acfab714 (diff) |
Add a basic textbox element
-rw-r--r-- | graphics.c | 17 | ||||
-rw-r--r-- | guifs.h | 13 | ||||
-rw-r--r-- | guispec.c | 6 | ||||
-rw-r--r-- | layout.c | 8 | ||||
-rw-r--r-- | main.c | 46 | ||||
-rw-r--r-- | props.c | 94 | ||||
-rwxr-xr-x | test.rc | 17 |
7 files changed, 180 insertions, 21 deletions
@@ -54,6 +54,10 @@ drawgui(GuiElement *g) } if(Dx(g->rect) > 0 && Dy(g->rect) > 0){ + /* Draw the background */ + Image *bg = getprop(g, Pbackground).colour->image; + draw(screen, g->rect, bg, nil, ZP); + spec.draw(g); for(int i = 0; i < g->nchildren; i++) @@ -65,8 +69,17 @@ drawgui(GuiElement *g) void drawcontainer(GuiElement *g) { - Image *bg = getprop(g, Pbackground).colour->image; - draw(screen, g->rect, bg, nil, ZP); + USED(g); +} + +void +drawtextbox(GuiElement *g) +{ + Rune *text = getprop(g, Ptext).text; + Image *fg = getprop(g, Ptextcolour).colour->image; + + + runestring(screen, g->content.min, fg, ZP, font, text); } Colour * @@ -5,15 +5,18 @@ enum { Ppadding, Porientation, Pbordercolour, + Ptext, + Ptextcolour, Pmax, }; enum { - nbaseprops = 4 + nbaseprops = 5 }; enum { Gcontainer, + Gtextbox, Gmax, }; @@ -46,11 +49,12 @@ union PropVal { Colour *colour; Spacing *spacing; int orientation; + Rune *text; }; struct PropSpec { char *name; - PropVal (*def)(void); + PropVal (*def)(int, int); char *(*print)(PropVal); char *(*parse)(char *, PropVal *); }; @@ -65,6 +69,7 @@ struct GuiSpec { char *name; void (*draw)(GuiElement *); void (*layout)(GuiElement *, Rectangle); + int leafnode; int nprops; int *proptags; }; @@ -91,6 +96,7 @@ struct GuiElement { Rectangle border; Rectangle rect; + Rectangle content; }; extern GuiElement *root; @@ -99,14 +105,17 @@ extern GuiSpec guispecs[Gmax]; extern int baseprops[nbaseprops]; void *emalloc(ulong); +int allspace(char *); Colour *mkcolour(ulong); void initgraphics(void); void layout(GuiElement *, Rectangle); void updategui(int); void drawcontainer(GuiElement *); +void drawtextbox(GuiElement *); void layoutcontainer(GuiElement *, Rectangle); +void layouttextbox(GuiElement *, Rectangle); PropVal getprop(GuiElement *, int); void setprop(GuiElement *, int, PropVal);
\ No newline at end of file @@ -4,8 +4,10 @@ #include "guifs.h" -int containerprops[] = {Pbackground, Porientation}; +int containerprops[] = {Porientation}; +int textboxprops[] = {Ptext, Ptextcolour}; GuiSpec guispecs[Gmax] = { - [Gcontainer] = { "container", drawcontainer, layoutcontainer, nelem(containerprops), containerprops} + [Gcontainer] = { "container", drawcontainer, layoutcontainer, 0, nelem(containerprops), containerprops}, + [Gtextbox] = { "textbox", drawtextbox, layouttextbox, 1, nelem(textboxprops), textboxprops}, };
\ No newline at end of file @@ -35,6 +35,7 @@ layout(GuiElement *g, Rectangle r0) wlock(&g->lock); g->border = r1; g->rect = r2; + g->content = r3; wunlock(&g->lock); rlock(&g->lock); @@ -65,4 +66,11 @@ layoutcontainer(GuiElement *g, Rectangle r) layout(g->children[i], r); r = rectaddpt(r, Pt(dx, dy)); } +} + +void +layouttextbox(GuiElement *g, Rectangle r) +{ + USED(g); + USED(r); }
\ No newline at end of file @@ -101,13 +101,13 @@ settype(GuiElement *g, int type) for(int i = 0; i < nbaseprops; i++){ int tag = baseprops[i]; props[i].tag = tag; - props[i].val = propspecs[tag].def(); + props[i].val = propspecs[tag].def(type, tag); props[i].qid = mkpropqid(tag); } for(int i = 0; i < spec.nprops; i++){ int tag = spec.proptags[i]; props[i+nbaseprops].tag = tag; - props[i+nbaseprops].val = propspecs[tag].def(); + props[i+nbaseprops].val = propspecs[tag].def(type, tag); props[i+nbaseprops].qid = mkpropqid(tag); } @@ -195,9 +195,14 @@ fswalk1(Fid *fid, char *name, Qid *qid) fid->aux = g->parent; *qid = g->parent->qid; } - }else if(strcmp(name, "clone") == 0) - *qid = g->qclone; - else if(strcmp(name, "event") == 0) + }else if(strcmp(name, "clone") == 0){ + rlock(&g->lock); + if(guispecs[g->type].leafnode) + err = Eexist; + else + *qid = g->qclone; + runlock(&g->lock); + }else if(strcmp(name, "event") == 0) *qid = g->qevent; else if(strcmp(name, "type") == 0) *qid = g->qtype; @@ -304,6 +309,11 @@ dirtreegen(int n, Dir *d, void *aux) d->gid = estrdup9p(username); d->muid = estrdup9p(username); + rlock(&g->lock); + if(guispecs[g->type].leafnode) + n++; + runlock(&g->lock); + if(n < Fmax){ d->length = 0; @@ -427,7 +437,31 @@ fswrite(Req *r) switch(QID_TYPE(r->fid->qid)){ case Qtype: - err = "Can't switch type"; + { + char *buf = emalloc(r->ifcall.count + 1); + buf[r->ifcall.count] = 0; + memcpy(buf, r->ifcall.data, r->ifcall.count); + + int type; + for(type = 0; type < Gmax; type++){ + char *name = guispecs[type].name; + int len = strlen(name); + if(strncmp(buf, name, len) == 0 && allspace(buf+len)){ + rlock(&g->lock); + int canswitch = (g->nchildren == 0 || guispecs[type].leafnode == 0); + runlock(&g->lock); + + if(canswitch) + settype(g, type); + else + err = "old node has children, and new node type can't"; + break; + } + } + if(type == Gmax) + err = "no such gui element type"; + free(buf); + } break; case Qprop: { @@ -22,34 +22,89 @@ allspace(char *r) } PropVal -defbackground(void) +defcolour(int gtag, int ptag) { PropVal v; - v.colour = mkcolour(DWhite); + ulong col = DTransparent; + + switch(ptag){ + case Pbackground: + switch(gtag){ + case Gcontainer: + col = DWhite; + break; + case Gtextbox: + col = 0xFFFFEAFF; + break; + } + break; + case Pbordercolour: + switch(gtag){ + case Gtextbox: + col = DYellowgreen; + break; + default: + col = DRed; + break; + } + break; + case Ptextcolour: + col = DBlack; + break; + } + + v.colour = mkcolour(col); return v; } PropVal -defspacing(void) +defspacing(int gtag, int ptag) { PropVal v; v.spacing = emalloc(sizeof(Spacing)); + + int space = 0; + + switch(ptag){ + case Pborder: + switch(gtag){ + case Gtextbox: + space = 4; + break; + } + break; + case Ppadding: + switch(gtag){ + case Gtextbox: + space = 2; + break; + } + break; + } + v.spacing->up = v.spacing->down = v.spacing->left = v.spacing->right = space; return v; } PropVal -deforientation(void) +deforientation(int gtag, int ptag) { + USED(gtag); + USED(ptag); + PropVal v; v.orientation = Horizontal; return v; } PropVal -defbordercolour(void) +deftext(int gtag, int ptag) { + USED(gtag); + USED(ptag); + PropVal v; - v.colour = mkcolour(DRed); + v.text = emalloc(sizeof(Rune)); + v.text[0] = 0; return v; } @@ -90,6 +145,15 @@ printorientation(PropVal p) } char * +printtext(PropVal p) +{ + char *str = smprint("%S", p.text); + if(str == nil) + sysfatal("smprint failed"); + return str; +} + +char * parsecolour(char *str, PropVal *p) { char *r; @@ -151,6 +215,16 @@ parseorientation(char *str, PropVal *p) return nil; } +char * +parsetext(char *str, PropVal *p) +{ + Rune *rstr = runesmprint("%s", str); + if(rstr == nil) + sysfatal("runesmprint failed"); + (*p).text = rstr; + return nil; +} + PropVal getprop(GuiElement *g, int tag) { @@ -180,12 +254,14 @@ setprop(GuiElement *g, int tag, PropVal val) } PropSpec propspecs[Pmax] = { - [Pbackground] = {"background", defbackground, printcolour, parsecolour}, + [Pbackground] = {"background", defcolour, printcolour, parsecolour}, [Pborder] = {"border", defspacing, printspacing, parsespacing}, [Pmargin] = {"margin", defspacing, printspacing, parsespacing}, [Ppadding] = {"padding", defspacing, printspacing, parsespacing}, [Porientation] = {"orientation", deforientation, printorientation, parseorientation}, - [Pbordercolour] = {"bordercolour", defbordercolour, printcolour, parsecolour}, + [Pbordercolour] = {"bordercolour", defcolour, printcolour, parsecolour}, + [Ptext] = {"text", deftext, printtext, parsetext}, + [Ptextcolour] = {"textcolour", defcolour, printcolour, parsecolour}, }; -int baseprops[nbaseprops] = {Pborder, Pmargin, Ppadding, Pbordercolour};
\ No newline at end of file +int baseprops[nbaseprops] = {Pbackground, Pborder, Pmargin, Ppadding, Pbordercolour};
\ No newline at end of file @@ -9,10 +9,22 @@ guifs -s testgui dir=/mnt/gui sleep $delay +# split the window vertically into two, and make the top one a textbox +echo vertical >> $dir/props/orientation +textdir=$dir/`{cat $dir/clone} +echo textbox >> $textdir/type + +fn show { + echo -n $* >> $textdir/props/text +} + +dir=$dir/`{cat $dir/clone} + colours=(FF0000 00FF00 0000FF FFFF00 00FFFF FF00FF FFFFFF 333333) for(colour in $colours){ dir=$dir/`{cat $dir/clone} # Create a new sub element in the gui (for now, always a "container") echo $colour^FF >> $dir/props/background # Set the background + show 'setting background of '^$dir^' to 0x'^$colour sleep $delay # Wait a bit } @@ -20,12 +32,14 @@ for(colour in $colours){ for(colour in $colours){ subdir=$dir/`{cat $dir/clone} echo $colour^FF >> $subdir/props/background + show 'setting background of '^$subdir^' to 0x'^$colour sleep $delay } # Add some padding to all elements for(f in `{walk /mnt/gui/ | grep 'padding$'}){ echo 10 >> $f + show 'echo 10 >> '^$f sleep $delay } @@ -33,17 +47,20 @@ for(f in `{walk /mnt/gui/ | grep 'padding$'}){ for(f in `{walk /mnt/gui | grep $dir'/[0-9]+/props/border$'}){ echo 8888CCFF >> $f^colour echo 5 >> $f + show 'echo 5 >> '^$f sleep $delay } # Add some margin to the innermost elements for(f in `{walk /mnt/gui | grep $dir'/[0-9]+/props/margin'}){ echo 5 >> $f + show 'echo 5 >> '^$f sleep $delay } # Make the inner container vertical echo vertical >> $dir/props/orientation +show 'echo vertical >> '^$dir/props/orientation # when the script ends, the old text window draws over the gui. I will fix that later. # For now, i just make the script sleep for a long time |