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