home *** CD-ROM | disk | FTP | other *** search
- /*
- * TransSkel multiple-window demonstration: Region module
- *
- * This module handles a window in which the mouse may be clicked and
- * dragged to draw rectangles. The rects so drawn are combined into
- * a single region, the outline of which is drawn. Rects drawn while
- * the shift key is held down are subtracted from the region.
- * Double-clicking the mouse clears the display. If the window is
- * resized, the region that is drawn is resized as well.
- *
- * BUG: should measure double-click time from mouse-up to next mouse down,
- * not time between mouse-downs.
- *
- * 21 Apr 88 Paul DuBois
- * 08 Jul 88
- * - Changed outline so that it's drawn as a marquee.
- * 29 Jan 89
- * - Conversion for TransSkel 2.0.
- * 12 Jan 91
- * - Conversion for TransSkel 3.0.
- */
-
- # include "TransSkel.h"
-
- # include "MultiSkel.h"
-
-
- static Rect rgnPortRect; /* portRect size - for detecting wind grows */
- static RgnHandle selectRgn; /* current region to be drawn */
- static long selectWhen; /* time of last click */
- static Point selectWhere; /* location of last click */
-
- static Pattern marqueePat = { 0x0f, 0x87, 0xc3, 0xe1, 0xf0, 0x78, 0x3c, 0x1e };
-
-
- static void
- MarqueeRgn (RgnHandle r)
- {
- PenState p;
- Byte b;
- short i;
-
- GetPenState (&p);
- PenPat (marqueePat);
- PenMode (patCopy);
- FrameRgn (r);
- SetPenState (&p);
- b = marqueePat[0]; /* shift pattern for next call */
- for (i = 0; i < 7; ++i)
- marqueePat[i] = marqueePat[i+1];
- marqueePat[7] = b;
- }
-
-
- /*
- * While mouse is down, draw gray selection rectangle in the current
- * port. Return the resultant rect in dstRect. The rect is always
- * clipped to the current portRect.
- */
-
- static void
- DoSelectRect (Point startPoint, Rect *dstRect)
- {
- Point pt, dragPt;
- Rect rClip;
- GrafPtr thePort;
- Boolean result;
- PenState ps;
- short i;
-
- GetPort (&thePort);
- rClip = thePort->portRect;
- rClip.right -= 15;
- GetPenState (&ps);
- PenPat (gray);
- PenMode (patXor);
- dragPt = startPoint;
- Pt2Rect (dragPt, dragPt, dstRect);
- FrameRect (dstRect);
- for (;;)
- {
- GetMouse (&pt);
- if (!EqualPt (pt, dragPt)) /* mouse has moved, change region */
- {
- FrameRect (dstRect);
- dragPt = pt;
- Pt2Rect (dragPt, startPoint, dstRect);
- result = SectRect (dstRect, &rClip, dstRect);
- FrameRect (dstRect);
- for (i = 0; i < 1000; ++i) { /* empty */ }
- }
- if (!StillDown ()) break;
- }
- FrameRect (dstRect); /* erase last rect */
- SetPenState (&ps);
- }
-
-
- /*
- * On double-click, clear window. On single click, draw gray selection
- * rectangle as long as mouse is held down. If user draws non-empty rect,
- * then add it to the selection region and redraw the region's outline.
- * If the shift-key was down, then subtract the selection region instead
- * and redraw.
- */
-
- static pascal void
- Mouse (Point pt, long t, short mods)
- {
- Rect r;
- RgnHandle rgn;
-
- r = rgnWind->portRect;
- if (pt.h >= r.right - 15) /* must not click in right edge */
- return;
- if (t - selectWhen <= GetDblTime ()) /* it's a double-click */
- {
- selectWhen = 0L; /* don't take next click as double-click */
- SetWindClip (rgnWind);
- EraseRgn (selectRgn);
- ResetWindClip ();
- SetEmptyRgn (selectRgn); /* clear region */
- }
- else
- {
- selectWhen = t; /* update click variables */
- selectWhere = pt;
- DoSelectRect (pt, &r); /* draw selection rectangle */
- if (!EmptyRect (&r))
- {
- EraseRgn (selectRgn);
- selectWhen = 0L;
- rgn = NewRgn ();
- RectRgn (rgn, &r);
- if ((mods & shiftKey) != 0) /* test shift key */
- DiffRgn (selectRgn, rgn, selectRgn);
- else
- UnionRgn (selectRgn, rgn, selectRgn);
- DisposeRgn (rgn);
- }
- }
- }
-
-
- static pascal void
- Idle (void)
- {
- short i;
-
- SetWindClip (rgnWind);
- MarqueeRgn (selectRgn); /* draw selection region outline */
- ResetWindClip (); /* restore previous clipping */
- }
-
-
- /*
- * Redraw the current region. If the window was resized, resize
- * the region to fit.
- */
-
- static pascal void
- Update (Boolean resized)
- {
- Rect r;
-
- r = rgnWind->portRect;
- EraseRect (&r);
- if (resized)
- {
- rgnPortRect.right -= 15; /* don't use right edge of window */
- r.right -= 15;
- MapRgn (selectRgn, &rgnPortRect, &r);
- rgnPortRect = rgnWind->portRect;
- }
- DrawGrowBox (rgnWind);
- Idle ();
- }
-
-
- static pascal void
- Activate (Boolean active)
- {
- DrawGrowBox (rgnWind);
- if (active)
- DisableItem (editMenu, 0);
- else
- EnableItem (editMenu, 0);
- DrawMenuBar ();
- }
-
-
- static pascal void
- Clobber (void)
- {
- DisposeRgn (selectRgn);
- DisposeWindow (rgnWind);
- }
-
-
- void
- RgnWindInit (void)
- {
- if (SkelQuery (skelQHasColorQD))
- rgnWind = GetNewCWindow (rgnWindRes, nil, (WindowPtr) -1L);
- else
- rgnWind = GetNewWindow (rgnWindRes, nil, (WindowPtr) -1L);
- if (rgnWind == (WindowPtr) nil)
- return;
- (void) SkelWindow (rgnWind,
- Mouse, /* draw rectangles */
- nil, /* ignore keyclicks */
- Update,
- Activate,
- nil, /* no close proc */
- Clobber, /* disposal proc */
- Idle, /* idle proc */
- false);
-
- rgnPortRect = rgnWind->portRect;
- selectRgn = NewRgn (); /* selected region empty initially */
- selectWhen = 0L; /* first click can't be taken as dbl-click */
- }
-