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 Textbutton Textbutton; 10 11 struct Textbutton 12 { 13 Control; 14 CFont *font; 15 CImage *image; 16 CImage *mask; 17 CImage *light; 18 CImage *bordercolor; 19 CImage *textcolor; 20 CImage *pressedtextcolor; 21 CImage *paletextcolor; 22 int pressed; 23 int lastbut; 24 int lastshow; 25 char **line; 26 int nline; 27 int align; 28 int border; 29 int off; 30 int showoff; 31 int prepress; 32 }; 33 34 enum{ 35 EAlign, 36 EBorder, 37 EBordercolor, 38 EFocus, 39 EFont, 40 EFormat, 41 EHide, 42 EImage, 43 ELight, 44 EMask, 45 EPaletextcolor, 46 EPressedtextcolor, 47 ERect, 48 EReveal, 49 EShow, 50 ESize, 51 EText, 52 ETextcolor, 53 EValue, 54 }; 55 56 static char *cmds[] = { 57 [EAlign] = "align", 58 [EBorder] = "border", 59 [EBordercolor] = "bordercolor", 60 [EFocus] = "focus", 61 [EFont] = "font", 62 [EFormat] = "format", 63 [EHide] = "hide", 64 [EImage] = "image", 65 [ELight] = "light", 66 [EMask] = "mask", 67 [EPaletextcolor] ="paletextcolor", 68 [EPressedtextcolor] ="pressedtextcolor", 69 [ERect] = "rect", 70 [EReveal] = "reveal", 71 [EShow] = "show", 72 [ESize] = "size", 73 [EText] = "text", 74 [ETextcolor] = "textcolor", 75 [EValue] = "value", 76 nil 77 }; 78 79 static void textbuttonshow(Textbutton*); 80 81 static void 82 textbuttonmouse(Control *c, Mouse *m) 83 { 84 Textbutton *t; 85 86 t = (Textbutton *)c; 87 if(m->buttons&7) { 88 if (ptinrect(m->xy,t->rect)) { 89 if (t->off) { 90 t->off = 0; 91 textbuttonshow(t); 92 } 93 } else { 94 if (!t->off) { 95 t->off = 1; 96 textbuttonshow(t); 97 } 98 } 99 } 100 if((m->buttons&7) != t->lastbut){ 101 if(m->buttons & 7){ 102 t->prepress = t->pressed; 103 if (t->pressed) 104 t->pressed = 0; 105 else 106 t->pressed = 1; 107 textbuttonshow(t); 108 }else{ /* generate event on button up */ 109 if (ptinrect(m->xy,t->rect)) 110 chanprint(t->event, t->format, t->name, t->pressed); 111 else { 112 t->off = 0; 113 t->pressed = t->prepress; 114 textbuttonshow(t); 115 } 116 } 117 } 118 t->lastbut = m->buttons & 7; 119 } 120 121 static void 122 textbuttonfree(Control *c) 123 { 124 int i; 125 Textbutton *t; 126 127 t = (Textbutton*)c; 128 _putctlfont(t->font); 129 _putctlimage(t->image); 130 _putctlimage(t->light); 131 _putctlimage(t->mask); 132 _putctlimage(t->textcolor); 133 _putctlimage(t->bordercolor); 134 _putctlimage(t->paletextcolor); 135 _putctlimage(t->pressedtextcolor); 136 for(i=0; i<t->nline; i++) 137 free(t->line[i]); 138 free(t->line); 139 } 140 141 static void 142 textbuttonshow(Textbutton *t) 143 { 144 Rectangle r, clipr; 145 int i, dx, dy, w; 146 Font *f; 147 Point p, q; 148 Image *im; 149 150 if(t->hidden || (t->lastshow == t->pressed && t->showoff == t->off)) 151 return; 152 f = t->font->font; 153 draw(t->screen, t->rect, t->image->image, nil, t->image->image->r.min); 154 if(t->border > 0) 155 border(t->screen, t->rect, t->border, t->bordercolor->image, ZP); 156 /* text goes here */ 157 dx = 0; 158 for(i=0; i<t->nline; i++){ 159 w = stringwidth(f, t->line[i]); 160 if(dx < w) 161 dx = w; 162 } 163 dy = t->nline*f->height; 164 clipr = insetrect(t->rect, t->border); 165 p = _ctlalignpoint(clipr, dx, dy, t->align); 166 im = t->textcolor->image; 167 if(t->off) 168 im = t->paletextcolor->image; 169 else if(t->pressed) 170 im = t->pressedtextcolor->image; 171 for(i=0; i<t->nline; i++){ 172 r.min = p; 173 r.max.x = p.x+dx; 174 r.max.y = p.y+f->height; 175 q = _ctlalignpoint(r, stringwidth(f, t->line[i]), f->height, t->align%3); 176 _string(t->screen, q, im, 177 ZP, f, t->line[i], nil, strlen(t->line[i]), 178 clipr, nil, ZP, SoverD); 179 p.y += f->height; 180 } 181 if(t->off || t->pressed) 182 draw(t->screen, t->rect, t->light->image, t->mask->image, t->mask->image->r.min); 183 t->lastshow = t->pressed; 184 t->showoff = t->off; 185 flushimage(display, 1); 186 } 187 188 static void 189 textbuttonctl(Control *c, CParse *cp) 190 { 191 int cmd, i; 192 Rectangle r; 193 Textbutton *t; 194 195 t = (Textbutton*)c; 196 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); 197 switch(cmd){ 198 default: 199 ctlerror("%q: unrecognized message '%s'", t->name, cp->str); 200 break; 201 case EAlign: 202 _ctlargcount(t, cp, 2); 203 t->align = _ctlalignment(cp->args[1]); 204 t->lastshow = -1; /* force redraw */ 205 break; 206 case EBorder: 207 _ctlargcount(t, cp, 2); 208 t->border = cp->iargs[1]; 209 t->lastshow = -1; /* force redraw */ 210 break; 211 case EBordercolor: 212 _ctlargcount(t, cp, 2); 213 _setctlimage(t, &t->bordercolor, cp->args[1]); 214 t->lastshow = -1; /* force redraw */ 215 break; 216 case EFocus: 217 break; 218 case EFont: 219 _ctlargcount(t, cp, 2); 220 _setctlfont(t, &t->font, cp->args[1]); 221 t->lastshow = -1; /* force redraw */ 222 break; 223 case EFormat: 224 _ctlargcount(t, cp, 2); 225 t->format = ctlstrdup(cp->args[1]); 226 break; 227 case EHide: 228 _ctlargcount(t, cp, 1); 229 t->hidden = 1; 230 break; 231 case EImage: 232 _ctlargcount(t, cp, 2); 233 _setctlimage(t, &t->image, cp->args[1]); 234 t->lastshow = -1; /* force redraw */ 235 break; 236 case ELight: 237 _ctlargcount(t, cp, 2); 238 _setctlimage(t, &t->light, cp->args[1]); 239 t->lastshow = -1; /* force redraw */ 240 break; 241 case EMask: 242 _ctlargcount(t, cp, 2); 243 _setctlimage(t, &t->mask, cp->args[1]); 244 t->lastshow = -1; /* force redraw */ 245 break; 246 case EPaletextcolor: 247 _ctlargcount(t, cp, 2); 248 _setctlimage(t, &t->paletextcolor, cp->args[1]); 249 t->lastshow = -1; /* force redraw */ 250 break; 251 case EPressedtextcolor: 252 _ctlargcount(t, cp, 2); 253 _setctlimage(t, &t->pressedtextcolor, cp->args[1]); 254 t->lastshow = -1; /* force redraw */ 255 break; 256 case ERect: 257 _ctlargcount(t, cp, 5); 258 r.min.x = cp->iargs[1]; 259 r.min.y = cp->iargs[2]; 260 r.max.x = cp->iargs[3]; 261 r.max.y = cp->iargs[4]; 262 if(Dx(r)<=0 || Dy(r)<=0) 263 ctlerror("%q: bad rectangle: %s", t->name, cp->str); 264 t->rect = r; 265 t->lastshow = -1; /* force redraw */ 266 break; 267 case EReveal: 268 _ctlargcount(t, cp, 1); 269 t->hidden = 0; 270 t->lastshow = -1; /* force redraw */ 271 textbuttonshow(t); 272 break; 273 case EShow: 274 _ctlargcount(t, cp, 1); 275 t->lastshow = -1; /* force redraw */ 276 textbuttonshow(t); 277 break; 278 case ESize: 279 if (cp->nargs == 3) 280 r.max = Pt(0x7fffffff, 0x7fffffff); 281 else{ 282 _ctlargcount(t, cp, 5); 283 r.max.x = cp->iargs[3]; 284 r.max.y = cp->iargs[4]; 285 } 286 r.min.x = cp->iargs[1]; 287 r.min.y = cp->iargs[2]; 288 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) 289 ctlerror("%q: bad sizes: %s", t->name, cp->str); 290 t->size.min = r.min; 291 t->size.max = r.max; 292 break; 293 case EText: 294 /* free existing text */ 295 for(i=0; i<t->nline; i++) 296 free(t->line[i]); 297 t->nline = cp->nargs-1; 298 t->line = ctlrealloc(t->line, t->nline*sizeof(char*)); 299 for(i=0; i<t->nline; i++) 300 t->line[i] = ctlstrdup(cp->args[i+1]); 301 t->lastshow = -1; /* force redraw */ 302 textbuttonshow(t); 303 break; 304 case ETextcolor: 305 _ctlargcount(t, cp, 2); 306 _setctlimage(t, &t->textcolor, cp->args[1]); 307 t->lastshow = -1; /* force redraw */ 308 break; 309 case EValue: 310 _ctlargcount(t, cp, 2); 311 if((cp->iargs[1]!=0) != t->pressed){ 312 t->pressed ^= 1; 313 textbuttonshow(t); 314 } 315 break; 316 } 317 } 318 319 Control* 320 createtextbutton(Controlset *cs, char *name) 321 { 322 Textbutton *t; 323 324 t = (Textbutton *)_createctl(cs, "textbutton", sizeof(Textbutton), name); 325 t->line = ctlmalloc(sizeof(char*)); 326 t->nline = 0; 327 t->image = _getctlimage("white"); 328 t->light = _getctlimage("yellow"); 329 t->mask = _getctlimage("opaque"); 330 t->bordercolor = _getctlimage("black"); 331 t->textcolor = _getctlimage("black"); 332 t->pressedtextcolor = _getctlimage("black"); 333 t->paletextcolor = _getctlimage("paleyellow"); 334 t->font = _getctlfont("font"); 335 t->format = ctlstrdup("%q: value %d"); 336 t->lastshow = -1; 337 t->mouse = textbuttonmouse; 338 t->ctl = textbuttonctl; 339 t->exit = textbuttonfree; 340 t->prepress = 0; 341 t->off = 0; 342 t->showoff = -1; 343 return (Control *)t; 344 } 345