1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <mouse.h> 6 #include <keyboard.h> 7 #include <control.h> 8 9 typedef struct Box Box; 10 11 struct Box 12 { 13 Control; 14 int border; 15 CImage *bordercolor; 16 CImage *image; 17 int align; 18 }; 19 20 enum{ 21 EAlign, 22 EBorder, 23 EBordercolor, 24 EFocus, 25 EHide, 26 EImage, 27 ERect, 28 EReveal, 29 EShow, 30 ESize, 31 }; 32 33 static char *cmds[] = { 34 [EAlign] = "align", 35 [EBorder] = "border", 36 [EBordercolor] ="bordercolor", 37 [EFocus] = "focus", 38 [EHide] = "hide", 39 [EImage] = "image", 40 [ERect] = "rect", 41 [EReveal] = "reveal", 42 [EShow] = "show", 43 [ESize] = "size", 44 nil 45 }; 46 47 static void 48 boxkey(Control *c, Rune *rp) 49 { 50 Box *b; 51 52 b = (Box*)c; 53 chanprint(b->event, "%q: key 0x%x", b->name, rp[0]); 54 } 55 56 static void 57 boxmouse(Control *c, Mouse *m) 58 { 59 Box *b; 60 61 b = (Box*)c; 62 chanprint(b->event, "%q: mouse %P %d %ld", b->name, 63 m->xy, m->buttons, m->msec); 64 } 65 66 static void 67 boxfree(Control *c) 68 { 69 _putctlimage(((Box*)c)->image); 70 } 71 72 static void 73 boxshow(Box *b) 74 { 75 Image *i; 76 Rectangle r; 77 78 if(b->hidden) 79 return; 80 if(b->border > 0){ 81 border(b->screen, b->rect, b->border, b->bordercolor->image, ZP); 82 r = insetrect(b->rect, b->border); 83 }else 84 r = b->rect; 85 i = b->image->image; 86 /* BUG: ALIGNMENT AND CLIPPING */ 87 draw(b->screen, r, i, nil, ZP); 88 } 89 90 static void 91 boxctl(Control *c, CParse *cp) 92 { 93 int cmd; 94 Rectangle r; 95 Box *b; 96 97 b = (Box*)c; 98 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); 99 switch(cmd){ 100 default: 101 ctlerror("%q: unrecognized message '%s'", b->name, cp->str); 102 break; 103 case EAlign: 104 _ctlargcount(b, cp, 2); 105 b->align = _ctlalignment(cp->args[1]); 106 break; 107 case EBorder: 108 _ctlargcount(b, cp, 2); 109 if(cp->iargs[1] < 0) 110 ctlerror("%q: bad border: %c", b->name, cp->str); 111 b->border = cp->iargs[1]; 112 break; 113 case EBordercolor: 114 _ctlargcount(b, cp, 2); 115 _setctlimage(b, &b->bordercolor, cp->args[1]); 116 break; 117 case EFocus: 118 _ctlargcount(b, cp, 2); 119 chanprint(b->event, "%q: focus %s", b->name, cp->args[1]); 120 break; 121 case EHide: 122 _ctlargcount(b, cp, 1); 123 b->hidden = 1; 124 break; 125 case EImage: 126 _ctlargcount(b, cp, 2); 127 _setctlimage(b, &b->image, cp->args[1]); 128 break; 129 case ERect: 130 _ctlargcount(b, cp, 5); 131 r.min.x = cp->iargs[1]; 132 r.min.y = cp->iargs[2]; 133 r.max.x = cp->iargs[3]; 134 r.max.y = cp->iargs[4]; 135 if(Dx(r)<0 || Dy(r)<0) 136 ctlerror("%q: bad rectangle: %s", b->name, cp->str); 137 b->rect = r; 138 break; 139 case EReveal: 140 _ctlargcount(b, cp, 1); 141 b->hidden = 0; 142 boxshow(b); 143 break; 144 case EShow: 145 _ctlargcount(b, cp, 1); 146 boxshow(b); 147 break; 148 case ESize: 149 if (cp->nargs == 3) 150 r.max = Pt(0x7fffffff, 0x7fffffff); 151 else{ 152 _ctlargcount(b, cp, 5); 153 r.max.x = cp->iargs[3]; 154 r.max.y = cp->iargs[4]; 155 } 156 r.min.x = cp->iargs[1]; 157 r.min.y = cp->iargs[2]; 158 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) 159 ctlerror("%q: bad sizes: %s", b->name, cp->str); 160 b->size.min = r.min; 161 b->size.max = r.max; 162 break; 163 } 164 } 165 166 Control* 167 createbox(Controlset *cs, char *name) 168 { 169 Box *b; 170 171 b = (Box *)_createctl(cs, "box", sizeof(Box), name); 172 b->image = _getctlimage("white"); 173 b->bordercolor = _getctlimage("black"); 174 b->align = Aupperleft; 175 b->key = boxkey; 176 b->mouse = boxmouse; 177 b->ctl = boxctl; 178 b->exit = boxfree; 179 return (Control *)b; 180 } 181