home *** CD-ROM | disk | FTP | other *** search
- /*
- ** James "im" Beninghaus
- */
-
- /*
- Version history
-
- 2.0 Nov 5 95 HTD
- "Updated" code for today's generation ;-).
- Added a callback parameter (so you could display the mouse coordinates
- while dragging the marquee, for example).
- Also added a "crop area" - you can confine the marquee selection
- to this area.
-
- 2.1 Nov 6
- Added TrackMarqueeOpaque() and ConstrainPointWithinRect().
- The problem with TrackMarquee occurs with color images that have
- grayish colors. Because of the use of patXor, the resulting
- marquee is grayish as well. The marquee is then VERY hard to see.
- The problem is, if you invert gray, you pretty much get gray!
- So TrackMarqueeOpaque adds an update callback procedure.
- TrackMarqueeOpaque does not use any patXor tricks but instead
- just plainly draws the marquee rect. However, we need a way to
- update the marquee (to erase the old marquee rect) which is
- what the callback proc is for.
- */
-
- #include "Marquee.h"
-
- // ---------------------------------------------------------------------------
-
- #define TICKDELAY 2
-
- /*
- ** Description
- ** TrackMarquee will display a marquee similar to the
- ** selection rectangle tool in MacPaintâ„¢. It is assumed that the
- ** current port has been set before calling.
- **
- ** Parameters
- ** start : the local coordinates where the mouse down occured. Mandatory.
- ** trackMouseProc : a callback procedure that will give you the current mouse's
- ** location. Optional (pass NULL)
- ** cropToRect : a rect in which to confine the marquee. Optional (pass NULL)
- ** resultRect : the final rectangle that was selected. Mandatory
- */
-
-
- void TrackMarquee(
- Point start,
- const Rect *cropToRect,
- Rect *resultRect) {
- /*
- ** there are fifteen patterns defined here
- ** each one eight bytes long starting at :
- ** patterns[0], patterns[1], patterns[2], patterns[3],
- ** patterns[4], patterns[5], patterns[6], patterns[7]
- */
- static unsigned char patterns[] = {
- 0xF8, 0xF1, 0xE3, 0xC7, 0x8F,
- 0x1F, 0x3E, 0x7C, 0xF8, 0xF1,
- 0xE3, 0xC7, 0x8F, 0x1F, 0x3E
- };
-
- Point mouse; /* the current mouse location */
- short index; /* the index of the current patterns array */
- Rect nowRect, /* the current rectangle to be framed */
- thenRect; /* the last rectangle to be framed */
- long nowTicks, /* the current tick count */
- thenTicks; /* the last tick count */
- PenState penState; /* the saved pen state on entry to procedure */
-
-
- thenTicks = 0;
- index = 0;
-
- GetPenState(&penState);
- PenMode(patXor);
-
- PenPat((ConstPatternParam)&patterns[index]);
- SetRect(&nowRect, start.h, start.v, start.h, start.v);
- FrameRect(&nowRect);
- thenRect = nowRect;
-
- while (StillDown()) {
- nowTicks = TickCount();
- GetMouse(&mouse);
-
- if (cropToRect != NULL) {
- ConstrainPointWithinRect(&mouse, cropToRect);
- }
-
- SetMobiusRect(&nowRect, start.h, start.v, mouse.h, mouse.v);
- if (((thenTicks + TICKDELAY) < nowTicks ? thenTicks = nowTicks, true : false) ||
- (!EqualRect(&nowRect, &thenRect))) {
-
- FrameRect(&thenRect);
- index = index < 7 ? index + 1 : 0;
-
- PenPat((ConstPatternParam)&patterns[index]);
- FrameRect(&nowRect);
- thenRect = nowRect;
- }
- }
- FrameRect(&thenRect);
-
- SetPenState(&penState);
- *resultRect = thenRect;
- } // END TrackMarquee
-
- // ---------------------------------------------------------------------------
-
- void TrackMarqueeOpaque(
- Point start,
- TrackUpdateProc trackUpdateProc,
- const RGBColor *marqueeColor,
- const Rect *cropToRect,
- Rect *resultRect) {
-
- Point mouse; /* the current mouse location */
- Rect nowRect, /* the current rectangle to be framed */
- thenRect; /* the last rectangle to be framed */
- long nowTicks, /* the current tick count */
- thenTicks; /* the last tick count */
-
- thenTicks = 0;
-
- SetRect(&nowRect, start.h, start.v, start.h, start.v);
- thenRect = nowRect;
-
- while (StillDown()) {
- nowTicks = TickCount();
- GetMouse(&mouse);
-
- if (cropToRect != NULL) {
- ConstrainPointWithinRect(&mouse, cropToRect);
- }
-
- SetMobiusRect(&nowRect, start.h, start.v, mouse.h, mouse.v);
-
- if (nowTicks > (thenTicks + TICKDELAY)) {
- thenTicks = nowTicks;
- // Erase old marquee
- trackUpdateProc(&thenRect, &nowRect);
- FrameMarquee(&nowRect, marqueeColor);
- thenRect = nowRect;
- }
- else if (!EqualRect(&nowRect, &thenRect) && nowTicks > (thenTicks + TICKDELAY)) {
- thenTicks = nowTicks;
- trackUpdateProc(&thenRect, &nowRect);
- FrameMarquee(&nowRect, marqueeColor);
- thenRect = nowRect;
- }
- }
- // Erase any visages of the marquee
- trackUpdateProc(&thenRect, &nowRect);
-
- *resultRect = thenRect;
- } // END TrackMarqueeOpaque
-
- // ---------------------------------------------------------------------------
-
- static long sIndex = 0; /* the index of the current patterns array */
-
- void FrameMarquee(const Rect *marqueeRect, const RGBColor *marqueeColor) {
- static unsigned char patterns[] = {
- 0xF8, 0xF1, 0xE3, 0xC7, 0x8F,
- 0x1F, 0x3E, 0x7C, 0xF8, 0xF1,
- 0xE3, 0xC7, 0x8F, 0x1F, 0x3E
- };
-
- PenState penState;
- RGBColor saveFore, saveBack, backColor;
-
- GetPenState(&penState);
- GetForeColor(&saveFore);
- GetBackColor(&saveBack);
- backColor.red = backColor.green = backColor.blue = 0xFFFF; // White
- RGBBackColor(&backColor);
-
- sIndex = sIndex < 7 ? sIndex + 1 : 0;
- PenPat((ConstPatternParam)&patterns[sIndex]);
- if (marqueeColor != NULL)
- RGBForeColor(marqueeColor);
- FrameRect(marqueeRect);
-
- RGBForeColor(&saveFore);
- RGBBackColor(&saveBack);
-
- SetPenState(&penState);
- } // END FrameMarquee
-
- // ---------------------------------------------------------------------------
-
- void SetMobiusRect(
- Rect *rect,
- short anchorLeft,
- short anchorTop,
- short curRight,
- short curBottom) {
-
- if (anchorLeft > curRight) {
- rect->left = curRight;
- rect->right = anchorLeft;
- } else {
- rect->left = anchorLeft;
- rect->right = curRight;
- }
- if (anchorTop > curBottom) {
- rect->top = curBottom;
- rect->bottom = anchorTop;
- } else {
- rect->top = anchorTop;
- rect->bottom = curBottom;
- }
- } // END SetMobiusRect
-
- // ---------------------------------------------------------------------------
-
- void ConstrainPointWithinRect(Point *point, const Rect *constrainRect) {
- if (point->h < constrainRect->left)
- point->h = constrainRect->left;
- else if (point->h > constrainRect->right)
- point->h = constrainRect->right;
- if (point->v < constrainRect->top)
- point->v = constrainRect->top;
- else if (point->v > constrainRect->bottom)
- point->v = constrainRect->bottom;
- } // END ConstrainPointWithinRect