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