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 Button Button; 10 11 struct Button 12 { 13 Control; 14 CImage *image; 15 CImage *mask; 16 CImage *light; 17 CImage *pale; 18 CImage *bordercolor; 19 int pressed; 20 int lastbut; 21 int lastshow; 22 int border; 23 int align; 24 int off; 25 int prepress; 26 }; 27 28 enum{ 29 EAlign, 30 EBorder, 31 EBordercolor, 32 EFocus, 33 EFormat, 34 EHide, 35 EImage, 36 ELight, 37 EMask, 38 EPale, 39 ERect, 40 EReveal, 41 EShow, 42 ESize, 43 EValue, 44 }; 45 46 static char *cmds[] = { 47 [EAlign] = "align", 48 [EBorder] = "border", 49 [EBordercolor] = "bordercolor", 50 [EFocus] = "focus", 51 [EFormat] = "format", 52 [EHide] = "hide", 53 [EImage] = "image", 54 [ELight] = "light", 55 [EMask] = "mask", 56 [EPale] = "pale", 57 [ERect] = "rect", 58 [EReveal] = "reveal", 59 [EShow] = "show", 60 [ESize] = "size", 61 [EValue] = "value", 62 nil 63 }; 64 65 static void 66 buttonfree(Control *c) 67 { 68 Button *b; 69 70 b = (Button *)c; 71 _putctlimage(b->image); 72 _putctlimage(b->mask); 73 _putctlimage(b->light); 74 _putctlimage(b->pale); 75 _putctlimage(b->bordercolor); 76 } 77 78 static void 79 buttonshow(Button *b) 80 { 81 Rectangle r; 82 83 if (b->hidden) 84 return; 85 r = b->rect; 86 if(b->border > 0){ 87 border(b->screen, r, b->border, b->bordercolor->image, ZP); 88 r = insetrect(b->rect, b->border); 89 } 90 draw(b->screen, r, b->image->image, nil, b->image->image->r.min); 91 if(b->off) 92 draw(b->screen, r, b->pale->image, b->mask->image, b->mask->image->r.min); 93 else if(b->pressed) 94 draw(b->screen, r, b->light->image, b->mask->image, b->mask->image->r.min); 95 b->lastshow = b->pressed; 96 flushimage(display, 1); 97 } 98 99 static void 100 buttonmouse(Control *c, Mouse *m) 101 { 102 Button *b; 103 104 b = (Button*)c; 105 106 if(m->buttons&7) { 107 if (ptinrect(m->xy,b->rect)) { 108 if (b->off) { 109 b->off = 0; 110 buttonshow(b); 111 } 112 } else { 113 if (!b->off) { 114 b->off = 1; 115 buttonshow(b); 116 } 117 } 118 } 119 if((m->buttons&7) != b->lastbut){ 120 if(m->buttons & 7){ 121 b->prepress = b->pressed; 122 if (b->pressed) 123 b->pressed = 0; 124 else 125 b->pressed = m->buttons & 7; 126 buttonshow(b); 127 }else /* generate event on button up */ 128 if (ptinrect(m->xy,b->rect)) 129 chanprint(b->event, b->format, b->name, b->pressed); 130 else { 131 b->off = 0; 132 b->pressed = b->prepress; 133 buttonshow(b); 134 } 135 } 136 b->lastbut = m->buttons & 7; 137 } 138 139 static void 140 buttonctl(Control *c, CParse *cp) 141 { 142 int cmd; 143 Rectangle r; 144 Button *b; 145 146 b = (Button*)c; 147 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); 148 switch(cmd){ 149 default: 150 ctlerror("%q: unrecognized message '%s'", b->name, cp->str); 151 break; 152 case EAlign: 153 _ctlargcount(b, cp, 2); 154 b->align = _ctlalignment(cp->args[1]); 155 b->lastshow = -1; /* force redraw */ 156 break; 157 case EBorder: 158 _ctlargcount(b, cp, 2); 159 b->border = cp->iargs[1]; 160 b->lastshow = -1; /* force redraw */ 161 break; 162 case EBordercolor: 163 _ctlargcount(b, cp, 2); 164 _setctlimage(b, &b->bordercolor, cp->args[1]); 165 b->lastshow = -1; /* force redraw */ 166 break; 167 case EFocus: 168 /* ignore focus change */ 169 break; 170 case EFormat: 171 _ctlargcount(b, cp, 2); 172 b->format = ctlstrdup(cp->args[1]); 173 break; 174 case EHide: 175 _ctlargcount(b, cp, 1); 176 b->hidden = 1; 177 break; 178 case EImage: 179 _ctlargcount(b, cp, 2); 180 _setctlimage(b, &b->image, cp->args[1]); 181 b->lastshow = -1; /* force redraw */ 182 break; 183 case ELight: 184 _ctlargcount(b, cp, 2); 185 _setctlimage(b, &b->light, cp->args[1]); 186 b->lastshow = -1; /* force redraw */ 187 break; 188 case EMask: 189 _ctlargcount(b, cp, 2); 190 _setctlimage(b, &b->mask, cp->args[1]); 191 b->lastshow = -1; /* force redraw */ 192 break; 193 case EPale: 194 _ctlargcount(b, cp, 2); 195 _setctlimage(b, &b->pale, cp->args[1]); 196 b->lastshow = -1; /* force redraw */ 197 break; 198 case ERect: 199 _ctlargcount(b, cp, 5); 200 r.min.x = cp->iargs[1]; 201 r.min.y = cp->iargs[2]; 202 r.max.x = cp->iargs[3]; 203 r.max.y = cp->iargs[4]; 204 if(Dx(r)<0 || Dy(r)<0) 205 ctlerror("%q: bad rectangle: %s", b->name, cp->str); 206 b->rect = r; 207 b->lastshow = -1; /* force redraw */ 208 break; 209 case EReveal: 210 _ctlargcount(b, cp, 1); 211 b->hidden = 0; 212 buttonshow(b); 213 break; 214 case EShow: 215 _ctlargcount(b, cp, 1); 216 buttonshow(b); 217 break; 218 case ESize: 219 if (cp->nargs == 3) 220 r.max = Pt(0x7fffffff, 0x7fffffff); 221 else{ 222 _ctlargcount(b, cp, 5); 223 r.max.x = cp->iargs[3]; 224 r.max.y = cp->iargs[4]; 225 } 226 r.min.x = cp->iargs[1]; 227 r.min.y = cp->iargs[2]; 228 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) 229 ctlerror("%q: bad sizes: %s", b->name, cp->str); 230 b->size.min = r.min; 231 b->size.max = r.max; 232 break; 233 case EValue: 234 _ctlargcount(b, cp, 2); 235 if((cp->iargs[1]!=0) != b->pressed){ 236 b->pressed ^= 1; 237 buttonshow(b); 238 } 239 break; 240 } 241 } 242 243 Control* 244 createbutton(Controlset *cs, char *name) 245 { 246 Button *b; 247 b = (Button*)_createctl(cs, "button", sizeof(Button), name); 248 b->image = _getctlimage("white"); 249 b->mask = _getctlimage("opaque"); 250 b->light = _getctlimage("yellow"); 251 b->pale = _getctlimage("paleyellow"); 252 b->bordercolor = _getctlimage("black"); 253 b->format = ctlstrdup("%q: value %d"); 254 b->lastshow = -1; 255 b->border = 0; 256 b->align = Aupperleft; 257 b->ctl = buttonctl; 258 b->mouse = buttonmouse; 259 b->key = nil; 260 b->exit = buttonfree; 261 b->off = 0; 262 b->prepress = 0; 263 return (Control*)b; 264 } 265