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