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 Box Box; 10 11 struct Box 12 { 13 Control; 14 int border; 15 CImage *bordercolor; 16 CImage *image; 17 int align; 18 }; 19 20 enum{ 21 EAlign, 22 EBorder, 23 EBordercolor, 24 EFocus, 25 EHide, 26 EImage, 27 ERect, 28 EReveal, 29 EShow, 30 ESize, 31 }; 32 33 static char *cmds[] = { 34 [EAlign] = "align", 35 [EBorder] = "border", 36 [EBordercolor] ="bordercolor", 37 [EFocus] = "focus", 38 [EHide] = "hide", 39 [EImage] = "image", 40 [ERect] = "rect", 41 [EReveal] = "reveal", 42 [EShow] = "show", 43 [ESize] = "size", 44 nil 45 }; 46 47 static void 48 boxkey(Control *c, Rune *rp) 49 { 50 Box *b; 51 52 b = (Box*)c; 53 chanprint(b->event, "%q: key 0x%x", b->name, rp[0]); 54 } 55 56 static void 57 boxmouse(Control *c, Mouse *m) 58 { 59 Box *b; 60 61 b = (Box*)c; 62 if (ptinrect(m->xy,b->rect)) 63 chanprint(b->event, "%q: mouse %P %d %ld", b->name, 64 m->xy, m->buttons, m->msec); 65 } 66 67 static void 68 boxfree(Control *c) 69 { 70 _putctlimage(((Box*)c)->image); 71 } 72 73 static void 74 boxshow(Box *b) 75 { 76 Image *i; 77 Rectangle r; 78 79 if(b->hidden) 80 return; 81 if(b->border > 0){ 82 border(b->screen, b->rect, b->border, b->bordercolor->image, ZP); 83 r = insetrect(b->rect, b->border); 84 }else 85 r = b->rect; 86 i = b->image->image; 87 /* BUG: ALIGNMENT AND CLIPPING */ 88 draw(b->screen, r, i, nil, ZP); 89 } 90 91 static void 92 boxctl(Control *c, CParse *cp) 93 { 94 int cmd; 95 Rectangle r; 96 Box *b; 97 98 b = (Box*)c; 99 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); 100 switch(cmd){ 101 default: 102 ctlerror("%q: unrecognized message '%s'", b->name, cp->str); 103 break; 104 case EAlign: 105 _ctlargcount(b, cp, 2); 106 b->align = _ctlalignment(cp->args[1]); 107 break; 108 case EBorder: 109 _ctlargcount(b, cp, 2); 110 if(cp->iargs[1] < 0) 111 ctlerror("%q: bad border: %c", b->name, cp->str); 112 b->border = cp->iargs[1]; 113 break; 114 case EBordercolor: 115 _ctlargcount(b, cp, 2); 116 _setctlimage(b, &b->bordercolor, cp->args[1]); 117 break; 118 case EFocus: 119 _ctlargcount(b, cp, 2); 120 chanprint(b->event, "%q: focus %s", b->name, cp->args[1]); 121 break; 122 case EHide: 123 _ctlargcount(b, cp, 1); 124 b->hidden = 1; 125 break; 126 case EImage: 127 _ctlargcount(b, cp, 2); 128 _setctlimage(b, &b->image, cp->args[1]); 129 break; 130 case ERect: 131 _ctlargcount(b, cp, 5); 132 r.min.x = cp->iargs[1]; 133 r.min.y = cp->iargs[2]; 134 r.max.x = cp->iargs[3]; 135 r.max.y = cp->iargs[4]; 136 if(Dx(r)<0 || Dy(r)<0) 137 ctlerror("%q: bad rectangle: %s", b->name, cp->str); 138 b->rect = r; 139 break; 140 case EReveal: 141 _ctlargcount(b, cp, 1); 142 b->hidden = 0; 143 boxshow(b); 144 break; 145 case EShow: 146 _ctlargcount(b, cp, 1); 147 boxshow(b); 148 break; 149 case ESize: 150 if (cp->nargs == 3) 151 r.max = Pt(0x7fffffff, 0x7fffffff); 152 else{ 153 _ctlargcount(b, cp, 5); 154 r.max.x = cp->iargs[3]; 155 r.max.y = cp->iargs[4]; 156 } 157 r.min.x = cp->iargs[1]; 158 r.min.y = cp->iargs[2]; 159 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) 160 ctlerror("%q: bad sizes: %s", b->name, cp->str); 161 b->size.min = r.min; 162 b->size.max = r.max; 163 break; 164 } 165 } 166 167 Control* 168 createbox(Controlset *cs, char *name) 169 { 170 Box *b; 171 172 b = (Box *)_createctl(cs, "box", sizeof(Box), name); 173 b->image = _getctlimage("white"); 174 b->bordercolor = _getctlimage("black"); 175 b->align = Aupperleft; 176 b->key = boxkey; 177 b->mouse = boxmouse; 178 b->ctl = boxctl; 179 b->exit = boxfree; 180 return (Control *)b; 181 } 182