1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3
4 /*************************************************************************
5 * Copyright (c) 2011 AT&T Intellectual Property
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors: See CVS logs. Details at http://www.graphviz.org/
12 *************************************************************************/
13
14 /* Lefteris Koutsofios - AT&T Labs Research */
15
16 #include "common.h"
17 #include "g.h"
18 #include "gcommon.h"
19 #include "mem.h"
20
21 #define WAU widget->u.a
22
GAcreatewidget(Gwidget_t * parent,Gwidget_t * widget,int attrn,Gwattr_t * attrp)23 int GAcreatewidget (
24 Gwidget_t *parent, Gwidget_t *widget, int attrn, Gwattr_t *attrp
25 ) {
26 PIXsize_t ps;
27 DWORD wflags;
28 int mode, ai;
29
30 if (!parent) {
31 Gerr (POS, G_ERRNOPARENTWIDGET);
32 return -1;
33 }
34 wflags = WS_CHILDWINDOW;
35 mode = G_AWVARRAY;
36 WAU->func = NULL;
37 ps.x = ps.y = MINAWSIZE;
38 for (ai = 0; ai < attrn; ai++) {
39 switch (attrp[ai].id) {
40 case G_ATTRSIZE:
41 GETSIZE (attrp[ai].u.s, ps, MINAWSIZE);
42 break;
43 case G_ATTRBORDERWIDTH:
44 wflags |= WS_BORDER;
45 break;
46 case G_ATTRMODE:
47 if (strcmp ("horizontal", attrp[ai].u.t) == 0)
48 mode = G_AWHARRAY;
49 else if (strcmp ("vertical", attrp[ai].u.t) == 0)
50 mode = G_AWVARRAY;
51 else {
52 Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
53 return -1;
54 }
55 break;
56 case G_ATTRLAYOUT:
57 if (strcmp ("on", attrp[ai].u.t) == 0) {
58 Gawsetmode (widget, FALSE);
59 WAU->mode = G_AWHARRAY;
60 } else if (strcmp ("off", attrp[ai].u.t) == 0) {
61 Gawsetmode (widget, TRUE);
62 WAU->mode = G_AWHARRAY;
63 } else {
64 Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
65 return -1;
66 }
67 break;
68 case G_ATTRWINDOWID:
69 Gerr (POS, G_ERRCANNOTSETATTR1, "windowid");
70 return -1;
71 case G_ATTRRESIZECB:
72 WAU->func = attrp[ai].u.func;
73 break;
74 case G_ATTRUSERDATA:
75 widget->udata = attrp[ai].u.u;
76 break;
77 default:
78 Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
79 return -1;
80 }
81 }
82 Gawinitialize (widget, mode);
83 Gadjustwrect (parent, &ps);
84 if (!(widget->w = CreateWindow (
85 "ArrayClass", "array", wflags, 0, 0, ps.x,
86 ps.y, parent->w, (HMENU) (widget - &Gwidgets[0]),
87 hinstance, NULL
88 ))) {
89 Gerr (POS, G_ERRCANNOTCREATEWIDGET);
90 return -1;
91 }
92 ShowWindow (widget->w, SW_SHOW);
93 UpdateWindow (widget->w);
94 if (parent && parent->type == G_ARRAYWIDGET)
95 Gawinsertchild (parent, widget);
96 return 0;
97 }
98
GAsetwidgetattr(Gwidget_t * widget,int attrn,Gwattr_t * attrp)99 int GAsetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
100 Gwidget_t *parent;
101 PIXsize_t ps;
102 DWORD wflags1;
103 int ai;
104
105 parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi];
106 wflags1 = SWP_NOMOVE | SWP_NOZORDER;
107 for (ai = 0; ai < attrn; ai++) {
108 switch (attrp[ai].id) {
109 case G_ATTRSIZE:
110 GETSIZE (attrp[ai].u.s, ps, MINAWSIZE);
111 /* Gadjustwrect (parent, &ps);*/
112 SetWindowPos (widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, wflags1);
113 break;
114 case G_ATTRBORDERWIDTH:
115 Gerr (POS, G_ERRCANNOTSETATTR2, "borderwidth");
116 return -1;
117 case G_ATTRMODE:
118 Gerr (POS, G_ERRCANNOTSETATTR2, "mode");
119 return -1;
120 case G_ATTRLAYOUT:
121 if (strcmp ("on", attrp[ai].u.t) == 0)
122 Gawsetmode (widget, FALSE);
123 else if (strcmp ("off", attrp[ai].u.t) == 0)
124 Gawsetmode (widget, TRUE);
125 else {
126 Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
127 return -1;
128 }
129 break;
130 case G_ATTRWINDOWID:
131 Gerr (POS, G_ERRCANNOTSETATTR2, "windowid");
132 return -1;
133 case G_ATTRRESIZECB:
134 WAU->func = attrp[ai].u.func;
135 break;
136 case G_ATTRUSERDATA:
137 widget->udata = attrp[ai].u.u;
138 break;
139 default:
140 Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
141 return -1;
142 }
143 }
144 return 0;
145 }
146
GAgetwidgetattr(Gwidget_t * widget,int attrn,Gwattr_t * attrp)147 int GAgetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
148 RECT r;
149 int ai;
150
151 for (ai = 0; ai < attrn; ai++) {
152 switch (attrp[ai].id) {
153 case G_ATTRSIZE:
154 GetWindowRect (widget->w, &r);
155 attrp[ai].u.s.x = r.right - r.left;
156 attrp[ai].u.s.y = r.bottom - r.top;
157 break;
158 case G_ATTRBORDERWIDTH:
159 Gerr (POS, G_ERRCANNOTGETATTR, "borderwidth");
160 return -1;
161 case G_ATTRMODE:
162 attrp[ai].u.t = (
163 WAU->mode == G_AWHARRAY
164 ) ? "horizontal" : "vertical";
165 break;
166 case G_ATTRLAYOUT:
167 attrp[ai].u.t = (Gawgetmode (widget)) ? "off" : "on";
168 break;
169 case G_ATTRWINDOWID:
170 sprintf (&Gbufp[0], "0x%lx", widget->w);
171 attrp[ai].u.t = &Gbufp[0];
172 break;
173 case G_ATTRRESIZECB:
174 attrp[ai].u.func = WAU->func;
175 break;
176 case G_ATTRUSERDATA:
177 attrp[ai].u.u = widget->udata;
178 break;
179 default:
180 Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
181 return -1;
182 }
183 }
184 return 0;
185 }
186
GAdestroywidget(Gwidget_t * widget)187 int GAdestroywidget (Gwidget_t *widget) {
188 Gwidget_t *parent;
189
190 parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi];
191 if (parent && parent->type == G_ARRAYWIDGET)
192 Gawdeletechild (parent, widget);
193 Gawdestroy (widget);
194 DestroyWindow (widget->w);
195 return 0;
196 }
197
198 /* the rest of this file contains the implementation of the array widget */
199
200 static void dolayout (Gwidget_t *, int);
201
Gaworder(Gwidget_t * widget,void * data,Gawordercb func)202 int Gaworder (Gwidget_t *widget, void *data, Gawordercb func) {
203 (*func) (data, &WAU->data);
204 dolayout (widget, TRUE);
205 return 0;
206 }
207
Gawsetmode(Gwidget_t * widget,int mode)208 int Gawsetmode (Gwidget_t *widget, int mode) {
209 WAU->data.batchmode = mode;
210 dolayout (widget, TRUE);
211 return 0;
212 }
213
Gawgetmode(Gwidget_t * widget)214 int Gawgetmode (Gwidget_t *widget) {
215 return WAU->data.batchmode;
216 }
217
Gawdefcoordscb(int wi,Gawdata_t * dp)218 void Gawdefcoordscb (int wi, Gawdata_t *dp) {
219 Gawcarray_t *cp;
220 int sx, sy, csx, csy, ci;
221
222 sx = dp->sx, sy = dp->sy;
223 csx = csy = 0;
224 for (ci = 0; ci < dp->cj; ci++) {
225 cp = &dp->carray[ci];
226 if (!cp->flag)
227 continue;
228 cp->ox = csx, cp->oy = csy;
229 if (dp->type == G_AWVARRAY)
230 cp->sx = sx - 2 * cp->bs, csy += cp->sy + 2 * cp->bs;
231 else
232 cp->sy = sy - 2 * cp->bs, csx += cp->sx + 2 * cp->bs;
233 }
234 if (dp->type == G_AWVARRAY)
235 dp->sy = csy;
236 else
237 dp->sx = csx;
238 }
239
Gawinitialize(Gwidget_t * widget,int mode)240 void Gawinitialize (Gwidget_t *widget, int mode) {
241 WAU->data.type = mode;
242 if (!(WAU->data.carray = Marrayalloc ((long) AWCARRAYINCR * AWCARRAYSIZE)))
243 panic1 (POS, "Gawinitialize", "cannot allocate carray");
244 WAU->data.cn = AWCARRAYINCR;
245 WAU->data.cj = 0;
246 WAU->data.batchmode = FALSE;
247 WAU->data.working = FALSE;
248 }
249
Gawdestroy(Gwidget_t * widget)250 void Gawdestroy (Gwidget_t *widget) {
251 Marrayfree (WAU->data.carray);
252 WAU->data.cn = WAU->data.cj = 0;
253 }
254
Gawresize(Gwidget_t * widget)255 void Gawresize (Gwidget_t *widget) {
256 dolayout (widget, FALSE);
257 }
258
Gawinsertchild(Gwidget_t * parent,Gwidget_t * child)259 void Gawinsertchild (Gwidget_t *parent, Gwidget_t *child) {
260 if (parent->u.a->data.cj == parent->u.a->data.cn) {
261 parent->u.a->data.carray = Marraygrow (
262 parent->u.a->data.carray,
263 (long) (parent->u.a->data.cn + AWCARRAYINCR) * AWCARRAYSIZE
264 );
265 parent->u.a->data.cn += AWCARRAYINCR;
266 }
267 parent->u.a->data.carray[parent->u.a->data.cj++].w = child->w;
268 dolayout (parent, TRUE);
269 }
270
Gawdeletechild(Gwidget_t * parent,Gwidget_t * child)271 void Gawdeletechild (Gwidget_t *parent, Gwidget_t *child) {
272 int ci;
273
274 for (ci = 0; ci < parent->u.a->data.cj; ci++)
275 if (parent->u.a->data.carray[ci].w == child->w)
276 break;
277 if (ci < parent->u.a->data.cj) {
278 for (; ci + 1 < parent->u.a->data.cj; ci++)
279 parent->u.a->data.carray[ci].w = parent->u.a->data.carray[ci + 1].w;
280 parent->u.a->data.cj--;
281 dolayout (parent, TRUE);
282 }
283 }
284
dolayout(Gwidget_t * widget,int flag)285 static void dolayout (Gwidget_t *widget, int flag) {
286 Gawdata_t *dp;
287 Gawcarray_t *cp;
288 RECT r;
289 int sx, sy, ci;
290
291 if (WAU->data.batchmode || WAU->data.working)
292 return;
293 WAU->data.working = TRUE;
294 dp = &WAU->data;
295 for (ci = 0; ci < dp->cj; ci++) {
296 cp = &dp->carray[ci];
297 GetWindowRect (cp->w, &r);
298 cp->flag = 1;
299 cp->ox = 0;
300 cp->oy = 0;
301 cp->sx = r.right - r.left;
302 cp->sy = r.bottom - r.top;
303 cp->bs = 0;
304 }
305 GetClientRect (widget->w, &r);
306 dp->sx = r.right - r.left, dp->sy = r.bottom - r.top;
307 if (WAU->func)
308 (*WAU->func) (widget - &Gwidgets[0], dp);
309 else
310 Gawdefcoordscb (widget - &Gwidgets[0], dp);
311 if ((sx = dp->sx) < MINAWSIZE)
312 sx = MINAWSIZE;
313 if ((sy = dp->sy) < MINAWSIZE)
314 sy = MINAWSIZE;
315 if (flag && (r.right - r.left != sx || r.bottom - r.top != sy)) {
316 sx -= (r.right - r.left);
317 sy -= (r.bottom - r.top);
318 GetWindowRect (widget->w, &r);
319 sx += (r.right - r.left);
320 sy += (r.bottom - r.top);
321 SetWindowPos (
322 widget->w, (HWND) NULL, 0, 0, sx, sy, SWP_NOMOVE | SWP_NOZORDER
323 );
324 }
325 for (ci = 0; ci < dp->cj; ci++) {
326 cp = &dp->carray[ci];
327 SetWindowPos (
328 cp->w, (HWND) NULL, cp->ox, cp->oy, cp->sx, cp->sy, SWP_NOZORDER
329 );
330 }
331 WAU->data.working = FALSE;
332 }
333