home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-13 | 22.2 KB | 699 lines | [TEXT/KAHL] |
- //------------------------- © 1994 - 1995 by James G. Stout ------------------------
- // File : cdefHSlider.c
- // Date : April 6, 1994
- // Author : Jim Stout
- // :
- // Purpose : A slider CDEF modeled after the on in the Brightness Control panel
- // :
- // : see cdefHSlider.h for more detail and variation codes
- // :
- // : If you find a use for this, I'd love to know about it. Bug reports
- // : are always interesting.
- // :
- // : Internet : JimS@WRQ.COM(work hours, PST)
- // : AppleLink : WRQ (daily)
- // : CompuServe : 73240,2052 (weekly or so)
- // : AOL : JasG (weekly or so)
- // : eWorld : Jim Stout (weekly or so)
- //----------------------------------------------------------------------------------
- //#define _DEBUGCDEF // comment this to build CDEF
-
- #include "fatCDEF.h"
-
- #include <Controls.h>
- #include <GestaltEqu.h>
- #include <Memory.h>
- #include <QDOffscreen.h>
- #include <ToolUtils.h>
- #include <Types.h>
- #include <Windows.h>
-
- #include "grayCDEF.h"
- #include "colorCDEF.h"
- #include "miscCDEF.h"
- #include "qdCDEF.h"
-
- #include "cdefHSlider.h"
-
- #ifdef _DEBUGCDEF
- pascal long CDmain (short, ControlHandle, short, long);
-
- pascal long CDmain (short varCode, ControlHandle theCtl, short message, long param)
- #else
-
- //==================================================================================
- // CDEF entry point
- //==================================================================================
- pascal long main (short varCode, ControlHandle theCtl, short message, long param)
- #endif
- {
- long ret = 0L;
- SignedByte cState, dState;
-
- #include "fatEntry.c"
-
- cState = HGetState((Handle)theCtl);
- HLock((Handle)theCtl);
- if((**theCtl).contrlData) {
- dState = HGetState((**theCtl).contrlData);
- HLock((**theCtl).contrlData);
- }
-
- switch(message) {
- case initCntl:
- doInit(theCtl);
- if((**theCtl).contrlData) {
- dState = HGetState((**theCtl).contrlData);
- HLock((**theCtl).contrlData);
- }
- break;
- case dispCntl:
- doDisp(theCtl);
- break;
- case drawCntl:
- if ((**theCtl).contrlVis != 0 &&
- ((WindowPeek)(**theCtl).contrlOwner)->visible) {
- doDraw(theCtl, varCode);
- }
- break;
- case testCntl:
- ret = doTest (theCtl, varCode, param);
- break;
- case calcCRgns:
- RectRgn((RgnHandle)(param & 0x7fffffffL), &(**theCtl).contrlRect);
- break;
- case calcCntlRgn:
- case calcThumbRgn:
- RectRgn((RgnHandle)(param), &(**theCtl).contrlRect);
- break;
- }
-
- if((**theCtl).contrlData)
- HSetState((**theCtl).contrlData, dState);
- HSetState((Handle)theCtl, cState);
-
- #include "fatExit.c"
-
- return (ret);
- }
-
- //==================================================================================
- // Initialize our control data
- //==================================================================================
-
- static void doInit (ControlHandle theCtl)
- {
- Rect scaleRect;
- CGrafPtr offPort=0;
- CDEFHandle hCDEF;
-
- //----------------------------------------------------------------------------------
- // force the scale rect to the size we want. It'll be clipped to the control Rect
- //----------------------------------------------------------------------------------
-
- scaleRect = (**theCtl).contrlRect;
- scaleRect.right = scaleRect.left + 121;
- scaleRect.bottom = scaleRect.top + 24;
-
- //----------------------------------------------------------------------------------
- // force the min & max as well
- //----------------------------------------------------------------------------------
-
- (**theCtl).contrlMin = 0;
- (**theCtl).contrlMax = 100; // number of pixels in scale
-
- hCDEF = (CDEFHandle)NewHandle(sizeof(CDEFData));
- if(hCDEF) {
- (**hCDEF).pDepth = 1; // filled in in doDraw()
- (**hCDEF).offPort = 0;
- (**hCDEF).scaleRect = scaleRect;
- (**hCDEF).qdVers = getQDVers();
-
- (**theCtl).contrlData = (Handle)hCDEF;
- }
- else
- (**theCtl).contrlData = 0;
- }
-
- //==================================================================================
- // Get rid of our control data
- //==================================================================================
-
- static void doDisp (ControlHandle theCtl)
- {
- BitMap *theBits;
- CDEFHandle hCDEF;
-
- hCDEF = (CDEFHandle)(**theCtl).contrlData;
- if(hCDEF) {
- if((**hCDEF).offPort) {
- if(((**hCDEF).offPort->portVersion & 0x8000) != 0) { // offPort is GWorld
- DisposeGWorld((**hCDEF).offPort);
- }
- else { // offport is bitmap
- theBits = &((GrafPtr)(**hCDEF).offPort)->portBits;
- DisposePtr((*theBits).baseAddr);
- ClosePort((GrafPtr)(**hCDEF).offPort);
- DisposePtr((Ptr)(**hCDEF).offPort);
- }
- }
- HUnlock((Handle)hCDEF);
- DisposeHandle((Handle)hCDEF);
- (**theCtl).contrlData = 0;
- }
- }
-
- //==================================================================================
- // Test to see if the mouse was pressed in the control thumb and drag accordingly
- //==================================================================================
-
- static long doTest (ControlHandle theCtl, short varCode, long param)
- {
- Rect rThumb, rScale;
- Point p;
- long ret=0,secs;
- short partCode;
- CDEFHandle hCDEF;
-
- hCDEF = (CDEFHandle)(**theCtl).contrlData;
- if(!hCDEF)
- return(ret);
-
- partCode = (**theCtl).contrlHilite;
- rScale = (**hCDEF).scaleRect;
-
- //----------------------------------------------------------------------------------
- // get the thumb rect, calculated from control value
- //----------------------------------------------------------------------------------
-
- getThumbRect(theCtl, &rThumb, &rScale);
- InsetRect(&rScale,4,7); // inset for active area
-
- p.h = LoWord(param);
- p.v = HiWord(param);
-
- if(PtInRect(p, &rThumb)) { // click in thumb?
- ret = 1;
- dragThumb(theCtl, varCode, param);
- }
- else
- if(PtInRect(p, &rScale)) { // click in scale?
- if(p.h < rThumb.left)
- ret = 2; // decrease
- else
- if(p.h > rThumb.right)
- ret = 3; // increase
-
- if(partCode == ret) {
- scaleClick(theCtl, varCode, (short)ret);
- Delay(6L, & secs);
- }
- }
- return(ret);
- }
-
- //==================================================================================
- // Respond to a mouse down in our "thumb", track the mouse to reposition the thumb,
- // set a new control value and call the actionProc (if any).
- //==================================================================================
- static void dragThumb (ControlHandle theCtl, short varCode, long param)
- {
- short newVal,maxDrag,minDrag;
- Rect rThumb, rScale;
- Point p,oldPt;
-
- rScale = (**(CDEFHandle)(**theCtl).contrlData).scaleRect;
- getThumbRect(theCtl, &rThumb, &rScale);
-
- p.h = oldPt.h = LoWord(param);
- p.v = HiWord(param);
-
- if(PtInRect(p, &rThumb)) {
- maxDrag = rScale.right - 4 - (rThumb.right - p.h);
- minDrag = rScale.left + 4 + (p.h - rThumb.left);
- while (StillDown()) {
- if(oldPt.h != p.h) { // mouse moved
- OffsetRect(&rThumb, (p.h-oldPt.h), 0); // move the thumb
- if(rThumb.left < rScale.left+5) { // pin to left of scale
- OffsetRect(&rThumb, rScale.left - rThumb.left+5, 0);
- }
- else
- if(rThumb.right > rScale.right-5) { // pin to right of scale
- OffsetRect(&rThumb, rScale.right - rThumb.right-5, 0);
- }
- newVal = -(rScale.left - rThumb.left + 5);
- if(newVal != (**theCtl).contrlValue) {
- (**theCtl).contrlValue = newVal;
- doDraw(theCtl, varCode);
- if((**theCtl).contrlAction != nil)
- CallControlActionProc((**theCtl).contrlAction,
- theCtl, 1);
- }
- if(p.h > minDrag && p.h < maxDrag) // track move
- oldPt.h = p.h;
- }
- GetMouse(&p);
- }
- }
- }
-
- //==================================================================================
- // Adjust the control after detecting a click in the scale instead of the thumb -
- // set a new control value and call the actionProc (if any).
- //==================================================================================
- static void scaleClick (ControlHandle theCtl, short varCode, short partCode)
- {
- Rect rThumb, rScale;
- short newVal;
-
- rScale = (**(CDEFHandle)(**theCtl).contrlData).scaleRect;
- getThumbRect(theCtl, &rThumb, &rScale);
-
- if(partCode == 2) {
- OffsetRect(&rThumb, -1, 0);
- }
- else
- if(partCode == 3) {
- OffsetRect(&rThumb, 1, 0);
- }
- if(rThumb.left < rScale.left+5) // pin to left of scale
- OffsetRect(&rThumb, rScale.left - rThumb.left+5, 0);
- else
- if(rThumb.right > rScale.right-5) // pin to right of scale
- OffsetRect(&rThumb, rScale.right - rThumb.right-5, 0);
-
- newVal = -(rScale.left - rThumb.left + 5);
-
- if(newVal != (**theCtl).contrlValue) {
- (**theCtl).contrlValue = newVal;
- doDraw(theCtl, varCode);
- if((**theCtl).contrlAction != nil)
- CallControlActionProc((**theCtl).contrlAction, theCtl, partCode);
- }
- }
-
- //==================================================================================
- // Calculate the thumb location from the control value
- //==================================================================================
-
- static void getThumbRect(ControlHandle theCtl, Rect *rThumb, Rect *rScale)
- {
- short h;
-
- SetRect(rThumb, 0, 0, 11, 24);
- h = (**theCtl).contrlValue + (rScale)->left + 5;
- OffsetRect(rThumb, h, (rScale)->top);
- }
-
- //==================================================================================
- // Draw both the scale and thumb into one bitmap. We've got the scale & thumb
- // stored as bitmap data in a char array in cdefHSliderBits.c.
- //==================================================================================
-
- Boolean drawParts (ControlHandle theCtl, short varCode, Rect *rThumb)
- {
- #include "cdefHSliderBits.c" // bitmap data
-
- Rect rScale, r, partRect;
- Boolean inColor = false, haveGray = false;
- RGBColor saveFore, saveBack, grayFrame, tingeColor, fillColor;
- RGBColor scaleColor = {56797, 56797, 56797};
- BitMap bits;
- GrafPtr offPort;
- Pattern pat = { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
- RgnHandle saveClip, clipRgn;
- CDEFHandle hCDEF;
-
- hCDEF = (CDEFHandle)(**theCtl).contrlData; // already locked
- if(hCDEF) {
- //----------------------------------------------------------------------------------
- // set up our drawing rects & save clip region since we change it below
- //----------------------------------------------------------------------------------
-
- SetRect(&rScale, 0, 0, 121, 24);
- r = partRect = rScale ;
-
- saveClip = NewRgn();
- GetClip(saveClip);
-
- //----------------------------------------------------------------------------------
- // Set colors - either cFrameColor or grayed version of cFrameColor if inactive
- //----------------------------------------------------------------------------------
-
- if((**hCDEF).pDepth > 2) {
- inColor = true;
- setPartColor(theCtl, cFrameColor, true);
- }
- else
- ForeColor(blackColor);
-
- if((**theCtl).contrlHilite == 0xFF) { // inactive control
- if(inColor) { // try to draw it in
- haveGray = getGray(&grayFrame); // gray
- if(haveGray)
- RGBForeColor(&grayFrame);
- }
- }
-
- if(inColor)
- saveColors(&saveFore, &saveBack); // saveFore may be gray...
-
- //----------------------------------------------------------------------------------
- // Clip drawing to the scale so we don't wipe out any background pattern
- //----------------------------------------------------------------------------------
-
- InsetRect(&rScale, 0, 5);
- clipRgn = NewRgn();
- OpenRgn();
- FrameRoundRect(&rScale, 11, 11);
- CloseRgn(clipRgn);
- SetClip(clipRgn);
-
- //----------------------------------------------------------------------------------
- // draw the scale into this offport
- //----------------------------------------------------------------------------------
-
- offPort = (GrafPtr)(**hCDEF).offPort;
- // construct a bitmap
- bits.bounds = partRect; // on the fly…
- bits.rowBytes = 16; // for the scale
- bits.baseAddr = hScale; // in data array
-
- BackColor(whiteColor); // foreColor set above
-
- CopyBits(&bits, // from bitmap
- &(offPort)->portBits, // to offscreen port
- &bits.bounds, // from rect
- &bits.bounds, // to rect
- srcCopy, nil);
-
- //----------------------------------------------------------------------------------
- // draw the 3D version of the scale
- //----------------------------------------------------------------------------------
-
- if(varCode & ctl3D && inColor) {
- InsetRect(&partRect, 3, 8);
- RGBForeColor(&scaleColor);
- RGBBackColor(&saveBack);
-
- //----------------------------------------------------------------------------------
- // fill center of scale with light gray
- //----------------------------------------------------------------------------------
-
- PaintRoundRect(&partRect,4,4);
-
- //----------------------------------------------------------------------------------
- // draw 3D shadow along bottom & right
- //----------------------------------------------------------------------------------
-
- setPartColor(theCtl, cTingeLight, true);
- GetForeColor(&tingeColor);
- tingeColor.red-=13107;
- tingeColor.green-=13107;
- tingeColor.blue-=13107;
- RGBForeColor(&tingeColor);
- MoveTo(partRect.left+1, partRect.bottom-1);
- LineTo(partRect.right-2, partRect.bottom-1);
- MoveTo(partRect.right-1, partRect.bottom-2);
- LineTo(partRect.right-1, partRect.top+1);
- MoveTo(partRect.right-2, partRect.bottom-2);
- LineTo(partRect.right-2, partRect.bottom-2);
- }
- else
-
- //----------------------------------------------------------------------------------
- // Draw other scale variations
- //----------------------------------------------------------------------------------
-
- if(varCode & scaleNoFill) {
- if(inColor)
- setPartColor(theCtl, cBodyColor, false);
- InsetRect(&partRect, 3, 8);
- PenPat( (ConstPatternParam) "\x00\x00\x00\x00\x00\x00\x00\x00");
- PaintRoundRect(&partRect, 4,4);
- }
- else
- if(varCode & scaleGray) {
- if(inColor) {
- setPartColor(theCtl, cBodyColor, true);
- GetForeColor(&fillColor);
- if(fillColor.red == 65535 &&
- fillColor.green == 65535 &&
- fillColor.blue == 65535) {
- ForeColor(blackColor);
- }
- if(haveGray) { // must be inactive
- if(getGray(&fillColor)) {
- RGBForeColor(&fillColor);
- }
- }
- }
- InsetRect(&partRect, 3, 8);
- FillRoundRect(&partRect, 4, 4, &pat);
- }
-
- //----------------------------------------------------------------------------------
- // draw the thumb - first, clip our drawing to the shape of the thumb so we don't
- // wipe out any background pattern.
- //----------------------------------------------------------------------------------
-
- if(clipRgn)
- DisposeRgn(clipRgn);
- clipRgn = NewRgn();
- OpenRgn();
- FrameRoundRect(rThumb, 12, 8);
- CloseRgn(clipRgn);
- SetClip(clipRgn);
-
- //----------------------------------------------------------------------------------
- // Now, blit the thumb to the screen & colorize/shade it if needed
- //----------------------------------------------------------------------------------
- if(inColor) {
- RGBForeColor(&saveFore);
- BackColor(whiteColor);
- }
-
- SetRect(&partRect, 0, 0, 11, 24); // construct a bitmap
- bits.bounds = partRect; // on the fly…
- bits.rowBytes = 2; // for the thumb
- bits.baseAddr = hThumb; // in data array
-
- CopyBits(&bits, // from bitmap
- &(offPort)->portBits, // to onscreen port
- &partRect, // from rect
- rThumb, // to rect
- srcCopy, nil);
-
- //----------------------------------------------------------------------------------
- // Draw 3D version of thumb
- //----------------------------------------------------------------------------------
-
- if(varCode & ctl3D && inColor) {
- RGBForeColor(&scaleColor);
- InsetRect(rThumb, 3, 1);
- PaintRect(rThumb);
-
- MoveTo((*rThumb).left-2, (*rThumb).bottom-2);
- LineTo((*rThumb).left-2, (*rThumb).top+1);
- MoveTo((*rThumb).right+1, (*rThumb).bottom-2);
- LineTo((*rThumb).right+1, (*rThumb).top+1);
-
- //----------------------------------------------------------------------------------
- // draw the 3D shadow in a grayed cTingeColor
- //----------------------------------------------------------------------------------
-
- RGBForeColor(&tingeColor);
- MoveTo((*rThumb).left, (*rThumb).bottom-1);
- LineTo((*rThumb).right-1, (*rThumb).bottom-1);
- LineTo((*rThumb).right-1, (*rThumb).top);
- MoveTo((*rThumb).right-2, (*rThumb).bottom-2);
- LineTo((*rThumb).right-2, (*rThumb).bottom-2);
- }
- else { // colorize center part
- if(inColor) { // of thumb
- ForeColor(whiteColor);
- setPartColor(theCtl, cThumbColor, true);
- InsetRect(rThumb, 3, 1);
- PaintRect(rThumb);
- }
- }
- }
- SetClip(saveClip);
- DisposeRgn(saveClip);
- DisposeRgn(clipRgn);
-
- return(haveGray);
- }
-
- //==================================================================================
- // Draw the control, it is made up from the scale bitmap and the thumb bitmap
- // which are assembled into an offscreen bitmap in "drawParts".
- //==================================================================================
-
- static void doDraw (ControlHandle theCtl, short varCode)
- {
- Rect offRect,rThumb,rScale;
- RgnHandle saveClip, newClip;
- BitMap *offBits;
- PixMapHandle pmHdl;
- CGrafPtr savePort;
- GDHandle saveGDev;
- PenState savePen;
- Boolean inactive = false, haveGray = false, inColor = false, haveGW = false;
- RGBColor saveFore,saveBack;
- CDEFHandle hCDEF;
-
- hCDEF = (CDEFHandle)(**theCtl).contrlData; // already locked
- if(hCDEF) {
-
- //----------------------------------------------------------------------------------
- // If control has been moved we need to update our rect
- //----------------------------------------------------------------------------------
-
- rScale = (**theCtl).contrlRect;
- rScale.right = rScale.left + 121;
- rScale.bottom = rScale.top + 24;
-
- (**hCDEF).scaleRect = rScale;
- (**theCtl).contrlData = (Handle)hCDEF;
-
- //----------------------------------------------------------------------------------
- // Create or update our GWorld
- //----------------------------------------------------------------------------------
-
- (**hCDEF).pDepth = getOff(&(**hCDEF).offPort, &(**theCtl).contrlRect);
-
- if((**hCDEF).pDepth == 0) // oh… oh…
- return;
-
- if(((**hCDEF).offPort->portVersion & 0x8000) != 0) { // have a GWorld
- haveGW = true;
- pmHdl = getLockedPixels(&(**hCDEF).offPort, (**hCDEF).qdVers);
- if(!pmHdl)
- return; // nuts…
- }
-
- //----------------------------------------------------------------------------------
- // Do the clip region properly. Thanks Ari!
- //----------------------------------------------------------------------------------
-
- saveClip = NewRgn();
- GetClip(saveClip);
-
- newClip = NewRgn();
- RectRgn(newClip, &(**theCtl).contrlRect);
- SectRgn(saveClip, newClip, newClip);
-
- if(EmptyRgn(newClip)) { // if empty, don't waste
- DisposeRgn(saveClip); // time drawing...
- DisposeRgn(newClip);
- return;
- }
-
- SetClip(newClip);
-
- //----------------------------------------------------------------------------------
- // Calculate size for offRect (scale) & position the thumb rect
- //----------------------------------------------------------------------------------
-
- SetRect(&offRect, 0, 0, 121, 24);
- rScale = (**hCDEF).scaleRect;
-
- SetRect(&rThumb, 0, 0, 11, 24);
- OffsetRect(&rThumb, (**theCtl).contrlValue+5,0);
-
- //----------------------------------------------------------------------------------
- // Initialize and set for drawing into offScreen port
- //----------------------------------------------------------------------------------
-
- if((**theCtl).contrlHilite == 0xFF) // inactive control
- inactive = true;
-
- if((**hCDEF).pDepth > 2) { // save onscreen
- inColor = true; // colors
- saveColors(&saveFore, &saveBack);
- }
-
- if(haveGW) { // we have a pixMap
- GetGWorld(&savePort, &saveGDev);
- SetGWorld((**hCDEF).offPort, nil);
- offBits = (BitMap *)*pmHdl;
- if((**(*savePort).bkPixPat).patType != 0 &&
- (savePort->portVersion & 0x8000) != 0)
- BackPixPat((*savePort).bkPixPat);
- }
- else { // we have a bitMap
- GetPort((GrafPtr*)&savePort);
- SetPort((GrafPtr)(**hCDEF).offPort);
- offBits = (BitMap *)&((GrafPtr)(**hCDEF).offPort)->portBits;
- }
-
- if(inColor) { // need same colors
- RGBForeColor(&saveFore); // offscreen
- RGBBackColor(&saveBack);
- }
-
- //----------------------------------------------------------------------------------
- // Erase background of offscreen port - pay attention to origin so patterned
- // backgrounds are aligned
- //----------------------------------------------------------------------------------
-
- SetOrigin((**theCtl).contrlRect.left, (**theCtl).contrlRect.top);
- EraseRect(&(**theCtl).contrlRect);
- SetOrigin(0,0);
-
- //----------------------------------------------------------------------------------
- // draw the control parts into the offscreen port
- //----------------------------------------------------------------------------------
-
- haveGray = drawParts (theCtl, varCode, &rThumb);
-
- //----------------------------------------------------------------------------------
- // Now, set up to copy the offscreen bit/pixmap to the screen
- //----------------------------------------------------------------------------------
-
- if(haveGW)
- SetGWorld(savePort, saveGDev);
- else
- SetPort((GrafPtr)savePort);
-
- if(inColor) {
- ForeColor(blackColor);
- BackColor(whiteColor);
- }
-
- //----------------------------------------------------------------------------------
- // now copy it to the onscreen port and restore our colors
- //----------------------------------------------------------------------------------
-
- CopyBits(offBits,
- &((GrafPtr)savePort)->portBits,
- &offRect,
- &rScale,
- srcCopy, nil);
-
- if(haveGW) {
- unlockPixels(pmHdl, (**hCDEF).qdVers);
- DisposeGWorld((**hCDEF).offPort);
- (**hCDEF).offPort = 0;
- }
-
- if(inColor)
- restoreColors(&saveFore, &saveBack);
-
- //----------------------------------------------------------------------------------
- // if we failed to get an inactive gray color, do it the old way
- //----------------------------------------------------------------------------------
-
- if(inactive && !haveGray) { // use the old way of drawing
- GetPenState(&savePen); // an inactive control
- PenMode(patBic);
- PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
- PaintRect(&(**theCtl).contrlRect);
- SetPenState(&savePen);
- }
- SetClip(saveClip);
- DisposeRgn(saveClip);
- DisposeRgn(newClip);
- }
- }