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