home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-30 | 17.7 KB | 548 lines | [TEXT/CWIE] |
- // ===========================================================================
- // LAGAPushButton.cp
- // ===========================================================================
- // “Apple Grayscale Appearance” compliant (almost) Push Button
- // Copyright © 1996 Chrisoft (Christophe ANDRES) All rights reserved.
- //
- // You may use this source code in any application (commercial, shareware, freeware,
- // postcardware, etc), but not remove this notice (no need to acknowledge the use of
- // this class in the about box)
- // You may not sell this source code in any form. This source code may be placed on
- // publicly accessable archive sites and source code disks. It may not be placed on
- // profit archive sites and source code disks without the permission of the author,
- // Christophe ANDRES.
- //
- // This source code is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- //
- // If you make any change or improvement on this class, please send the improved/changed
- // version to : chrisoft@calva.net or Christophe ANDRES
- // 20, rue Prosper Mérimée
- // 67100 STRASBOURG
- // FRANCE
- //
- // ===========================================================================
- // LAGAPushButton.h <- double-click + Command-D to see class declaration
- //
- // LAGAPushButton is my implementation of the “Apple Grayscale Appearance for System 7.5”
- // Push Buttons with the exception of the pressed state. The pressed state is my own kind,
- // because I (and my customers) found it nicer than Apple's ;-)
- //
- // if mRadioBehavior is set, the Push Button acts as a RadioButton and can be used with
- // a radio group
- //
- // This class requires AGAColors.cp to be present in your project
- //
- // Version : 1.2
- //
- // Change History (most recent first, date in US form : mm/dd/yy):
- //
- // 06/30/96 ca Public release of version 1.2
- // 06/27/96 ca Changed checks for disabled state (check on triState_On instead of triState_Off)
- // in order that triState_Latent state is drawn as disabled
- // 06/04/96 ca Added static RegisterClass for easier class registration
- // made changes to allow the usage of either the standard button template or the custom LAGAPushButton
- // template. The standard button template is easier for layout because you can see the text, but you
- // can't control the checkbox behavior of the button, which is possible from the custom template
- // Defined class_ID1 and CreateAGAPushButtonStream1 to handle the two template possibilities
- // Added a CPPb to "LAGAPushButton CPPb.rsrc" called LAGAPushButton1 to handle the standard button
- // template, without having to tinker the class ID
- // Increased version to 1.2
- // 06/01/96 ms Changes brought by Marco Sandri <msandri@mbox.vol.it>
- // Changes made to avoid icon "flicker" during pressing
- // 05/15/96 ca Increased version to 1.1
- // Replaced mTextTraitsH by mTextTraitsID, to simplify, text traits management
- // Replaced UEnvironment::HasFeature(env_SupportsColor) with PaneInColor
- // Added copy constructor
- // Added "on the fly" constructor
- // Added change history
- // 04/??/96 jhs Improvements sent by James H. Stein <steinj@best.com>
- // Added missing includes (for those who do not use the "classic" PP prefix)
- // Added adjustement for italics
- // Added frame adjustment if the font is the text is higher than the button
- // 04/22/96 ca class made available by Christophe ANDRES <chrisoft@calva.net>
- // (version 1.0)
- //
- // To Do:
- //
-
- #include "LAGAPushButton.h"
- #include "AGAColors.h"
- #include <UDrawingState.h>
- #include <UDrawingUtils.h>
- #include <PP_Messages.h>
- #include <PP_Resources.h>
-
- char LAGAPushButton::mCorners[3][4][4][4] = {
- // Enabled
- {
- // topleft
- {
- { -1, -1, 12, B },
- { -1, B, 4, 2 },
- { 12, 4, W, W },
- { B, 2, W, W }
- },
- // topright
- {
- { B, 12, -1, -1 },
- { 2, 4, B, -1 },
- { W, 2, 5, 12 },
- { 2, 5, 8, B }
- },
- // bottomleft
- {
- { B, 2, W, 2 },
- { 12, 4, 2, 5 },
- { -1, B, 4, 8 },
- { -1, -1, 12, B }
- },
- // bottomright
- {
- { 5, 5, 8, B },
- { 5, 8, 8, 12 },
- { 8, 8, B, -1 },
- { B, 12, -1, -1 }
- }
- },
- // Pressed
- {
- // topleft
- {
- { -1, -1, 12, B },
- { -1, B, 10, 8 },
- { 12, 10, 8, 4 },
- { B, 8, 4, 4 }
- },
- // topright
- {
- { B, 12, -1, -1 },
- { 8, 10, B, -1 },
- { 4, 4, 8, 12 },
- { 4, 4, 4, B }
- },
- // bottomleft
- {
- { B, 8, 4, 4 },
- { 12, 10, 4, 4 },
- { -1, B, 10, 4 },
- { -1, -1, 12, B }
- },
- // bottomright
- {
- { 4, 4, 4, B },
- { 4, 4, 10, 12 },
- { 4, 10, B, -1 },
- { B, 12, -1, -1 }
- }
- },
- // Disabled
- {
- // topleft
- {
- { -1, -1, 7, 7 },
- { -1, 7, 4, 2 },
- { 7, 4, 1, 1 },
- { 7, 2, 1, 1 }
- },
- // topright
- {
- { 7, 7, -1, -1 },
- { 2, 4, 7, -1 },
- { 1, 2, 4, 7 },
- { 2, 4, 5, 7 }
- },
- // bottomleft
- {
- { 7, 2, 1, 2 },
- { 7, 4, 2, 4 },
- { -1, 7, 4, 5 },
- { -1, -1, 7, 7 }
- },
- // bottomright
- {
- { 4, 4, 5, 7 },
- { 4, 5, 5, 7 },
- { 5, 5, 7, -1 },
- { 7, 7, -1, -1 }
- }
- }
- };
-
- // begin <06/04/96 ca>
- void LAGAPushButton::RegisterClass ()
-
- {
- URegistrar::RegisterClass(LAGAPushButton::class_ID, (ClassCreatorFunc)LAGAPushButton::CreateAGAPushButtonStream);
- URegistrar::RegisterClass(LAGAPushButton::class_ID1, (ClassCreatorFunc)LAGAPushButton::CreateAGAPushButtonStream1);
- }
- // end <06/04/96 ca>
-
- LAGAPushButton* LAGAPushButton::CreateAGAPushButtonStream (LStream *inStream)
-
- {
- // Constructing from a 'AGA7' template
- return(new LAGAPushButton(inStream));
- }
-
- LAGAPushButton* LAGAPushButton::CreateAGAPushButtonStream1 (LStream *inStream)
-
- {
- // Constructing from a 'AgA7' template
- return(new LAGAPushButton(inStream, true));
- }
-
- //-------Constructors-------------------------------------------------------------------------------------------------
-
- LAGAPushButton::LAGAPushButton ()
-
- {
- mTextTraitsID = Txtr_SystemFont; // <05/15/96 ca>
- mStyleCache = -1; // <05/15/96 ca>
- mRadioBehavior = false;
- }
-
- LAGAPushButton::LAGAPushButton (LStream *inStream, Boolean inCreateWithStandardButton) : LControl(inStream)
-
- {
- mStyleCache = -1; // <05/15/96 ca>
-
- if (inCreateWithStandardButton)
- {
- // begin <06/04/96 ca>
- // Change so we can use the standard button template; makes layout easier
- Int16 controlKind;
- ResIDT textTraitsID;
- Str255 title;
- Int32 macRefCon;
-
- inStream->ReadData(&controlKind, sizeof(Int16)); // Ignored
- inStream->ReadData(&mTextTraitsID, sizeof(ResIDT));
- inStream->ReadPString(mTitle);
- inStream->ReadData(&macRefCon, sizeof(Int32)); // Ignored
- mRadioBehavior = false;
- // end <06/04/96 ca>
- }
- else
- {
- unsigned char radioBehavior;
-
- inStream->ReadPString(mTitle);
-
- inStream->ReadData(&mTextTraitsID, sizeof (ResIDT)); // <05/15/96 ca>
-
- inStream->ReadData(&radioBehavior, sizeof(unsigned char));
- mRadioBehavior = (radioBehavior != 0);
- if (mRadioBehavior)
- mMaxValue = 1;
- }
- }
-
- // begin <05/15/96 ca>
- LAGAPushButton::LAGAPushButton (const LAGAPushButton &inOriginal) : LControl(inOriginal)
-
- {
- mTitle = inOriginal.mTitle;
- mTextTraitsID = inOriginal.mTextTraitsID;
- mStyleCache = inOriginal.mStyleCache;
- mRadioBehavior = inOriginal.mRadioBehavior;
- if (mRadioBehavior)
- mMaxValue = 1;
- }
-
- LAGAPushButton::LAGAPushButton (const SPaneInfo &inPaneInfo, MessageT inClickedMessage, ResIDT inTextTraitsID,
- Str255 inTitle, Boolean inRadioButtonBehavior) : LControl(inPaneInfo, inClickedMessage, 0, 0, 1)
- {
- mTitle = inTitle;
- mTextTraitsID = inTextTraitsID;
- mStyleCache = -1;
- mRadioBehavior = inRadioButtonBehavior;
- if (mRadioBehavior)
- mMaxValue = 1;
- }
- // end <05/15/96 ca>
-
- //-------Utilities--------------------------------------------------------------------------------------------------
-
- void LAGAPushButton::HotSpotResult (Int16 inHotSpot)
-
- {
- // Undo Button hilighting
- if (!mRadioBehavior)
- {
- HotSpotAction(inHotSpot, false, true);
- BroadcastValueMessage(); // Although value doesn't change,
- // send message to inform Listeners
- // that button was clicked
- }
- else
- {
- // In the Mac interface, clicking on a RadioButton always
- // turns it on (or leaves it on). The standard way to turn
- // off a RadioButton is to turn on another one in the
- // same Radio Group. A Radio Group will normally be a
- // Listener of a RadioButton.
-
- if (mValue != Button_On) // <06/01/96 ms>
- SetValue(Button_On);
- }
- }
-
- void LAGAPushButton::HotSpotAction (Int16 inHotSpot, Boolean inCurrInside, Boolean inPrevInside)
-
- {
- // Draw if cursor moved from IN to OUT
- // or from OUT to IN
- if (inCurrInside != inPrevInside && (!mRadioBehavior || mValue != Button_On)) // <06/01/96 ms>
- {
- FocusDraw();
- DrawAll(inCurrInside);
- }
- }
-
- void LAGAPushButton::SetValue (Int32 inValue)
-
- {
-
- if (!mRadioBehavior)
- {
- LControl::SetValue(inValue);
- }
- else
- {
- if (inValue < mMinValue)
- inValue = mMinValue;
- else
- if (inValue > mMaxValue)
- inValue = mMaxValue;
- mValue = inValue;
- // If turning RadioButton on, broadcast message so that the
- // RadioGroup (if present) will turn off the other RadioButtons
- // in the group.
-
- if (inValue == Button_On)
- {
- BroadcastValueMessage();
- BroadcastMessage(msg_ControlClicked, (void*) this);
- }
- Draw(nil); // <06/01/96 ms>
- }
- }
-
- StringPtr LAGAPushButton::GetDescriptor (Str255 outDescriptor) const
-
- {
- return LString::CopyPStr(mTitle, outDescriptor);
- }
-
- void LAGAPushButton::SetDescriptor (ConstStr255Param inDescriptor)
-
- {
- mTitle = inDescriptor;
- Refresh();
- }
-
- //-------Drawers----------------------------------------------------------------------------------------------------
-
- void LAGAPushButton::DrawSelf ()
-
- {
- DrawAll(false);
- }
-
- void LAGAPushButton::DrawAll (Boolean inPushed)
-
- {
- DrawGraphic(inPushed);
- DrawText(inPushed);
- }
-
- void LAGAPushButton::DrawGraphic (Boolean inPushed)
-
- {
- StColorPenState theState;
- Rect frame, tempRect;
- long theValue = (mRadioBehavior ? mValue : 0);
- Boolean down = inPushed || (theValue != 0);
- Boolean hasColor = ::PaneInColor(this);
- Boolean disabled = (mEnabled != triState_On); // <06/27/96 ca>
-
- theState.Normalize();
- CalcLocalFrameRect(frame);
-
- tempRect = frame;
- ::InsetRect(&tempRect, 1, 1);
- if (hasColor)
- {
- ApplyForeAndBackColors();
- if (down)
- ::RGBBackColor(&gAGAColorArray[4]);
- }
- EraseRect(&tempRect);
-
- // Draw the frame;
- if (disabled)
- {
- if (hasColor)
- ::RGBForeColor(&gAGAColorArray[7]);
- else
- ::PenPat(&qd.gray);
- }
- ::MoveTo(frame.left + 2, frame.top);
- ::LineTo(frame.right - 3, frame.top);
- ::LineTo(frame.right - 1, frame.top + 2);
- ::LineTo(frame.right - 1, frame.bottom - 3);
- ::LineTo(frame.right - 3, frame.bottom - 1);
- ::LineTo(frame.left + 2, frame.bottom - 1);
- ::LineTo(frame.left, frame.bottom - 3);
- ::LineTo(frame.left, frame.top + 2);
- ::LineTo(frame.left + 2, frame.top);
- if (disabled && !hasColor)
- ::PenNormal();
-
- // Draw the four corners around
- if (hasColor)
- {
- short pattern = (disabled ? 2 : (down ? 1 : 0));
- const RGBColor *col = gAGAColorArray;
- for (int i = 0; i < 4; i++)
- for (int j = 0; j < 4; j++)
- {
- if (mCorners[pattern][0][i][j] != -1)
- ::SetCPixel(frame.left + j, frame.top + i, &col[mCorners[pattern][0][i][j]]);
- if (mCorners[pattern][1][i][j] != -1)
- ::SetCPixel(frame.right - 4 + j, frame.top + i, &col[mCorners[pattern][1][i][j]]);
- if (mCorners[pattern][2][i][j] != -1)
- ::SetCPixel(frame.left + j, frame.bottom - 4 + i, &col[mCorners[pattern][2][i][j]]);
- if (mCorners[pattern][3][i][j] != -1)
- ::SetCPixel(frame.right - 4 + j, frame.bottom - 4 + i, &col[mCorners[pattern][3][i][j]]);
- }
-
- if (down)
- ::RGBForeColor(&gAGAColorArray[8]);
- else
- ::RGBForeColor(&gAGAColorArray[2]);
- ::MoveTo(frame.left + 1, frame.top + 4);
- ::LineTo(frame.left + 1, frame.bottom - 5);
- ::MoveTo(frame.left + 4, frame.top + 1);
- ::LineTo(frame.right - 5, frame.top + 1);
-
- if (!down)
- {
- if (disabled)
- ::RGBForeColor(&gAGAColorArray[1]);
- else
- ::ForeColor(whiteColor);
- ::MoveTo(frame.left + 2, frame.bottom - 5);
- ::LineTo(frame.left + 2, frame.top + 2);
- ::LineTo(frame.right - 5, frame.top + 2);
-
- if (disabled)
- ::RGBForeColor(&gAGAColorArray[5]);
- else
- ::RGBForeColor(&gAGAColorArray[8]);
- ::MoveTo(frame.left + 4, frame.bottom - 2);
- ::LineTo(frame.right - 5, frame.bottom - 2);
- ::MoveTo(frame.right - 2, frame.bottom - 5);
- ::LineTo(frame.right - 2, frame.top + 4);
-
- if (disabled)
- ::RGBForeColor(&gAGAColorArray[4]);
- else
- ::RGBForeColor(&gAGAColorArray[5]);
- ::MoveTo(frame.left + 4, frame.bottom - 3);
- ::LineTo(frame.right - 5, frame.bottom - 3);
- ::MoveTo(frame.right - 3, frame.bottom - 5);
- ::LineTo(frame.right - 3, frame.top + 4);
- }
- }
- }
-
- void LAGAPushButton::DrawText (Boolean inPushed)
-
- {
- StTextState origTextState;
- StColorPenState origCPenState;
- Boolean hasColor = ::PaneInColor(this);
-
- Rect theFrame;
- CalcLocalFrameRect(theFrame);
- ::InsetRect(&theFrame, 3, 3);
- //StClipRgnState theClip(theFrame); // There is no need to clip here, since in UTextDrawing::DrawWithJustification
- // clipping is already handled
-
- Int16 theJust = UTextTraits::SetPortTextTraits(mTextTraitsID); // <05/15/96 ca>
- short theWidth = ::StringWidth(mTitle);
- {
- // <04/??/96 jhs> Italic adjustment <05/15/96 ca>
- if (mStyleCache == -1)
- {
- // The style is not known, let's get it
- TextTraitsH theTraitH = UTextTraits::LoadTextTraits(mTextTraitsID);
- mStyleCache = (theTraitH ? (*theTraitH)->style : 0);
- }
- Boolean isItalic = mStyleCache & (1 << italicBit);
- if (isItalic)
- theWidth += 5;
- }
- // Center horizontally
- if (theWidth < (theFrame.right - theFrame.left))
- {
- theFrame.left = (((theFrame.right - theFrame.left) - theWidth) / 2) + theFrame.left;
- theFrame.right = theFrame.left + theWidth + 1;
- }
-
- // Center vertically
- FontInfo fontInfo;
- ::GetFontInfo(&fontInfo);
- short lineHeight = fontInfo.ascent + fontInfo.descent;
- if (lineHeight < (theFrame.bottom - theFrame.top))
- theFrame.top = (((theFrame.bottom - theFrame.top) - lineHeight) / 2) + theFrame.top;
- theFrame.top -= 2;
- {
- // <04/??/96 jhs> klutzes in:
- while (lineHeight > theFrame.bottom - theFrame.top)
- {
- ++theFrame.bottom;
- --theFrame.top;
- }
- }
-
- long theValue = (mRadioBehavior ? mValue : 0);
- if (hasColor)
- {
- if (inPushed || (theValue != 0))
- {
- theFrame.left++;
- theFrame.right++;
- theFrame.top++;
- theFrame.bottom++;
- }
- // Set background color
-
- RGBColor textColor; // Text has its own foreground color
- ::GetForeColor(&textColor);
-
- ApplyForeAndBackColors();
- if (mEnabled == triState_On) // <06/27/96 ca>
- {
- ::RGBForeColor(&textColor);
- if (inPushed)
- ::RGBBackColor(&gAGAColorArray[4]);
- }
- else
- ::RGBForeColor(&gAGAColorArray[7]);
- }
-
- UTextDrawing::DrawWithJustification((Ptr)&mTitle[1], mTitle[0], theFrame, theJust);
-
- if (!hasColor && (inPushed || (theValue != 0)))
- {
- CalcLocalFrameRect(theFrame);
- ::InsetRect(&theFrame, 1, 1);
- ::InvertRect(&theFrame);
- }
- }
-
-