source: trunk/athena/lib/Xj/Arrow.c @ 12242

Revision 12242, 10.7 KB checked in by ghudson, 26 years ago (diff)
Move Jets sources here from athena/bin/dash/src/lib, and autoconfiscate.
Line 
1/*
2 * $Source: /afs/dev.mit.edu/source/repository/athena/lib/Xj/Arrow.c,v $
3 * $Author: ghudson $
4 *
5 * Copyright 1990, 1991 by the Massachusetts Institute of Technology.
6 *
7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
9 *
10 */
11
12#if  (!defined(lint))  &&  (!defined(SABER))
13static char rcsid[] =
14"$Header: /afs/dev.mit.edu/source/repository/athena/lib/Xj/Arrow.c,v 1.1 1998-12-17 16:23:02 ghudson Exp $";
15#endif
16
17#include "mit-copyright.h"
18#include <stdio.h>
19#include "Jets.h"
20#include "Arrow.h"
21
22extern int DEBUG;
23
24#define offset(field) XjOffset(ArrowJet,field)
25
26static XjResource resources[] = {
27  { XjNx, XjCX, XjRInt, sizeof(int),
28      offset(core.x), XjRString, XjInheritValue },
29  { XjNy, XjCY, XjRInt, sizeof(int),
30      offset(core.y), XjRString, XjInheritValue },
31  { XjNwidth, XjCWidth, XjRInt, sizeof(int),
32      offset(core.width), XjRString, "15" },
33  { XjNheight, XjCHeight, XjRInt, sizeof(int),
34      offset(core.height), XjRString, "15" },
35  { XjNforeground, XjCForeground, XjRColor, sizeof(int),
36      offset(arrow.foreground), XjRString, XjDefaultForeground },
37  { XjNbackground, XjCBackground, XjRColor, sizeof(int),
38      offset(arrow.background), XjRString, XjDefaultBackground },
39  { XjNfillColor, XjCForeground, XjRColor, sizeof(int),
40      offset(arrow.fillColor), XjRString, XjDefaultForeground },
41  { XjNreverseVideo, XjCReverseVideo, XjRBoolean, sizeof(Boolean),
42      offset(arrow.reverseVideo), XjRBoolean, (caddr_t) False },
43  { XjNpadding, XjCPadding, XjRInt, sizeof(int),
44      offset(arrow.padding), XjRString, "2" },
45  { XjNdirection, XjCDirection, XjRDirection, sizeof(int),
46      offset(arrow.direction), XjRString, XjNorth },
47  { XjNhighlightProc, XjCHighlightProc, XjRCallback, sizeof(XjCallback *),
48      offset(arrow.highlightProc), XjRString, "fillArrow(1)" },
49  { XjNunHighlightProc, XjCHighlightProc, XjRCallback, sizeof(XjCallback *),
50      offset(arrow.unHighlightProc), XjRString, "fillArrow(0)" },
51};
52
53#undef offset
54
55static void classInitialize(), expose(), realize(),
56  querySize(), move(), destroy(), resize(), computePoints();
57
58int fillArrow();
59
60ArrowClassRec arrowClassRec = {
61  {
62    /* class name */            "Arrow",
63    /* jet size   */            sizeof(ArrowRec),
64    /* classInitialize */       classInitialize,
65    /* classInitialized? */     0,
66    /* initialize */            NULL,
67    /* prerealize */            NULL,
68    /* realize */               realize,
69    /* event */                 NULL,
70    /* expose */                expose,
71    /* querySize */             querySize,
72    /* move */                  move,
73    /* resize */                resize,
74    /* destroy */               destroy,
75    /* resources */             resources,
76    /* number of 'em */         XjNumber(resources)
77  }
78};
79
80JetClass arrowJetClass = (JetClass)&arrowClassRec;
81
82
83static void classInitialize(me)
84     ArrowJet me;
85{
86  XjRegisterCallback(fillArrow, "fillArrow");
87}
88
89
90/*
91 * Things are currently broken screenwise.
92 * It will be fun to fix later. :)
93 */
94static void realize(me)
95     ArrowJet me;
96{
97  unsigned long valuemask;
98  XGCValues values;
99
100  if (me->arrow.reverseVideo)
101    {
102      int temp;
103
104      temp = me->arrow.foreground;
105      me->arrow.foreground = me->arrow.background;
106      me->arrow.background = temp;
107      if (me->arrow.fillColor == me->arrow.background)
108        me->arrow.fillColor = me->arrow.foreground;
109    }
110
111  values.foreground = me->arrow.foreground;
112  values.background = me->arrow.background;
113  values.function = GXcopy;
114  values.graphics_exposures = False;
115  valuemask = ( GCForeground | GCBackground |
116               GCFunction | GCGraphicsExposures );
117
118  me->arrow.gc_reverse = XjCreateGC(me->core.display,
119                                    me->core.window,
120                                    valuemask,
121                                    &values);
122
123  values.foreground = me->arrow.background;
124  values.background = me->arrow.foreground;
125  valuemask = ( GCForeground | GCBackground |
126               GCFunction | GCGraphicsExposures );
127
128  me->arrow.gc = XjCreateGC(me->core.display,
129                            me->core.window,
130                            valuemask,
131                            &values);
132
133  values.foreground = me->arrow.fillColor;
134  valuemask = ( GCForeground | GCBackground |
135               GCFunction | GCGraphicsExposures );
136
137  me->arrow.gc_fill = XjCreateGC(me->core.display,
138                                 me->core.window,
139                                 valuemask,
140                                 &values);
141}
142
143static void destroy(me)
144     ArrowJet me;
145{
146  XjFreeGC(me->core.display, me->arrow.gc);
147  XjFreeGC(me->core.display, me->arrow.gc_reverse);
148  XjFreeGC(me->core.display, me->arrow.gc_fill);
149}
150
151static void querySize(me, size)
152     ArrowJet me;
153     XjSize *size;
154{
155  if (DEBUG)
156    printf ("QS(arrow) '%s' w=%d,h=%d\n", me->core.name, me->core.width,
157            me->core.height);
158
159  size->width = me->core.width;
160  size->height = me->core.height;
161}
162
163static void move(me, x, y)
164     ArrowJet me;
165     int x, y;
166{
167  if (DEBUG)
168    printf ("MV(arrow) '%s' x=%d,y=%d\n", me->core.name, x, y);
169
170  me->core.x = x;
171  me->core.y = y;
172  computePoints(me);
173}
174
175static void resize(me, size)
176     Jet me;
177     XjSize *size;
178{
179  if (DEBUG)
180    printf ("RS(arrow) '%s' w=%d,d=%d\n",
181            me->core.name, size->width, size->height);
182
183  if (me->core.width != size->width
184      || me->core.height != size->height)
185    {
186      XClearArea(me->core.display, me->core.window,
187                 me->core.x, me->core.y,
188                 me->core.width, me->core.height,
189                 None);
190
191      me->core.width = size->width;
192      me->core.height = size->height;
193
194      computePoints(me);
195    }
196}
197
198
199static void expose(me, event)
200     Jet me;
201     XEvent *event;             /* ARGSUSED */
202{
203  ArrowJet aj = (ArrowJet) me;
204
205  XFillPolygon(me->core.display, me->core.window,
206               aj->arrow.gc,
207               aj->arrow.pt, aj->arrow.num_pts,
208               Nonconvex, CoordModeOrigin);
209  XDrawLines(me->core.display, me->core.window,
210             aj->arrow.gc_reverse,
211             aj->arrow.pt, aj->arrow.num_pts, CoordModeOrigin);
212}
213
214
215int fillArrow(me, fill, data)
216     Jet me;
217     int fill;
218     caddr_t data;              /* ARGSUSED */
219{
220  ArrowJet aj = (ArrowJet) me;
221
222  if (fill)
223    XFillPolygon(me->core.display, me->core.window,
224                 aj->arrow.gc_fill,
225                 aj->arrow.pt, aj->arrow.num_pts,
226                 Nonconvex, CoordModeOrigin);
227  else
228    XFillPolygon(me->core.display, me->core.window,
229                 aj->arrow.gc,
230                 aj->arrow.pt, aj->arrow.num_pts,
231                 Nonconvex, CoordModeOrigin);
232  XDrawLines(me->core.display, me->core.window,
233             aj->arrow.gc_reverse,
234             aj->arrow.pt, aj->arrow.num_pts, CoordModeOrigin);
235  return 0;
236}
237
238
239void setDirection(me, dir)
240     ArrowJet me;
241     int dir;
242{
243  XClearArea(me->core.display, me->core.window,
244             me->core.x, me->core.y,
245             me->core.width, me->core.height,
246             None);
247  me->arrow.direction = dir;
248
249  computePoints((Jet) me);
250  expose((Jet) me, NULL);
251}
252
253
254
255static void computePoints(me)
256     Jet me;
257{
258  ArrowJet aj = (ArrowJet) me;
259  int length = MIN(me->core.width, me->core.height);
260  int length2 = length - (2 * aj->arrow.padding);
261
262  aj->arrow.x = me->core.x + (me->core.width - length)/2;
263  aj->arrow.y = me->core.y + (me->core.height - length)/2;
264
265  if (aj->arrow.direction % 2)  /* the diagonals are all "odd" */
266    {
267/*
268 *  For an arrow pointing northeast, the points go something like this:
269 *
270 *  07-----6    Point 0 and 7 are identical, to close the figure.
271 *   \     |
272 *    1    |    For the other diagonals, you get the idea...
273 *   /     |
274 *  2   4  |
275 *   \ / \ |
276 *    3   \5
277 */
278      int i;
279      double len25 = length2 * .25;
280      double len35 = length2 * .35;
281      double len40 = length2 * .40;
282
283#define PT aj->arrow.pt
284#define PAD aj->arrow.padding
285#define len15  (len40-len25)
286#define len75  (len35+len40)
287#define len100 (len25+len75)
288#define LEN  (PAD + length2 - 1)
289
290      aj->arrow.num_pts = 8;
291
292      /*
293       * Assign the "X" coordinates first...
294       */
295      switch (aj->arrow.direction)
296        {
297        case 1:         /* northeast */
298        case 3:         /* southeast */
299          PT[0].x = PT[7].x = PAD + len15;
300          PT[1].x = PAD + len40;
301          PT[2].x = PAD;
302          PT[3].x = PAD + len35;
303          PT[4].x = PAD + len75;
304          PT[5].x = PT[6].x = PAD + length2;
305          break;
306
307        case 5:         /* southwest */
308          break;
309
310        case 7:         /* northwest */
311          break;
312        }
313
314      /*
315       * Now assign the "Y" coordinates...
316       */
317      switch (aj->arrow.direction)
318        {
319        case 1:         /* northeast */
320          PT[0].y = PT[6].y = PT[7].y = LEN - len100;
321          PT[1].y = LEN - len75;
322          PT[2].y = LEN - len35;
323          PT[3].y = LEN;
324          PT[4].y = LEN - len40;
325          PT[5].y = LEN - len15 /*len40 + len25*/;
326          break;
327
328        case 3:         /* southeast */
329          PT[0].y = PT[6].y = PT[7].y = PAD + len100;
330          PT[1].y = PAD + len75;
331          PT[2].y = PAD + len35;
332          PT[3].y = PAD;
333          PT[4].y = PAD + len40;
334          PT[5].y = PAD + len15;
335          break;
336
337        case 2:         /* east */
338        case 6:         /* west */
339          break;
340        }
341
342      for (i=0; i < aj->arrow.num_pts; i++)
343        {
344          PT[i].x += aj->arrow.x;
345          PT[i].y += aj->arrow.y;
346        }
347    }
348  else                          /* N, E, S, W are all "even" */
349    {
350/*
351 *  For an arrow pointing north, the points go something like this:
352 *      0--9       
353 *     /    \      Points 0 and 9 are distinct points, because of
354 *    /      \     the fact that we divide the width by 2 in order
355 *   /        \    to get the midpoint, and so for an even-width
356 *  1          8   arrow, the "tip" of the arrow will be off-center
357 *  2--3    6--7   by one pixel.
358 *     |    |
359 *     4----5      Similar ordering for the other major directions.
360 */
361      int l[8], x[8], y[8], i;
362      int length3 = (length + 1)/2 - 1;
363      int length4 = length2 * 2/7;
364
365      aj->arrow.num_pts = 10;
366
367      l[0] = aj->arrow.padding;
368      l[1] = length3;
369      l[2] = length/2;
370      l[3] = aj->arrow.padding + length2 - 1;
371      l[4] = aj->arrow.padding + length4;
372      l[5] = l[3] - length4;
373      l[6] = length3 + 1;
374      l[7] = l[2] - 1;
375
376      for (i=0; i<8; i++)
377        {
378          x[i] = l[i] + aj->arrow.x;
379          y[i] = l[i] + aj->arrow.y;
380        }
381
382      /*
383       * Assign the "X" coordinates first...
384       */
385      switch (aj->arrow.direction)
386        {
387        case 0:         /* north */
388        case 4:         /* south */
389          PT[0].x = x[1];
390          PT[1].x = PT[2].x = x[0];
391          PT[3].x = PT[4].x = x[4];
392          PT[5].x = PT[6].x = x[5];
393          PT[7].x = PT[8].x = x[3];
394          PT[9].x = x[2];
395          break;
396
397        case 2:         /* east */
398          PT[0].x = PT[9].x = x[3];
399          PT[1].x = PT[8].x = x[2];
400          PT[2].x = PT[3].x = PT[6].x = PT[7].x = x[7];
401          PT[4].x = PT[5].x = x[0];
402          break;
403
404        case 6:         /* west */
405          PT[0].x = PT[9].x = x[0];
406          PT[1].x = PT[8].x = x[1];
407          PT[2].x = PT[3].x = PT[6].x = PT[7].x = x[6];
408          PT[4].x = PT[5].x = x[3];
409          break;
410        }
411
412      /*
413       * Now assign the "Y" coordinates...
414       */
415      switch (aj->arrow.direction)
416        {
417        case 0:         /* north */
418          PT[0].y = PT[9].y = y[0];
419          PT[1].y = PT[8].y = y[1];
420          PT[2].y = PT[3].y = PT[6].y = PT[7].y = y[6];
421          PT[4].y = PT[5].y = y[3];
422          break;
423
424        case 4:         /* south */
425          PT[0].y = PT[9].y = y[3];
426          PT[1].y = PT[8].y = y[2];
427          PT[2].y = PT[3].y = PT[6].y = PT[7].y = y[7];
428          PT[4].y = PT[5].y = y[0];
429          break;
430
431        case 2:         /* east */
432        case 6:         /* west */
433          PT[0].y = y[1];
434          PT[1].y = PT[2].y = y[0];
435          PT[3].y = PT[4].y = y[4];
436          PT[5].y = PT[6].y = y[5];
437          PT[7].y = PT[8].y = y[3];
438          PT[9].y = y[2];
439          break;
440#undef PT
441        }
442    }
443}
Note: See TracBrowser for help on using the repository browser.