home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 February / macformat-047.iso / Shareware Plus / Developers / The Gray Council 1.2.1 / source / Core / GrayCouncil.cpp next >
Encoding:
Text File  |  1996-11-07  |  311.1 KB  |  11,275 lines  |  [TEXT/CWIE]

  1. //
  2. // The Gray Council
  3. // Copyright ©1996 by Trygve Isaacson. All Rights Reserved.
  4. //
  5. // Before using any of the Gray Council source code, read and
  6. // follow the licensing info in the accompanying documentation
  7. // or contact:
  8. //   <trygve@bombaydigital.com>
  9. //   <http://www.bombaydigital.com>
  10. //
  11. // Also check the web site above to make sure you have the latest version!
  12. //
  13. // The Gray Council provides a set of standard C++ classes that implement
  14. // the standard Apple Grayscale Appearance. The core classes do not
  15. // require any other code such as a particular class framework.
  16. // There are separate files provided that plug The Gray Council core
  17. // into class frameworks.
  18. //
  19. // Classes defined below:
  20. //    AGAObject -- abstract base class for most others
  21. //    MExclusiveObject -- mixin class for mutual exclusivity (e.g. radio)
  22. //    AGATextStyle -- text style attributes container
  23. //    AGADrawingEnvironment -- stack-based save/restore class for drawing attributes
  24. //    AGAStaticText -- simple string object
  25. //    AGAPushButton -- push button with auto default outline capability
  26. //    AGACheckBox -- check box with mixed state capability
  27. //    AGAOffscreenImage -- class for storing and drawing an offscreen pixmap
  28. //    AGARadioButton -- radio button with mixed state capability
  29. //    MIconButtonObject -- mixin class for icon buttons
  30. //    AGAIconPushButton -- AGAPushButton subclass for icon push buttons
  31. //    AGAIconCheckBox -- AGACheckBox subclass for on/off icon buttons
  32. //    AGAIconRadioButton -- AGARadioButton subclass for mutually exclusive
  33. //        on/off icon buttons
  34. //    AGATrackingIndicator -- abstract superclass for scroll bar and slider
  35. //    AGAScrollBar -- scroll bar with 32-bit values, live tracking, and
  36. //        proportional indicator capabilities
  37. //    AGASlider -- slider with pointy or rectangular indicator, optional
  38. //        labels, live tracking, proportional indicator capabilities
  39. //    AGAPopupMenu -- popup menu with optional title
  40. //    AGACustomPopupMenuSizer -- stack-based class to make PopupMenuSelect use custom font/size
  41. //    AGALittleArrows -- little up/down arrows with notification
  42. //    AGADisclosureTriangle -- disclosure triangle with animation
  43. //    AGAProgressIndicator -- determinate or indeterminate progress gauge
  44. //        with moving determinate origin capability
  45. //    AGASeparator -- separator line with automatic directionality
  46. //    AGAGroupBox -- primary or secondary group box with optional title or
  47. //        room for external title or control
  48. //    AGATabPanel -- folder tabs for switching panels
  49. //    GDIterator -- stack-based class for multi-screen drawing
  50. //
  51.  
  52. #include "GrayCouncil.h"
  53.  
  54. #include <limits.h>
  55. #include <LowMem.h>
  56.  
  57. #pragma segment GrayCouncilCore1
  58.  
  59. //
  60. // Initialization -----------------------------------------------------
  61. //
  62. // Must be called by client application after initializing the toolbox,
  63. // and before any other Gray Council calls are made.
  64. // The framework-specific initialization functions call this automatically.
  65. //
  66.  
  67. OSErr InitGrayCouncil()
  68.     {
  69.     OSErr    result;
  70.     SInt32    gestaltResponse;
  71.  
  72.     //
  73.     // Initialize some basic globals.
  74.     //
  75.     
  76.     // Default flags. Only live scrolling is on by default.
  77.     gAGADefaults = kAGALiveScrolling;
  78.     
  79.     // Set global Color QuickDraw flag.
  80.     result = ::Gestalt(gestaltQuickdrawVersion, &gestaltResponse);
  81.     gAGAHasColorQD = (result == noErr) && (gestaltResponse != gestaltOriginalQD);
  82.     
  83.     // Allocate the group container.
  84.     gGroupsContainer = new AGAGroupsContainer;
  85.  
  86.     // Try to allocate the offscreen images.
  87.  
  88.     result = AGARadioButton::AllocateRadioImages();
  89.     
  90.     if (result == noErr)
  91.         result = AGAProgressIndicator::AllocateProgressImages();
  92.     
  93.     if (result == noErr)
  94.         result = AGATabPanel::AllocateTabImages();
  95.     
  96.     return result;
  97.     }
  98.  
  99. //
  100. // Static routines used only inside this file -------------------------
  101. //
  102.  
  103. static SInt16 MinSInt16(SInt16 a, SInt16 b) { return (a < b) ? a : b; }
  104. static SInt16 MaxSInt16(SInt16 a, SInt16 b) { return (a > b) ? a : b; }
  105. static SInt32 MinSInt32(SInt32 a, SInt32 b) { return (a < b) ? a : b; }
  106. static SInt32 MaxSInt32(SInt32 a, SInt32 b) { return (a > b) ? a : b; }
  107.  
  108. static void DelayFuture(SInt32 delayTicks)
  109.     {
  110.     // Delay for the specified number of ticks.
  111.  
  112.     SInt32    dontCare;
  113.     ::Delay(delayTicks, &dontCare);
  114.     }
  115.  
  116. static void DelayFutureWhileStillDown(SInt32 delayTicks)
  117.     {
  118.     // Delay for the specified number of ticks, but bail
  119.     // out if the user lets go of the mouse first.
  120.  
  121.     SInt32    future = delayTicks + ::TickCount();
  122.  
  123.     while (::StillDown() && (::TickCount() < future))
  124.         {};
  125.     }
  126.  
  127. static SInt32 RuntimeJustify(SInt32 userJust)
  128.     {
  129.     // Return the actual runtime justification value for
  130.     // the supplied value. The caller can use the result
  131.     // alone to know determine drawing direction.
  132.     // If the supplied value specifies default, we need
  133.     // to check the current system script direction.
  134.     // Otherwise, whatever was specified is OK as is.
  135.  
  136.     if (userJust == teFlushDefault)
  137.         {
  138.         if (::GetSysDirection() == 0)
  139.             return teFlushLeft;
  140.         else
  141.             return teFlushRight;
  142.         }
  143.     else
  144.         return userJust;
  145.     }
  146.  
  147. //
  148. // AGATextStyle --------------------------------------------------------
  149. //
  150.  
  151. AGATextStyle::AGATextStyle()
  152.     {
  153.     // Default constructor, use system font.
  154.  
  155.     mFontNum = systemFont;    // typically Chicago
  156.     mFontSize = 0;            // application size, typically 12-point
  157.     mFontStyle = normal;
  158.     }
  159.  
  160. AGATextStyle::AGATextStyle(SInt16 fontNum, SInt16 fontSize, Style fontStyle)
  161.     {
  162.     // Construct with direct parameters.
  163.  
  164.     mFontNum = fontNum;
  165.     mFontSize = fontSize;
  166.     mFontStyle = fontStyle;
  167.     }
  168.  
  169. AGATextStyle::AGATextStyle(StringPtr fontName, SInt16 fontSize, Style fontStyle)
  170.     {
  171.     // Construct by converting font name to font number.
  172.  
  173.     ::GetFNum(fontName, &mFontNum);
  174.     mFontSize = fontSize;
  175.     mFontStyle = fontStyle;
  176.     }
  177.  
  178. AGATextStyle::AGATextStyle(const TextStyle& textStyle)
  179.     {
  180.     // Construct by copying another text style.
  181.  
  182.     mFontNum = textStyle.tsFont;
  183.     mFontSize = textStyle.tsSize;
  184.     mFontStyle = textStyle.tsFace;
  185.     }
  186.  
  187. void AGATextStyle::PrepareForDrawing() const
  188.     {
  189.     // Set the text pen for subsequent drawing.
  190.  
  191.     ::TextFont(mFontNum);
  192.     ::TextSize(mFontSize);
  193.     ::TextFace(mFontStyle);
  194.     }
  195.  
  196. //
  197. // AGADrawingEnvironment ---------------------------------------------------------------
  198. //
  199.  
  200. AGADrawingEnvironment::AGADrawingEnvironment()
  201.     {
  202.     // Save current environment, then cleanse the pen.
  203.  
  204.     this->SaveEnvironment();
  205.     this->Cleanse();
  206.     }
  207.  
  208. AGADrawingEnvironment::~AGADrawingEnvironment()
  209.     {
  210.     this->RestoreEnvironment();
  211.     }
  212.  
  213. void AGADrawingEnvironment::SaveEnvironment()
  214.     {
  215.     // Save all text/pen attributes that we will change.
  216.  
  217.     GrafPtr    currentPort;
  218.  
  219.     ::GetPort(¤tPort);
  220.  
  221.     ::GetPenState(&mSavedPenState);
  222.     ::GetForeColor(&mSavedForeColor);
  223.     ::GetBackColor(&mSavedBackColor);
  224.     mSavedFontNum = currentPort->txFont;
  225.     mSavedFontSize = currentPort->txSize;
  226.     mSavedFontStyle = currentPort->txFace;
  227.     }
  228.  
  229. void AGADrawingEnvironment::RestoreEnvironment()
  230.     {
  231.     // Restore text/pen attributes that we saved.
  232.  
  233.     ::SetPenState(&mSavedPenState);
  234.     ::RGBForeColor(&mSavedForeColor);
  235.     ::RGBBackColor(&mSavedBackColor);
  236.     ::TextFont(mSavedFontNum);
  237.     ::TextSize(mSavedFontSize);
  238.     ::TextFace(mSavedFontStyle);
  239.     }
  240.  
  241. void AGADrawingEnvironment::Cleanse()
  242.     {
  243.     // Put the pen into a nice clean state.
  244.  
  245.     ::PenNormal();                            // pen size 1,1, solid black pattern, srcOr
  246.     ::RGBForeColor(&gAGARamp[rB]);            // black fore color
  247.     ::RGBBackColor(&gAGARamp[rW]);            // white back color
  248.     gAGAStdSystemStyle.PrepareForDrawing();    // system font 12 point
  249.     }
  250.  
  251. //
  252. // AGAObject ---------------------------------------------------------------
  253. //
  254.  
  255. AGAObject::AGAObject(Rect* bounds)
  256.     {
  257.     // Construct enabled.
  258.  
  259.     mBounds = *bounds;
  260.     mEnabled = true;
  261.     mEnabledBackgroundColor = gAGARamp[r2];
  262.     mDisabledBackgroundColor = gAGARamp[r2];
  263.     }
  264.  
  265. AGAObject::~AGAObject()
  266.     {
  267.     }
  268.  
  269. void AGAObject::GetObjectBounds(Rect* bounds)
  270.     {
  271.     // Return current bounds.
  272.  
  273.     *bounds = mBounds;
  274.     }
  275.  
  276. void AGAObject::SetObjectBounds(Rect* bounds, Boolean redraw)
  277.     {
  278.     // Change bounds, redraw if specified.
  279.  
  280.     mBounds = *bounds;
  281.     
  282.     if (redraw)
  283.         this->DrawObject();
  284.     }
  285.  
  286. void AGAObject::DrawObject()
  287.     {
  288.     // Override to draw particular type of object.
  289.     }
  290.  
  291. Boolean AGAObject::ContainsMouse(Point mouseLocation)
  292.     {
  293.     // Return true if mouse will hit object.
  294.  
  295.     return ::PtInRect(mouseLocation, &mBounds);
  296.     }
  297.  
  298. Boolean AGAObject::TrackMouse(Point /*mouseLocation*/)
  299.     {
  300.     if (! mEnabled)
  301.         return false;
  302.  
  303.     // Process mouse tracking, return true if tracking
  304.     // eventually "did something". Return false if
  305.     // tracking had no ultimate effect, e.g. mouse
  306.     // up outside a push button.
  307.  
  308.     Boolean    finishedIn = false;
  309.     Boolean    wasIn = false;
  310.     Boolean    isIn;
  311.     Boolean    isButtonDown = true;    // ensure at least one time through
  312.     Point    newMouseLocation;
  313.     
  314.     while (isButtonDown)
  315.         {
  316.         ::GetMouse(&newMouseLocation);    // gives local coordinates
  317.         
  318.         isIn = this->HitTest(newMouseLocation);
  319.         
  320.         if (isIn != wasIn)
  321.             this->SetTrackingState(isIn);
  322.         
  323.         wasIn = isIn;
  324.  
  325.         isButtonDown = ::StillDown();
  326.         }
  327.     
  328.     if (isIn)    // if finished IN, restore normal appearance
  329.         this->SetTrackingState(kTrackingOut);
  330.     
  331.     return isIn;
  332.     }
  333.  
  334. void AGAObject::SetEnable(Boolean isEnabled, Boolean redraw)
  335.     {
  336.     // Set object enable state, redraw if specified.
  337.  
  338.     mEnabled = isEnabled;
  339.     
  340.     if (redraw)
  341.         this->DrawObject();
  342.     }
  343.  
  344. void AGAObject::SetBackgroundColors(RGBColor* enabledColor, RGBColor* disabledColor)
  345.     {
  346.     // Set colors to be used when erasing background.
  347.     // Most views don't need this. Default is AGA ramp r2.
  348.     // AGAStaticText and AGADisclosureTriangle need to
  349.     // erase their background, so if your background is
  350.     // not r2 (white, for example), call this to set it.
  351.     // Also, objects contained in tab panel views need
  352.     // r1 when enabled, and r2 when disabled, so that's
  353.     // an even wackier case; the adapter classes handle
  354.     // it for you.
  355.  
  356.     mEnabledBackgroundColor = *enabledColor;
  357.     mDisabledBackgroundColor = *disabledColor;
  358.     }
  359.  
  360. SInt32 AGAObject::GetValue()
  361.     {
  362.     return 0;    // overriden for objects that have a useful value
  363.     }
  364.  
  365. void AGAObject::SetValue(SInt32 /*newValue*/, Boolean /*redraw*/)
  366.     {
  367.     // overriden for objects that have a useful value
  368.     }
  369.  
  370. Boolean AGAObject::HitTest(Point mouseLocation)
  371.     {
  372.     // Return true if mouse is inside tracking area of
  373.     // object. This function may be overridden for
  374.     // classes that do not have simple rectangular
  375.     // boundary hit testing.
  376.  
  377.     return ::PtInRect(mouseLocation, &mBounds);
  378.     }
  379.  
  380. void AGAObject::SetTrackingState(Boolean /*isIn*/)
  381.     {
  382.     // Override to draw the object in the appropriate
  383.     // state during tracking. If isIn is true, it means
  384.     // that the mouse is now in the positive hit test
  385.     // area of the object.
  386.     }
  387.  
  388. void AGAObject::ApplyBackgroundColor()
  389.     {
  390.     // Use the proper background color and apply it as
  391.     // the current foreground color suitable for a
  392.     // subsequent PaintRect or similar call.
  393.  
  394.     if (mEnabled)
  395.         ::RGBForeColor(&mEnabledBackgroundColor);
  396.     else
  397.         ::RGBForeColor(&mDisabledBackgroundColor);
  398.     }
  399.  
  400. //
  401. // AGAStaticText ---------------------------------------------------------------
  402. //
  403. // This class draws a static text label.
  404. //
  405.  
  406. AGAStaticText::AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification)
  407. : AGAObject(bounds)
  408.     {
  409.     // Construct with empty string.
  410.  
  411.     mJustification = justification;
  412.     mTitle[0];
  413.     mTextStyle = textStyle;
  414.     }
  415.  
  416. AGAStaticText::AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification, StringPtr title)
  417. : AGAObject(bounds)
  418.     {
  419.     // Construct with supplied string.
  420.  
  421.     mJustification = justification;
  422.     AGA_PLstrcpy(mTitle, title);
  423.     mTextStyle = textStyle;
  424.     }
  425.  
  426. AGAStaticText::AGAStaticText(Rect* bounds, const AGATextStyle& textStyle, SInt32 justification, SInt16 stringListResourceID, SInt16 stringIndex)
  427. : AGAObject(bounds)
  428.     {
  429.     // Construct by getting string from specified resource.
  430.  
  431.     mJustification = justification;
  432.     ::GetIndString(mTitle, stringListResourceID, stringIndex);
  433.     mTextStyle = textStyle;
  434.     }
  435.  
  436. AGAStaticText::~AGAStaticText()
  437.     {
  438.     }
  439.  
  440. void AGAStaticText::DrawObject()
  441.     {
  442.     AGADrawingEnvironment    env;
  443.  
  444.     // Paint over possible obsolete text, draw current text.
  445.  
  446.     GDIterator    iter;
  447.     Boolean        deep;
  448.  
  449.     while (iter.More(deep))
  450.         {
  451.         if (deep)
  452.             this->ApplyBackgroundColor();
  453.         else
  454.             ::RGBForeColor(&gAGARamp[rW]);
  455.  
  456.         ::PaintRect(&mBounds);
  457.  
  458.         RGBColor    teBackgroundColor;
  459.         ::GetForeColor(&teBackgroundColor);    // fg color right now is what the TE must leave in the bg
  460.  
  461.         AGATextBox(&mTitle[1], mTitle[0], &mBounds, mJustification, mEnabled ? kNormalOutput : kDisabledOutput, deep, mTextStyle, &teBackgroundColor);
  462.         }
  463.     }
  464.  
  465. void AGAStaticText::SetTitle(StringPtr title, Boolean redraw)
  466.     {
  467.     // Change text, redraw if specified.
  468.  
  469.     AGA_PLstrcpy(mTitle, title);
  470.     
  471.     if (redraw)
  472.         this->DrawObject();
  473.     }
  474.  
  475. //
  476. // AGAPushButton ---------------------------------------------------------------
  477. //
  478. // This class implements a standard text pushbutton object.
  479. //
  480.  
  481. AGAPushButton::AGAPushButton(Rect* bounds, const AGATextStyle& textStyle)
  482. : AGAObject(bounds)
  483.     {
  484.     // Construct with initial empty button title.
  485.  
  486.     mIsDefault = false;
  487.     mFrameInside = true;
  488.     mTitle[0];
  489.     mTextStyle = textStyle;
  490.     }
  491.  
  492. AGAPushButton::AGAPushButton(Rect* bounds, const AGATextStyle& textStyle, StringPtr title)
  493. : AGAObject(bounds)
  494.     {
  495.     // Construct with specified button title.
  496.  
  497.     mIsDefault = false;
  498.     mFrameInside = true;
  499.     AGA_PLstrcpy(mTitle, title);
  500.     mTextStyle = textStyle;
  501.     }
  502.  
  503. AGAPushButton::AGAPushButton(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex)
  504. : AGAObject(bounds)
  505.     {
  506.     // Construct by getting button title from specified resource.
  507.  
  508.     mIsDefault = false;
  509.     mFrameInside = true;
  510.     ::GetIndString(mTitle, stringListResourceID, stringIndex);
  511.     mTextStyle = textStyle;
  512.     }
  513.  
  514. AGAPushButton::~AGAPushButton()
  515.     {
  516.     }
  517.  
  518. void AGAPushButton::DrawObject()
  519.     {
  520.     // Draw button in normal unpressed state.
  521.  
  522.     this->DrawButton(kNotPressed);
  523.     }
  524.  
  525. void AGAPushButton::SetTitle(StringPtr title, Boolean redraw)
  526.     {
  527.     // Change button title, redraw if specified.
  528.  
  529.     AGA_PLstrcpy(mTitle, title);
  530.     
  531.     if (redraw)
  532.         this->DrawObject();
  533.     }
  534.  
  535. void AGAPushButton::SetDefault(Boolean isDefault, Boolean frameInside)
  536.     {
  537.     // Set default state. If mIsDefault is true, the button will
  538.     // be drawn with a default button outline. If mFrameInside
  539.     // is true, the outline will be inside mBounds and the button
  540.     // will be drawn inset from there; if mFrameInside is false,
  541.     // the outline will be outside mBounds and the button will
  542.     // be drawn at mBounds.
  543.  
  544.     mIsDefault = isDefault;
  545.     mFrameInside = frameInside;
  546.     }
  547.  
  548. Boolean AGAPushButton::IsDefault()
  549.     {
  550.     // Return true if this button has a default outline.
  551.  
  552.     return mIsDefault;
  553.     }
  554.  
  555. void AGAPushButton::DrawButton(Boolean pressed)
  556.     {
  557.     AGADrawingEnvironment    env;
  558.  
  559.     // Draw the button in the appropriate state.
  560.  
  561.     GDIterator    iter;
  562.     Boolean        deep;
  563.  
  564.     while (iter.More(deep))
  565.         {
  566.         if (! mEnabled)
  567.             this->DrawButtonDisabled(deep);
  568.         else if (pressed)
  569.             this->DrawButtonPressed(deep);
  570.         else
  571.             this->DrawButtonNormal(deep);
  572.         }
  573.     }
  574.  
  575. Boolean AGAPushButton::HitTest(Point mouseLocation)
  576.     {
  577.     // Return true if the mouse is in the button.
  578.     // Account for case where default button outline
  579.     // is inside mBounds.
  580.  
  581.     Rect    r = mBounds;
  582.     
  583.     if (mIsDefault && mFrameInside)
  584.         ::InsetRect(&r, 3, 3);
  585.  
  586.     return ::PtInRect(mouseLocation, &r);
  587.     }
  588.  
  589. void AGAPushButton::SetTrackingState(Boolean isIn)
  590.     {
  591.     // Draw the button pressed or unpressed as specified.
  592.  
  593.     this->DrawButton(isIn);
  594.     }
  595.  
  596. void AGAPushButton::DrawButtonNormal(Boolean deep)
  597.     {
  598.     // Draw the button in enabled/unpressed state.
  599.  
  600.     Rect    r = mBounds;
  601.     
  602.     if (mIsDefault && mFrameInside)
  603.         ::InsetRect(&r, 3, 3);
  604.     
  605.     ::PenSize(1, 1);
  606.  
  607.     if (deep)
  608.         {
  609.         // Fill the interior.
  610.         ::InsetRect(&r, 1, 1);
  611.         ::RGBForeColor(&gAGARamp[r2]);
  612.         ::PaintRect(&r);
  613.         ::InsetRect(&r, -1, -1);
  614.         
  615.         // Draw the frame.
  616.         ::MoveTo(r.left + 1, r.top + 1);
  617.         ::RGBForeColor(&gAGARamp[rB]);
  618.         ::Line(0, 0);
  619.         ::Move(1, -1);
  620.         ::RGBForeColor(&gAGARamp[r12]);
  621.         ::Line(0, 0);
  622.         ::Move(1, 0);
  623.         ::RGBForeColor(&gAGARamp[rB]);
  624.         ::Line(r.right - r.left - 6, 0);
  625.         ::RGBForeColor(&gAGARamp[r12]);
  626.         ::Line(0, 0);
  627.         ::Move(1, 1);
  628.         ::RGBForeColor(&gAGARamp[rB]);
  629.         ::Line(0, 0);
  630.         ::Move(1, 1);
  631.         ::RGBForeColor(&gAGARamp[r12]);
  632.         ::Line(0, 0);
  633.         ::Move(0, 1);
  634.         ::RGBForeColor(&gAGARamp[rB]);
  635.         ::Line(0, r.bottom - r.top - 6);
  636.         ::RGBForeColor(&gAGARamp[r12]);
  637.         ::Line(0, 0);
  638.         ::Move(-1, 1);
  639.         ::RGBForeColor(&gAGARamp[rB]);
  640.         ::Line(0, 0);
  641.         ::Move(-1, 1);
  642.         ::RGBForeColor(&gAGARamp[r12]);
  643.         ::Line(0, 0);
  644.         ::Move(-1, 0);
  645.         ::RGBForeColor(&gAGARamp[rB]);
  646.         ::Line(- (r.right - r.left - 6), 0);
  647.         ::RGBForeColor(&gAGARamp[r12]);
  648.         ::Line(0, 0);
  649.         ::Move(-1, -1);
  650.         ::RGBForeColor(&gAGARamp[rB]);
  651.         ::Line(0, 0);
  652.         ::Move(-1, -1);
  653.         ::RGBForeColor(&gAGARamp[r12]);
  654.         ::Line(0, 0);
  655.         ::Move(0, -1);
  656.         ::RGBForeColor(&gAGARamp[rB]);
  657.         ::Line(0, -(r.bottom - r.top - 6));
  658.         ::RGBForeColor(&gAGARamp[r12]);
  659.         ::Line(0, 0);
  660.         
  661.         // Add 1st inner pixels.
  662.         ::MoveTo(r.left + 1, r.top + 2);
  663.         ::RGBForeColor(&gAGARamp[r4]);
  664.         ::Line(0, 0);
  665.         ::Move(1, -1);
  666.         ::Line(0, 0);
  667.         ::Move(r.right - r.left - 5, 0);
  668.         ::Line(0, 0);
  669.         ::Move(1, 1);
  670.         ::RGBForeColor(&gAGARamp[r5]);
  671.         ::Line(0, 0);
  672.         ::Move(0, 1);
  673.         ::RGBForeColor(&gAGARamp[r8]);
  674.         ::Line(0, r.bottom - r.top - 6);
  675.         ::Line(-1, 0);
  676.         ::Line(0, 1);
  677.         ::Line(- (r.right - r.left - 6), 0);
  678.         ::RGBForeColor(&gAGARamp[r4]);
  679.         ::Move(-1, 0);
  680.         ::Line(-1, -1);
  681.  
  682.         // Add 2nd inner pixels.
  683.         ::MoveTo(r.left + 2, r.bottom - 4);
  684.         ::RGBForeColor(&gAGARamp[rW]);
  685.         ::Line(0, -(r.bottom - r.top - 6));
  686.         ::Line(1, 1);
  687.         ::Line(0, -1);
  688.         ::Line(r.right - r.left - 7, 0);
  689.         ::Move(1, 1);
  690.         ::RGBForeColor(&gAGARamp[r5]);
  691.         ::Line(0, r.bottom - r.top - 7);
  692.         ::Line(-1, 0);
  693.         ::Line(0, 1);
  694.         ::Line(- (r.right - r.left - 7), 0);
  695.         }
  696.     else    // 1-bit
  697.         {
  698.         ::RGBForeColor(&gAGARamp[rW]);
  699.         ::PaintRoundRect(&r, 7, 7);
  700.         ::RGBForeColor(&gAGARamp[rB]);
  701.         ::FrameRoundRect(&r, 7, 7);
  702.         }
  703.  
  704.     // Draw the title.
  705.     AGAStringOut(mTitle, &r, truncMiddle, teJustCenter, kNormalOutput, deep, mTextStyle);
  706.     
  707.     // Draw the default button outline.
  708.     this->DrawOutlineNormal(deep);
  709.     }
  710.  
  711. void AGAPushButton::DrawButtonPressed(Boolean deep)
  712.     {
  713.     // Draw the button in enabled/pressed state.
  714.  
  715.     Rect    r = mBounds;
  716.     
  717.     if (mIsDefault && mFrameInside)
  718.         ::InsetRect(&r, 3, 3);
  719.     
  720.     ::PenSize(1, 1);
  721.  
  722.     if (deep)
  723.         {
  724.         // Fill the interior.
  725.         ::InsetRect(&r, 1, 1);
  726.         ::RGBForeColor(&gAGARamp[r9]);
  727.         ::PaintRect(&r);
  728.         ::InsetRect(&r, -1, -1);
  729.         
  730.         // Draw the frame.
  731.         ::MoveTo(r.left + 1, r.top + 1);
  732.         ::RGBForeColor(&gAGARamp[rB]);
  733.         ::Line(0, 0);
  734.         ::Move(1, -1);
  735.         ::RGBForeColor(&gAGARamp[r12]);
  736.         ::Line(0, 0);
  737.         ::Move(1, 0);
  738.         ::RGBForeColor(&gAGARamp[rB]);
  739.         ::Line(r.right - r.left - 6, 0);
  740.         ::RGBForeColor(&gAGARamp[r12]);
  741.         ::Line(0, 0);
  742.         ::Move(1, 1);
  743.         ::RGBForeColor(&gAGARamp[rB]);
  744.         ::Line(0, 0);
  745.         ::Move(1, 1);
  746.         ::RGBForeColor(&gAGARamp[r12]);
  747.         ::Line(0, 0);
  748.         ::Move(0, 1);
  749.         ::RGBForeColor(&gAGARamp[rB]);
  750.         ::Line(0, r.bottom - r.top - 6);
  751.         ::RGBForeColor(&gAGARamp[r12]);
  752.         ::Line(0, 0);
  753.         ::Move(-1, 1);
  754.         ::RGBForeColor(&gAGARamp[rB]);
  755.         ::Line(0, 0);
  756.         ::Move(-1, 1);
  757.         ::RGBForeColor(&gAGARamp[r12]);
  758.         ::Line(0, 0);
  759.         ::Move(-1, 0);
  760.         ::RGBForeColor(&gAGARamp[rB]);
  761.         ::Line(- (r.right - r.left - 6), 0);
  762.         ::RGBForeColor(&gAGARamp[r12]);
  763.         ::Line(0, 0);
  764.         ::Move(-1, -1);
  765.         ::RGBForeColor(&gAGARamp[rB]);
  766.         ::Line(0, 0);
  767.         ::Move(-1, -1);
  768.         ::RGBForeColor(&gAGARamp[r12]);
  769.         ::Line(0, 0);
  770.         ::Move(0, -1);
  771.         ::RGBForeColor(&gAGARamp[rB]);
  772.         ::Line(0, -(r.bottom - r.top - 6));
  773.         ::RGBForeColor(&gAGARamp[r12]);
  774.         ::Line(0, 0);
  775.         
  776.         // Add 1st inner pixels.
  777.         ::MoveTo(r.left + 1, r.bottom - 3);
  778.         ::RGBForeColor(&gAGARamp[r11]);
  779.         ::Line(0, -(r.bottom - r.top - 5));
  780.         ::Line(1, 0);
  781.         ::Line(0, -1);
  782.         ::Line(r.right - r.left - 5, 0);
  783.         ::Move(1, 1);
  784.         ::RGBForeColor(&gAGARamp[r8]);
  785.         ::Line(0, 0);
  786.         ::Move(0, 1);
  787.         ::RGBForeColor(&gAGARamp[r7]);
  788.         ::Line(0, r.bottom - r.top - 6);
  789.         ::Line(-1, 0);
  790.         ::Line(0, 1);
  791.         ::Line(- (r.right - r.left - 5), 0);
  792.         ::RGBForeColor(&gAGARamp[r8]);
  793.         ::Line(0, 0);
  794.  
  795.         // Add 2nd inner pixels.
  796.         ::MoveTo(r.left + 2, r.bottom - 4);
  797.         ::RGBForeColor(&gAGARamp[r10]);
  798.         ::Line(0, -(r.bottom - r.top - 7));
  799.         ::Line(1, 0);
  800.         ::Line(0, -1);
  801.         ::Line(r.right - r.left - 7, 0);
  802.         ::Move(1, 1);
  803.         ::RGBForeColor(&gAGARamp[r8]);
  804.         ::Line(0, r.bottom - r.top - 7);
  805.         ::Line(-1, 0);
  806.         ::Line(0, 1);
  807.         ::Line(- (r.right - r.left - 7), 0);
  808.         }
  809.     else    // 1-bit
  810.         {
  811.         ::RGBForeColor(&gAGARamp[rB]);
  812.         ::PaintRoundRect(&r, 7, 7);
  813.         }
  814.  
  815.     // Draw the title.
  816.     AGAStringOut(mTitle, &r, truncMiddle, teJustCenter, kInverseOutput, deep, mTextStyle);
  817.     
  818.     // Draw the default button outline.
  819.     this->DrawOutlineNormal(deep);
  820.     }
  821.  
  822. void AGAPushButton::DrawButtonDisabled(Boolean deep)
  823.     {
  824.     // Draw the button in disabled/unpressed state.
  825.  
  826.     Rect    r = mBounds;
  827.     
  828.     if (mIsDefault && mFrameInside)
  829.         ::InsetRect(&r, 3, 3);
  830.     
  831.     ::PenSize(1, 1);
  832.  
  833.     if (deep)
  834.         {
  835.         // Fill the interior.
  836.         ::InsetRect(&r, 1, 1);
  837.         ::RGBForeColor(&gAGARamp[r2]);
  838.         ::PaintRect(&r);
  839.         ::InsetRect(&r, -1, -1);
  840.         
  841.         // Draw the frame.
  842.         ::MoveTo(r.left + 1, r.top + 1);
  843.         ::RGBForeColor(&gAGARamp[r7]);
  844.         ::Line(0, 0);
  845.         ::Move(1, -1);
  846.         ::Line(0, 0);
  847.         ::Move(1, 0);
  848.         ::Line(r.right - r.left - 6, 0);
  849.         ::Line(0, 0);
  850.         ::Move(1, 1);
  851.         ::Line(0, 0);
  852.         ::Move(1, 1);
  853.         ::Line(0, 0);
  854.         ::Move(0, 1);
  855.         ::Line(0, r.bottom - r.top - 6);
  856.         ::Line(0, 0);
  857.         ::Move(-1, 1);
  858.         ::Line(0, 0);
  859.         ::Move(-1, 1);
  860.         ::Line(0, 0);
  861.         ::Move(-1, 0);
  862.         ::Line(- (r.right - r.left - 6), 0);
  863.         ::Line(0, 0);
  864.         ::Move(-1, -1);
  865.         ::Line(0, 0);
  866.         ::Move(-1, -1);
  867.         ::Line(0, 0);
  868.         ::Move(0, -1);
  869.         ::Line(0, -(r.bottom - r.top - 6));
  870.         ::Line(0, 0);
  871.         }
  872.     else    // 1-bit
  873.         {
  874.         ::RGBForeColor(&gAGARamp[rW]);
  875.         ::PaintRoundRect(&r, 7, 7);
  876.         ::RGBForeColor(&gAGARamp[rB]);
  877.         ::FrameRoundRect(&r, 7, 7);
  878.         }
  879.  
  880.     // Draw the title.
  881.     AGAStringOut(mTitle, &r, truncMiddle, teJustCenter, kDisabledOutput, deep, mTextStyle);
  882.     
  883.     // Draw the default button outline.
  884.     this->DrawOutlineDisabled(deep);
  885.     
  886.     if (! deep)
  887.         {
  888.         if (mIsDefault)
  889.             ::InsetRect(&r, -3, -3);
  890.  
  891.         ::RGBForeColor(&gAGARamp[rB]);
  892.         ::PenPat(&qd.gray);
  893.         ::PenMode(patBic);
  894.         ::PaintRect(&r);
  895.  
  896.         ::PenNormal();
  897.         }
  898.     }
  899.  
  900. void AGAPushButton::DrawOutlineNormal(Boolean deep)
  901.     {
  902.     // Draw the default button outline in normal
  903.     // state if the button has one. It may be either
  904.     // inside or outside mBounds.
  905.     
  906.     // If we are drawing the outline outside the normal
  907.     // bounds, we should force the clipping to include
  908.     // that outside area, because the framework or whoever
  909.     // may have reduced clipping to our bounds.
  910.  
  911.     if (! mIsDefault)
  912.         return;
  913.  
  914.     Rect    r = mBounds;
  915.     
  916.     if (! mFrameInside)
  917.         ::InsetRect(&r, -3, -3);
  918.  
  919.     if (deep)
  920.         {
  921.         // Draw the frame.
  922.         ::MoveTo(r.left + 1, r.top + 2);
  923.         ::RGBForeColor(&gAGARamp[rB]);
  924.         ::Line(1, -1);
  925.         ::Move(1, -1);
  926.         ::RGBForeColor(&gAGARamp[r12]);
  927.         ::Line(0, 0);
  928.         ::Move(1, 0);
  929.         ::RGBForeColor(&gAGARamp[rB]);
  930.         ::Line(r.right - r.left - 8, 0);
  931.         ::RGBForeColor(&gAGARamp[r12]);
  932.         ::Line(0, 0);
  933.         ::Move(1, 1);
  934.         ::RGBForeColor(&gAGARamp[rB]);
  935.         ::Line(1, 1);
  936.         ::Move(1, 1);
  937.         ::RGBForeColor(&gAGARamp[r12]);
  938.         ::Line(0, 0);
  939.         ::Move(0, 1);
  940.         ::RGBForeColor(&gAGARamp[rB]);
  941.         ::Line(0, r.bottom - r.top - 8);
  942.         ::RGBForeColor(&gAGARamp[r12]);
  943.         ::Line(0, 0);
  944.         ::Move(-1, 1);
  945.         ::RGBForeColor(&gAGARamp[rB]);
  946.         ::Line(-1, 1);
  947.         ::Move(-1, 1);
  948.         ::RGBForeColor(&gAGARamp[r12]);
  949.         ::Line(0, 0);
  950.         ::Move(-1, 0);
  951.         ::RGBForeColor(&gAGARamp[rB]);
  952.         ::Line(- (r.right - r.left - 8), 0);
  953.         ::RGBForeColor(&gAGARamp[r12]);
  954.         ::Line(0, 0);
  955.         ::Move(-1, -1);
  956.         ::RGBForeColor(&gAGARamp[rB]);
  957.         ::Line(-1, -1);
  958.         ::Move(-1, -1);
  959.         ::RGBForeColor(&gAGARamp[r12]);
  960.         ::Line(0, 0);
  961.         ::Move(0, -1);
  962.         ::RGBForeColor(&gAGARamp[rB]);
  963.         ::Line(0, -(r.bottom - r.top - 8));
  964.         ::RGBForeColor(&gAGARamp[r12]);
  965.         ::Line(0, 0);
  966.         
  967.         // Draw the interior.
  968.         ::MoveTo(r.left + 1, r.bottom - 4);
  969.         ::RGBForeColor(&gAGARamp[r2]);
  970.         ::Line(0, -(r.bottom - r.top - 7));
  971.         ::Line(1, 0);
  972.         ::Line(0, -1);
  973.         ::Line(1, 0);
  974.         ::Line(0, -1);
  975.         ::Line(r.right - r.left - 8, 0);
  976.         ::Move(1, 0);
  977.         ::RGBForeColor(&gAGARamp[r3]);
  978.         ::Line(0, 0);
  979.         ::Move(1, 1);
  980.         ::RGBForeColor(&gAGARamp[r4]);
  981.         ::Line(0, 0);
  982.         ::Move(1, 1);
  983.         ::RGBForeColor(&gAGARamp[r7]);
  984.         ::Line(0, 1);
  985.         ::RGBForeColor(&gAGARamp[r8]);
  986.         ::Line(0, r.bottom - r.top - 8);
  987.         ::Line(-2, 2);
  988.         ::Line(-(r.right - r.left - 8), 0);
  989.         ::Move(-1, 0);
  990.         ::RGBForeColor(&gAGARamp[r7]);
  991.         ::Line(0, 0);
  992.         ::Move(-1, -1);
  993.         ::RGBForeColor(&gAGARamp[r4]);
  994.         ::Line(0, 0);
  995.         ::Move(-1, -1);
  996.         ::RGBForeColor(&gAGARamp[r3]);
  997.         ::Line(0, 0);
  998.         ::Move(1, 0);
  999.         ::RGBForeColor(&gAGARamp[r5]);
  1000.         ::Line(0, -(r.bottom - r.top - 8));
  1001.         ::Line(2, -2);
  1002.         ::Line(r.right - r.left - 8, 0);
  1003.         ::Line(0, 1);
  1004.         ::Line(1, 0);
  1005.         ::Line(0, r.bottom - r.top - 8);
  1006.         ::Line(-2, 2);
  1007.         ::Line(-(r.right - r.left - 8), 0);
  1008.         ::Line(0, -1);
  1009.         ::Move(0, -1);
  1010.         ::RGBForeColor(&gAGARamp[r8]);
  1011.         ::Line(1, 1);
  1012.         ::MoveTo(r.left + 3, r.top + 4);
  1013.         ::Line(1, -1);
  1014.         ::MoveTo(r.right -5, r.top + 3);
  1015.         ::Line(1, 1);
  1016.         ::MoveTo(r.right -5, r.bottom - 4);
  1017.         ::Line(1, -1);
  1018.         ::Move(1, 1);
  1019.         ::RGBForeColor(&gAGARamp[r7]);
  1020.         ::Line(-1, 1);
  1021.         }
  1022.     else
  1023.         {
  1024.         ::RGBForeColor(&gAGARamp[rB]);
  1025.         ::PenSize(2, 2);
  1026.         ::FrameRoundRect(&r, 11, 11);
  1027.         ::PenSize(1, 1);
  1028.         }
  1029.     }
  1030.  
  1031. void AGAPushButton::DrawOutlineDisabled(Boolean deep)
  1032.     {
  1033.     // Draw the default button outline in disabled
  1034.     // state if the button has one. It may be either
  1035.     // inside or outside mBounds.
  1036.  
  1037.     if (! mIsDefault)
  1038.         return;
  1039.  
  1040.     Rect    r = mBounds;
  1041.     
  1042.     if (! mFrameInside)
  1043.         ::InsetRect(&r, -3, -3);
  1044.  
  1045.     if (deep)
  1046.         {
  1047.         // Draw the frame.
  1048.         ::MoveTo(r.left + 1, r.top + 2);
  1049.         ::RGBForeColor(&gAGARamp[r7]);
  1050.         ::Line(1, -1);
  1051.         ::Move(1, -1);
  1052.         ::Line(0, 0);
  1053.         ::Move(1, 0);
  1054.         ::Line(r.right - r.left - 8, 0);
  1055.         ::Line(0, 0);
  1056.         ::Move(1, 1);
  1057.         ::Line(1, 1);
  1058.         ::Move(1, 1);
  1059.         ::Line(0, 0);
  1060.         ::Move(0, 1);
  1061.         ::Line(0, r.bottom - r.top - 8);
  1062.         ::Line(0, 0);
  1063.         ::Move(-1, 1);
  1064.         ::Line(-1, 1);
  1065.         ::Move(-1, 1);
  1066.         ::Line(0, 0);
  1067.         ::Move(-1, 0);
  1068.         ::Line(- (r.right - r.left - 8), 0);
  1069.         ::Line(0, 0);
  1070.         ::Move(-1, -1);
  1071.         ::Line(-1, -1);
  1072.         ::Move(-1, -1);
  1073.         ::Line(0, 0);
  1074.         ::Move(0, -1);
  1075.         ::Line(0, -(r.bottom - r.top - 8));
  1076.         ::Line(0, 0);
  1077.         
  1078.         // Draw the interior.
  1079.         ::MoveTo(r.left + 1, r.bottom - 4);
  1080.         ::RGBForeColor(&gAGARamp[r4]);
  1081.         ::Line(0, -(r.bottom - r.top - 7));
  1082.         ::Line(1, 0);
  1083.         ::Line(0, -1);
  1084.         ::Line(1, 0);
  1085.         ::Line(0, -1);
  1086.         ::Line(r.right - r.left - 8, 0);
  1087.         ::Move(3, 2);
  1088.         ::Line(0, r.bottom - r.top - 7);
  1089.         ::Line(-1, 0);
  1090.         ::Line(0, 1);
  1091.         ::Line(-1, 0);
  1092.         ::Line(0, 1);
  1093.         ::Line(-(r.right - r.left - 7), 0);
  1094.         ::Move(-2, -2);
  1095.         ::Line(1, 1);
  1096.         ::Line(0, -(r.bottom - r.top - 7));
  1097.         ::Line(1, 0);
  1098.         ::Line(0, -1);
  1099.         ::Line(1, 0);
  1100.         ::Line(0, -1);
  1101.         ::Line(r.right - r.left - 7, 0);
  1102.         ::Line(-1, -1);
  1103.         ::Move(-1, 2);
  1104.         ::Line(2, 0);
  1105.         ::Move(-1, 1);
  1106.         ::Line(1, 0);
  1107.         ::Line(0, r.bottom - r.top - 9);
  1108.         ::Line(-1, 0);
  1109.         ::Line(0, 1);
  1110.         ::Line(-1, 0);
  1111.         ::Line(0, 1);
  1112.         ::Line(-(r.right - r.left - 8), 0);
  1113.         ::Line(0, -2);
  1114.         ::Line(1, 1);
  1115.         }
  1116.     else
  1117.         {
  1118.         ::RGBForeColor(&gAGARamp[rB]);
  1119.         ::PenSize(2, 2);
  1120.         ::FrameRoundRect(&r, 11, 11);
  1121.         ::PenSize(1, 1);
  1122.         }
  1123.     }
  1124.  
  1125. //
  1126. // AGACheckBox ---------------------------------------------------------------
  1127. //
  1128. // This class implements a standard checkbox object with the additional
  1129. // capability of supporting mixed state.
  1130. //
  1131.  
  1132. AGACheckBox::AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, Boolean automaticState)
  1133. : AGAObject(bounds)
  1134.     {
  1135.     // Construct with initial empty button title.
  1136.  
  1137.     mValue = kCheckBoxOff;
  1138.     mAutomaticState = automaticState;
  1139.     mTitle[0];
  1140.     mTextStyle = textStyle;
  1141.     }
  1142.  
  1143. AGACheckBox::AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, StringPtr title, Boolean automaticState)
  1144. : AGAObject(bounds)
  1145.     {
  1146.     // Construct with specified button title.
  1147.  
  1148.     mValue = kCheckBoxOff;
  1149.     mAutomaticState = automaticState;
  1150.     AGA_PLstrcpy(mTitle, title);
  1151.     mTextStyle = textStyle;
  1152.     }
  1153.  
  1154. AGACheckBox::AGACheckBox(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex, Boolean automaticState)
  1155. : AGAObject(bounds)
  1156.     {
  1157.     // Construct by getting button title from specified resource.
  1158.  
  1159.     mValue = kCheckBoxOff;
  1160.     mAutomaticState = automaticState;
  1161.     ::GetIndString(mTitle, stringListResourceID, stringIndex);
  1162.     mTextStyle = textStyle;
  1163.     }
  1164.  
  1165. AGACheckBox::~AGACheckBox()
  1166.     {
  1167.     }
  1168.  
  1169. void AGACheckBox::DrawObject()
  1170.     {
  1171.     // Draw button in normal unpressed state.
  1172.  
  1173.     this->DrawButton(kNotPressed);
  1174.     }
  1175.  
  1176. Boolean AGACheckBox::TrackMouse(Point mouseLocation)
  1177.     {
  1178.     // If inherited tracking succeeded and we are set to
  1179.     // automatically change our state, toggle it.
  1180.  
  1181.     Boolean    wasItHit = AGAObject::TrackMouse(mouseLocation);
  1182.  
  1183.     if (wasItHit && mAutomaticState)
  1184.         this->SetValue((mValue == kCheckBoxOn) ? kCheckBoxOff : kCheckBoxOn, kRedraw);
  1185.  
  1186.     return wasItHit;
  1187.     }
  1188.  
  1189. void AGACheckBox::SetTitle(StringPtr title, Boolean redraw)
  1190.     {
  1191.     // Change button title, redraw if specified.
  1192.  
  1193.     AGA_PLstrcpy(mTitle, title);
  1194.     
  1195.     if (redraw)
  1196.         this->DrawObject();
  1197.     }
  1198.  
  1199. SInt32 AGACheckBox::GetValue()
  1200.     {
  1201.     // Return current state.
  1202.  
  1203.     return mValue;
  1204.     }
  1205.  
  1206. void AGACheckBox::SetValue(SInt32 newValue, Boolean redraw)
  1207.     {
  1208.     // Set current state, redraw if specified and necessary.
  1209.  
  1210.     if (newValue != mValue)
  1211.         {
  1212.         mValue = newValue;
  1213.         
  1214.         if (redraw)
  1215.             {
  1216.             this->DrawButton(kNotPressed);
  1217.             }
  1218.         }
  1219.     }
  1220.  
  1221. void AGACheckBox::DrawButton(Boolean pressed)
  1222.     {
  1223.     AGADrawingEnvironment    env;
  1224.  
  1225.     // Draw the button in the appropriate state.
  1226.  
  1227.     GDIterator    iter;
  1228.     Boolean        deep;
  1229.  
  1230.     while (iter.More(deep))
  1231.         {
  1232.         if (! mEnabled)
  1233.             this->DrawButtonDisabled(deep);
  1234.         else if (pressed)
  1235.             this->DrawButtonPressed(deep);
  1236.         else
  1237.             this->DrawButtonNormal(deep);
  1238.         }
  1239.     }
  1240.  
  1241. void AGACheckBox::SetTrackingState(Boolean isIn)
  1242.     {
  1243.     // Draw the button pressed or unpressed as specified.
  1244.  
  1245.     this->DrawButton(isIn);
  1246.     }
  1247.  
  1248. void AGACheckBox::DrawButtonNormal(Boolean deep)
  1249.     {
  1250.     // Draw the button in enabled/unpressed state.
  1251.  
  1252.     Rect    r = mBounds;
  1253.     
  1254.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  1255.  
  1256.     r.bottom = r.top + kCheckBoxSize;
  1257.     r.right = r.left + kCheckBoxSize;
  1258.     
  1259.     ::PenSize(1, 1);
  1260.  
  1261.     if (deep)
  1262.         {
  1263.         // Fill the interior.
  1264.         ::InsetRect(&r, 1, 1);
  1265.         ::RGBForeColor(&gAGARamp[r2]);
  1266.         ::PaintRect(&r);
  1267.         ::InsetRect(&r, -1, -1);
  1268.         
  1269.         // Draw the frame.
  1270.         ::RGBForeColor(&gAGARamp[rB]);
  1271.         ::FrameRect(&r);
  1272.         
  1273.         // Draw the edges.
  1274.         ::MoveTo(r.left + 1, r.bottom - 3);
  1275.         ::RGBForeColor(&gAGARamp[rW]);
  1276.         ::Line(0, -8);
  1277.         ::Line(8, 0);
  1278.         ::Move(1, 1);
  1279.         ::RGBForeColor(&gAGARamp[r7]);
  1280.         ::Line(0, 8);
  1281.         ::Line(-8, 0);
  1282.         
  1283.         if (mValue == kCheckBoxOn)
  1284.             {
  1285.             // Draw the X and its shadow.
  1286.             ::MoveTo(r.left + 3, r.top + 2);
  1287.             ::RGBForeColor(&gAGARamp[rB]);
  1288.             ::Line(5, 5);
  1289.             ::Move(0, 1);
  1290.             ::Line(-5, -5);
  1291.             ::Move(0, 4);
  1292.             ::Line(5, -5);
  1293.             ::Move(0, 1);
  1294.             ::Line(-5, 5);
  1295.             ::Move(1, 0);
  1296.             ::RGBForeColor(&gAGARamp[r8]);
  1297.             ::Line(1, -1);
  1298.             ::Move(2, -2);
  1299.             ::Line(2, -2);
  1300.             ::Move(0, 1);
  1301.             ::RGBForeColor(&gAGARamp[r5]);
  1302.             ::Line(-1, 1);
  1303.             ::Move(-2, 2);
  1304.             ::Line(-2, 2);
  1305.             ::Move(5, 0);
  1306.             ::Line(0, 0);
  1307.             ::Move(0, -1);
  1308.             ::RGBForeColor(&gAGARamp[r8]);
  1309.             ::Line(0, 0);
  1310.             }
  1311.         else if (mValue == kCheckBoxMixed)
  1312.             {
  1313.             // Draw the dash and its shadow.
  1314.             ::MoveTo(r.left + 3, r.top + 5);
  1315.             ::PenSize(2, 2);
  1316.             ::RGBForeColor(&gAGARamp[rB]);
  1317.             ::Line(4, 0);
  1318.             
  1319.             ::MoveTo(r.left + 4, r.top + 7);
  1320.             ::PenSize(1, 1);
  1321.             ::RGBForeColor(&gAGARamp[r5]);
  1322.             ::Line(5, 0);
  1323.             ::Line(-2, 0);
  1324.             }
  1325.         }
  1326.     else
  1327.         {
  1328.         // Paint white over previous junk, if any.
  1329.         ::RGBForeColor(&gAGARamp[rW]);
  1330.         ::PaintRect(&r);
  1331.         // Paint frame.
  1332.         ::RGBForeColor(&gAGARamp[rB]);
  1333.         ::FrameRect(&r);
  1334.  
  1335.         // Draw check or dash.
  1336.         if (mValue == kCheckBoxOn)
  1337.             {
  1338.             ::PenSize(1, 1);
  1339.             ::MoveTo(r.left, r.top);
  1340.             ::Line(kCheckBoxSize-1, kCheckBoxSize-1);
  1341.             ::Move(-(kCheckBoxSize-1), 0);
  1342.             ::Line(kCheckBoxSize-1, -(kCheckBoxSize-1));
  1343.             }
  1344.         else if (mValue == kCheckBoxMixed)
  1345.             {
  1346.             ::PenSize(1, 2);
  1347.             ::MoveTo(r.left + 3, r.top + 5);
  1348.             ::Line(5, 0);
  1349.             }
  1350.         
  1351.         ::PenNormal();
  1352.         }
  1353.  
  1354.     // Draw the title.
  1355.     r = mBounds;
  1356.  
  1357.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  1358.  
  1359.     r.left += (kCheckBoxSize + 4);
  1360.     r.bottom = r.top + kCheckBoxSize;
  1361.     AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
  1362.     }
  1363.  
  1364. void AGACheckBox::DrawButtonPressed(Boolean deep)
  1365.     {
  1366.     // Draw the button in enabled/pressed state.
  1367.  
  1368.     Rect    r = mBounds;
  1369.     
  1370.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  1371.  
  1372.     r.bottom = r.top + kCheckBoxSize;
  1373.     r.right = r.left + kCheckBoxSize;
  1374.     
  1375.     ::PenSize(1, 1);
  1376.  
  1377.     if (deep)
  1378.         {
  1379.         // Fill the interior.
  1380.         ::InsetRect(&r, 1, 1);
  1381.         ::RGBForeColor(&gAGARamp[r8]);
  1382.         ::PaintRect(&r);
  1383.         ::InsetRect(&r, -1, -1);
  1384.         
  1385.         // Draw the frame.
  1386.         ::RGBForeColor(&gAGARamp[rB]);
  1387.         ::FrameRect(&r);
  1388.         
  1389.         // Draw the edges.
  1390.         ::MoveTo(r.left + 1, r.bottom - 3);
  1391.         ::RGBForeColor(&gAGARamp[r10]);
  1392.         ::Line(0, -8);
  1393.         ::Line(8, 0);
  1394.         ::Move(1, 1);
  1395.         ::RGBForeColor(&gAGARamp[r6]);
  1396.         ::Line(0, 8);
  1397.         ::Line(-8, 0);
  1398.         
  1399.         if (mValue == kCheckBoxOn)
  1400.             {
  1401.             // Draw the X and its shadow.
  1402.             ::MoveTo(r.left + 3, r.top + 2);
  1403.             ::RGBForeColor(&gAGARamp[rB]);
  1404.             ::Line(5, 5);
  1405.             ::Move(0, 1);
  1406.             ::Line(-5, -5);
  1407.             ::Move(0, 4);
  1408.             ::Line(5, -5);
  1409.             ::Move(0, 1);
  1410.             ::Line(-5, 5);
  1411.             ::Move(1, 0);
  1412.             ::RGBForeColor(&gAGARamp[r11]);
  1413.             ::Line(1, -1);
  1414.             ::Move(2, -2);
  1415.             ::Line(2, -2);
  1416.             ::Move(0, 1);
  1417.             ::RGBForeColor(&gAGARamp[r10]);
  1418.             ::Line(-1, 1);
  1419.             ::Move(-2, 2);
  1420.             ::Line(-2, 2);
  1421.             ::Move(5, 0);
  1422.             ::Line(0, 0);
  1423.             ::Move(0, -1);
  1424.             ::RGBForeColor(&gAGARamp[r11]);
  1425.             ::Line(0, 0);
  1426.             }
  1427.         else if (mValue == kCheckBoxMixed)
  1428.             {
  1429.             // Draw the dash and its shadow.
  1430.             ::MoveTo(r.left + 3, r.top + 5);
  1431.             ::PenSize(2, 2);
  1432.             ::RGBForeColor(&gAGARamp[rB]);
  1433.             ::Line(4, 0);
  1434.             
  1435.             ::MoveTo(r.left + 4, r.top + 7);
  1436.             ::PenSize(1, 1);
  1437.             ::RGBForeColor(&gAGARamp[r10]);
  1438.             ::Line(5, 0);
  1439.             ::Line(-2, 0);
  1440.             }
  1441.         }
  1442.     else
  1443.         {
  1444.         // Paint white over previous junk, if any.
  1445.         ::RGBForeColor(&gAGARamp[rW]);
  1446.         ::PaintRect(&r);
  1447.         // Paint frame.
  1448.         ::RGBForeColor(&gAGARamp[rB]);
  1449.         ::PenSize(2, 2);
  1450.         ::FrameRect(&r);
  1451.  
  1452.         // Draw check or dash.
  1453.         if (mValue == kCheckBoxOn)
  1454.             {
  1455.             ::PenSize(1, 1);
  1456.             ::MoveTo(r.left, r.top);
  1457.             ::Line(kCheckBoxSize-1, kCheckBoxSize-1);
  1458.             ::Move(-(kCheckBoxSize-1), 0);
  1459.             ::Line(kCheckBoxSize-1, -(kCheckBoxSize-1));
  1460.             }
  1461.         else if (mValue == kCheckBoxMixed)
  1462.             {
  1463.             ::PenSize(1, 2);
  1464.             ::MoveTo(r.left + 3, r.top + 5);
  1465.             ::Line(5, 0);
  1466.             }
  1467.         
  1468.         ::PenNormal();
  1469.         }
  1470.  
  1471.     // Draw the title.
  1472.     r = mBounds;
  1473.  
  1474.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  1475.  
  1476.     r.left += (kCheckBoxSize + 4);
  1477.     r.bottom = r.top + kCheckBoxSize;
  1478.     AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
  1479.     }
  1480.  
  1481. void AGACheckBox::DrawButtonDisabled(Boolean deep)
  1482.     {
  1483.     // Draw the button in disabled/unpressed state.
  1484.  
  1485.     Rect    r = mBounds;
  1486.     
  1487.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  1488.  
  1489.     r.bottom = r.top + kCheckBoxSize;
  1490.     r.right = r.left + kCheckBoxSize;
  1491.     
  1492.     ::PenSize(1, 1);
  1493.  
  1494.     if (deep)
  1495.         {
  1496.         // Fill the interior.
  1497.         ::InsetRect(&r, 1, 1);
  1498.         ::RGBForeColor(&gAGARamp[r2]);
  1499.         ::PaintRect(&r);
  1500.         ::InsetRect(&r, -1, -1);
  1501.         
  1502.         // Draw the frame.
  1503.         ::RGBForeColor(&gAGARamp[r7]);
  1504.         ::FrameRect(&r);
  1505.  
  1506.         if (mValue == kCheckBoxOn)
  1507.             {
  1508.             // Draw the X.
  1509.             ::PenSize(1, 2);
  1510.             ::MoveTo(r.left + 3, r.top + 2);
  1511.             ::RGBForeColor(&gAGARamp[r7]);
  1512.             ::Line(5, 5);
  1513.             ::Move(-5, 0);
  1514.             ::Line(5, -5);
  1515.             ::Move(0, 1);
  1516.             }
  1517.         else if (mValue == kCheckBoxMixed)
  1518.             {
  1519.             // Draw the dash.
  1520.             ::MoveTo(r.left + 3, r.top + 5);
  1521.             ::PenSize(2, 2);
  1522.             ::RGBForeColor(&gAGARamp[r7]);
  1523.             ::Line(4, 0);
  1524.             }
  1525.         }
  1526.     else
  1527.         {
  1528.         // Paint white over previous junk, if any.
  1529.         ::RGBForeColor(&gAGARamp[rW]);
  1530.         ::PaintRect(&r);
  1531.  
  1532.         // Paint frame.
  1533.         ::PenPat(&qd.gray);
  1534.         ::RGBForeColor(&gAGARamp[rB]);
  1535.         ::FrameRect(&r);
  1536.  
  1537.         // Draw check or dash.
  1538.         if (mValue == kCheckBoxOn)
  1539.             {
  1540.             ::PenPat(&qd.black);    // 1-pixel diagonals can disappear when qd.gray
  1541.             ::MoveTo(r.left + 2, r.top + 2);
  1542.             ::Line(kCheckBoxSize-5, kCheckBoxSize-5);
  1543.             ::Move(-(kCheckBoxSize-5), 0);
  1544.             ::Line(kCheckBoxSize-5, -(kCheckBoxSize-5));
  1545.             }
  1546.         else if (mValue == kCheckBoxMixed)
  1547.             {
  1548.             ::PenSize(1, 2);
  1549.             ::MoveTo(r.left + 3, r.top + 5);
  1550.             ::Line(5, 0);
  1551.             }
  1552.         
  1553.         ::PenNormal();
  1554.         }
  1555.  
  1556.     // Draw the title.
  1557.     r = mBounds;
  1558.  
  1559.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  1560.  
  1561.     r.left += (kCheckBoxSize + 4);
  1562.     r.bottom = r.top + kCheckBoxSize;
  1563.     AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kDisabledOutput, deep, mTextStyle);
  1564.     }
  1565.  
  1566. //
  1567. // AGAGroupsContainer --------------------------------------------------------
  1568. //
  1569. // This class is used internally to maintain the MExclusiveObject
  1570. // behavior that allows radio buttons to automatically maintain
  1571. // standard radio button group XOR behavior.
  1572. //
  1573.  
  1574. AGAGroupsContainer::AGAGroupsContainer()
  1575.     {
  1576.     mGroupsArraySize = 0;
  1577.     mGroups = (AGAGroupMember**) ::NewHandle(0);
  1578.     
  1579.     this->ExpandArray();
  1580.     }
  1581.  
  1582. AGAGroupsContainer::~AGAGroupsContainer()
  1583.     {
  1584.     if (mGroups != NULL)
  1585.         {
  1586.         ::DisposeHandle((Handle) mGroups);
  1587.         mGroups = NULL;
  1588.         }
  1589.     }
  1590.  
  1591. void AGAGroupsContainer::AGAAddGroupMember(MExclusiveObject* groupMember)
  1592.     {
  1593.     this->AddGroupMember(groupMember, true);
  1594.     }
  1595.  
  1596. void AGAGroupsContainer::AGARemoveGroupMember(MExclusiveObject* groupMember)
  1597.     {
  1598.     // If the supplied object has an ID pair, search for it in the
  1599.     // members array and zero it out.
  1600.  
  1601.     if ((mGroups != NULL) && (groupMember->mGroupIDPart1 != kNoGroupID) && (groupMember->mGroupIDPart2 != kNoGroupID))
  1602.         {
  1603.         AGAGroupMember*    memberPtr;
  1604.  
  1605.         ::HLock((Handle) mGroups);
  1606.  
  1607.         memberPtr = *mGroups;
  1608.  
  1609.         for (UInt32 i = 0; i < mGroupsArraySize; i++)
  1610.             {
  1611.             if ((memberPtr->mGroupIDPart1 == groupMember->mGroupIDPart1) &&
  1612.                 (memberPtr->mGroupIDPart2 == groupMember->mGroupIDPart2) &&
  1613.                 (memberPtr->mGroupMember == groupMember))
  1614.                 {
  1615.                 memberPtr->mGroupIDPart1 = kNoGroupID;
  1616.                 memberPtr->mGroupIDPart2 = kNoGroupID;
  1617.                 memberPtr->mGroupMember = NULL;
  1618.                 }
  1619.                 
  1620.             memberPtr++;
  1621.             }
  1622.  
  1623.         ::HUnlock((Handle) mGroups);
  1624.         }
  1625.     }
  1626.  
  1627. void AGAGroupsContainer::AGAHitGroupMember(MExclusiveObject* groupMember)
  1628.     {
  1629.     // If the supplied object has an ID pair, send every other
  1630.     // member of its group the TurnOff message.
  1631.  
  1632.     if ((mGroups != NULL) && (groupMember->mGroupIDPart1 != kNoGroupID) && (groupMember->mGroupIDPart2 != kNoGroupID))
  1633.         {
  1634.         AGAGroupMember*    memberPtr;
  1635.  
  1636.         ::HLock((Handle) mGroups);
  1637.  
  1638.         memberPtr = *mGroups;
  1639.  
  1640.         for (UInt32 i = 0; i < mGroupsArraySize; i++)
  1641.             {
  1642.             if ((memberPtr->mGroupIDPart1 == groupMember->mGroupIDPart1) &&
  1643.                 (memberPtr->mGroupIDPart2 == groupMember->mGroupIDPart2))
  1644.                 memberPtr->mGroupMember->TurnOff();
  1645.                 
  1646.             memberPtr++;
  1647.             }
  1648.  
  1649.         ::HUnlock((Handle) mGroups);
  1650.         }
  1651.     }
  1652.  
  1653. void AGAGroupsContainer::AddGroupMember(MExclusiveObject* groupMember, Boolean allowExpand)
  1654.     {
  1655.     // If the supplied object has an ID pair, add it to the
  1656.     // members array. Try to re-use a zeroed-out entry; if none
  1657.     // is left, expand the handle by another chunk.
  1658.  
  1659.     if ((mGroups != NULL) && (groupMember->mGroupIDPart1 != kNoGroupID) && (groupMember->mGroupIDPart2 != kNoGroupID))
  1660.         {
  1661.         AGAGroupMember*    memberPtr;
  1662.         Boolean            done = false;
  1663.  
  1664.         ::HLock((Handle) mGroups);
  1665.  
  1666.         memberPtr = *mGroups;
  1667.  
  1668.         for (UInt32 i = 0; (i < mGroupsArraySize) && ! done; i++)
  1669.             {
  1670.             if ((memberPtr->mGroupIDPart1 == kNoGroupID) &&
  1671.                 (memberPtr->mGroupIDPart2 == kNoGroupID))
  1672.                 {
  1673.                 memberPtr->mGroupIDPart1 = groupMember->mGroupIDPart1;
  1674.                 memberPtr->mGroupIDPart2 = groupMember->mGroupIDPart2;
  1675.                 memberPtr->mGroupMember = groupMember;
  1676.                 done = true;
  1677.                 }
  1678.                 
  1679.             memberPtr++;
  1680.             }
  1681.  
  1682.         ::HUnlock((Handle) mGroups);
  1683.         
  1684.         if (allowExpand && ! done)
  1685.             {
  1686.             this->ExpandArray();
  1687.             this->AddGroupMember(groupMember, false);    // false = recur once only!
  1688.             }
  1689.         }
  1690.     }
  1691.  
  1692. void AGAGroupsContainer::ExpandArray()
  1693.     {
  1694.     if (mGroups != NULL)
  1695.         {
  1696.         ::SetHandleSize((Handle) mGroups, (mGroupsArraySize + kGroupArrayChunkSize) * sizeof(AGAGroupMember));
  1697.         
  1698.         if (::MemError() == noErr)
  1699.             {
  1700.             mGroupsArraySize += kGroupArrayChunkSize;
  1701.             
  1702.             for (UInt32 i = mGroupsArraySize - kGroupArrayChunkSize; i < mGroupsArraySize; i++)
  1703.                 {
  1704.                 (*mGroups)[i].mGroupIDPart1 = kNoGroupID;
  1705.                 (*mGroups)[i].mGroupIDPart2 = kNoGroupID;
  1706.                 (*mGroups)[i].mGroupMember = NULL;
  1707.                 }
  1708.             }
  1709.         }
  1710.     }
  1711.  
  1712. //
  1713. // MExclusiveObject ---------------------------------------------------------------
  1714. //
  1715. // This class is a mixin class for objects that can be included in a
  1716. // group of mutually exclusively selected objects, i.e. radio buttons
  1717. // or icon buttons. When any group member is selected, the others in
  1718. // the group are sent the TurnOff message.
  1719. //
  1720.  
  1721. MExclusiveObject::MExclusiveObject(UInt32 groupIDPart1, UInt32 groupIDPart2)
  1722.     {
  1723.     // Construct by setting the ID pair and adding to
  1724.     // the group.
  1725.  
  1726.     mGroupIDPart1 = groupIDPart1;
  1727.     mGroupIDPart2 = groupIDPart2;
  1728.  
  1729.     gGroupsContainer->AGAAddGroupMember(this);
  1730.     }
  1731.  
  1732. MExclusiveObject::~MExclusiveObject()
  1733.     {
  1734.     // Destruct by removing from the group.
  1735.  
  1736.     gGroupsContainer->AGARemoveGroupMember(this);
  1737.     }
  1738.  
  1739. void MExclusiveObject::SetGroupID(UInt32 groupIDPart1, UInt32 groupIDPart2)
  1740.     {
  1741.     gGroupsContainer->AGARemoveGroupMember(this);
  1742.  
  1743.     mGroupIDPart1 = groupIDPart1;
  1744.     mGroupIDPart2 = groupIDPart2;
  1745.  
  1746.     gGroupsContainer->AGAAddGroupMember(this);
  1747.     }
  1748.  
  1749. void MExclusiveObject::TurnOff()
  1750.     {
  1751.     // Override as needed.
  1752.     }
  1753.  
  1754. //
  1755. // AGAOffscreenImage ------------------------------------------------------------
  1756. //
  1757. // AGAOffscreenImage holds the data needed to blast a clipped region
  1758. // of pixel values onto the current port. This is used by the AGARadioButton
  1759. // class to avoid the ultra-tedious pixel-by-pixel drawing of the grayscale
  1760. // radio button images.
  1761. //
  1762.  
  1763. AGAOffscreenImage::AGAOffscreenImage()
  1764.     {
  1765.     mImagePixMap = NULL;
  1766.     mClippingRegion = NULL;
  1767.     }
  1768.  
  1769. AGAOffscreenImage::~AGAOffscreenImage()
  1770.     {
  1771.     if (mImagePixMap != NULL)
  1772.         ::DisposePixMap(mImagePixMap);
  1773.  
  1774.     if (mClippingRegion != NULL)
  1775.         ::DisposeRgn(mClippingRegion);
  1776.     }
  1777.  
  1778. OSErr AGAOffscreenImage::CreateImageData(Point imageSize,
  1779.                                         SInt8* imageColorIndexes,
  1780.                                         RgnHandle clippingRegion,
  1781.                                         const RGBColor* outsideColor)
  1782.     {
  1783.     // Allocate an offscreen PixMap to contain the RGB values
  1784.     // specified.
  1785.  
  1786.     const UInt32 kImageDepth = 4;
  1787.     
  1788.     ::SetRect(&mImageSourceRect, 0, 0, imageSize.h, imageSize.v);
  1789.  
  1790.     if (clippingRegion != NULL)
  1791.         {
  1792.         // Copy the supplied clipping region.
  1793.  
  1794.         mClippingRegion = ::NewRgn();
  1795.         if (mClippingRegion == NULL)
  1796.             return memFullErr;
  1797.  
  1798.         ::CopyRgn(clippingRegion, mClippingRegion);
  1799.         OSErr    result = ::MemError();
  1800.         if (result != noErr)
  1801.             return result;
  1802.         }
  1803.  
  1804.     //
  1805.     // Allocate and set up the PixMap structure.
  1806.     //
  1807.  
  1808.     Ptr    imagePtr = ::NewPtr(kImageDepth * imageSize.h * imageSize.v);
  1809.  
  1810.     if (imagePtr == NULL)
  1811.         return memFullErr;
  1812.  
  1813.     mImagePixMap = ::NewPixMap();
  1814.     ::HLockHi((Handle) mImagePixMap);
  1815.     
  1816.     PixMapPtr    pixMapPtr = *mImagePixMap;
  1817.     
  1818.     pixMapPtr->baseAddr = imagePtr;
  1819.     pixMapPtr->rowBytes = (kImageDepth * imageSize.h) | 0x8000;
  1820.     pixMapPtr->bounds = mImageSourceRect;
  1821.     pixMapPtr->pixelType = RGBDirect;
  1822.     pixMapPtr->pixelSize = 32;    // direct 32-bit color values
  1823.     pixMapPtr->cmpCount = 3;    // 3 color components (RGB)
  1824.     pixMapPtr->cmpSize = 8;        // 8 bits per component
  1825.     pixMapPtr->planeBytes = 0;
  1826.  
  1827.     if (pixMapPtr->pmTable != NULL)
  1828.         {
  1829.         // We're using direct color, so toss the table.
  1830.         ::DisposeCTable(pixMapPtr->pmTable);
  1831.         pixMapPtr->pmTable = NULL;
  1832.         }
  1833.     
  1834.     pixMapPtr->pmReserved = 0;
  1835.     
  1836.     //
  1837.     // Finally, set the pixel RGB color values.
  1838.     //
  1839.     
  1840.     UInt32*    pixelPtr = (UInt32*) imagePtr;
  1841.     UInt32    numPixels = imageSize.h * imageSize.v;
  1842.     SInt8*    indexPtr = imageColorIndexes;
  1843.     
  1844.     for (UInt32 pixelIndex = 0; pixelIndex < numPixels; pixelIndex++)
  1845.         {
  1846.         SInt8        rampIndex = *indexPtr++;
  1847.         RGBColor    rampColor;
  1848.         
  1849.         if (rampIndex == OUT)
  1850.             rampColor = *outsideColor;
  1851.         else
  1852.             rampColor = gAGARamp[rampIndex];
  1853.         
  1854.         //
  1855.         // Construct 32-bit color value.
  1856.         // Assuming red is RRrr, blue is BBbb, green is GGgg,
  1857.         // we want 0x00RRGGBB, using high byte of each color.
  1858.         // This way we toss the low-order (LSB) color data.
  1859.         //
  1860.  
  1861.         UInt32    pixelValue =
  1862.                 ((((UInt32) rampColor.red) & 0x0000FF00) << 8) |
  1863.                 (((UInt32) rampColor.green) & 0x0000FF00) |
  1864.                 ((((UInt32) rampColor.blue) & 0x0000FF00) >> 8);
  1865.  
  1866.         *pixelPtr++ = pixelValue;
  1867.         }
  1868.  
  1869.     return noErr;
  1870.     }
  1871.  
  1872. void AGAOffscreenImage::DrawImage(SInt16 imageHOrigin, SInt16 imageVOrigin)
  1873.     {
  1874.     // Blast the offscreen image data into the current
  1875.     // port at the specified coordinate location.
  1876.  
  1877.     RGBColor    savedBackColor;
  1878.     GrafPtr        currentPort;
  1879.     Rect        outputRect = mImageSourceRect;
  1880.     
  1881.     ::GetBackColor(&savedBackColor);
  1882.  
  1883.     // Set to black-on-white before doing CopyBits or our colors may
  1884.     // be massaged on the way to the screen.
  1885.     ::RGBBackColor(&gAGARamp[rW]);
  1886.     ::RGBForeColor(&gAGARamp[rB]);
  1887.     
  1888.     ::OffsetRect(&outputRect, imageHOrigin, imageVOrigin);
  1889.     
  1890.     if (mClippingRegion != NULL)
  1891.         ::OffsetRgn(mClippingRegion, imageHOrigin, imageVOrigin);
  1892.  
  1893.     ::GetPort(¤tPort);
  1894.     ::CopyBits((BitMapPtr) *mImagePixMap,
  1895.         &(currentPort->portBits),
  1896.         &mImageSourceRect,
  1897.         &outputRect,
  1898.         srcCopy,
  1899.         mClippingRegion);
  1900.     
  1901.     if (mClippingRegion != NULL)
  1902.         ::OffsetRgn(mClippingRegion, - imageHOrigin, - imageVOrigin);
  1903.  
  1904.     ::RGBBackColor(&savedBackColor);
  1905.     }
  1906.  
  1907. void AGAOffscreenImage::DrawPattern(Rect* imageRect)
  1908.     {
  1909.     // Blast the offscreen image data into the current
  1910.     // port, starting at the specified coordinate location,
  1911.     // repeating tiled until the imageRect is filled.
  1912.  
  1913.     RGBColor    savedBackColor;
  1914.     GrafPtr        currentPort;
  1915.     Rect        outputRect;
  1916.     
  1917.     ::GetBackColor(&savedBackColor);
  1918.     ::RGBBackColor(&gAGARamp[rW]);    // need white BG for desired CopyBits behavior
  1919.     
  1920.     if (mClippingRegion != NULL)
  1921.         ::OffsetRgn(mClippingRegion, imageRect->left, imageRect->top);
  1922.  
  1923.     ::GetPort(¤tPort);
  1924.     
  1925.     outputRect.top = imageRect->top;
  1926.     outputRect.bottom = outputRect.top + mImageSourceRect.bottom;
  1927.  
  1928.     while (outputRect.top < imageRect->bottom)
  1929.         {
  1930.         outputRect.left = imageRect->left;
  1931.         outputRect.right = outputRect.left + mImageSourceRect.right;
  1932.         
  1933.         while (outputRect.left < imageRect->right)
  1934.             {
  1935.             ::CopyBits((BitMapPtr) *mImagePixMap,
  1936.                 &(currentPort->portBits),
  1937.                 &mImageSourceRect,
  1938.                 &outputRect,
  1939.                 srcCopy,
  1940.                 mClippingRegion);
  1941.             
  1942.             ::OffsetRect(&outputRect, mImageSourceRect.right, 0);
  1943.             }
  1944.  
  1945.         ::OffsetRect(&outputRect, 0, mImageSourceRect.bottom);
  1946.         }
  1947.  
  1948.     if (mClippingRegion != NULL)
  1949.         ::OffsetRgn(mClippingRegion, - imageRect->left, - imageRect->top);
  1950.  
  1951.     ::RGBBackColor(&savedBackColor);
  1952.     }
  1953.  
  1954. //
  1955. // AGARadioButton ---------------------------------------------------------------
  1956. //
  1957. // This class implements a standard radio button object,
  1958. // with the additional capabilities of automatic handling of
  1959. // radio group mutual exclusivity, and mixed state.
  1960. //
  1961.  
  1962. // Each radio button drawing state has an offscreen image.
  1963. AGAOffscreenImage*    AGARadioButton::mgOffscreenRadioImages[kNumRadioImages];
  1964.  
  1965. // These are the color ramp indexes that are used to build the offscreen images.
  1966. SInt8                AGARadioButton::kRadioImageValues[kNumRadioImages][kRadioImageHeight][kRadioImageWidth] =
  1967.     {
  1968.         {    // kRadioNormalOff
  1969.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  1970.         { OUT, OUT,  rB, r10,  r2,  r2,  r2,  r4, r11,  rB, OUT, OUT },
  1971.         { OUT,  rB,  r4,  r2,  r1,  rW,  rW,  rW,  r2,  r7,  rB, OUT },
  1972.         {  r5, r10,  r2,  r1,  rW,  rW,  r1,  r1,  r2,  r4, r11,  r5 },
  1973.         { r11,  r2,  r1,  rW,  rW,  r1,  r1,  r2,  r2,  r4,  r7, r11 },
  1974.         {  rB,  r2,  rW,  rW,  r1,  r1,  r2,  r2,  r4,  r4,  r7,  rB },
  1975.         {  rB,  r2,  rW,  r1,  r1,  r2,  r2,  r4,  r4,  r5,  r7,  rB },
  1976.         { r11,  r4,  rW,  r1,  r2,  r2,  r4,  r4,  r5,  r5,  r7, r11 },
  1977.         {  r5, r10,  r2,  r2,  r2,  r4,  r4,  r5,  r5,  r7, r11,  r5 },
  1978.         { OUT,  rB,  r7,  r4,  r4,  r4,  r5,  r5,  r7,  r7,  rB, OUT },
  1979.         { OUT, OUT,  rB, r10,  r7,  r7,  r7,  r7, r11,  rB, OUT, OUT },
  1980.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  1981.         },
  1982.  
  1983.         {    // kRadioNormalOn
  1984.         { OUT, OUT, OUT,  r5, r12,  rB,  rB, r12,  r5, OUT, OUT, OUT },
  1985.         { OUT, OUT, r12,  rB, r11, r10, r10, r10, r11,  rB, OUT, OUT },
  1986.         { OUT, r12, r11, r10,  r8,  r8,  r8,  r7,  r7,  r6,  rB, OUT },
  1987.         {  r5,  rB, r10,  r8,  rB,  rB,  rB,  rB,  r6,  r6, r11,  r5 },
  1988.         { r12, r11,  r8,  rB,  rB,  rB,  rB,  rB,  rB,  r6,  r4, r11 },
  1989.         {  rB, r10,  r8,  rB,  rB,  rB,  rB,  rB,  rB,  r4,  r4,  rB },
  1990.         {  rB, r10,  r8,  rB,  rB,  rB,  rB,  rB,  rB,  r4,  r2,  rB },
  1991.         { r12, r10,  r7,  rB,  rB,  rB,  rB,  rB,  rB,  r2,  rW, r11 },
  1992.         {  r5, r12,  r7,  r6,  rB,  rB,  rB,  rB,  r2,  rW, r11,  r5 },
  1993.         { OUT, r12,  r6,  r6,  r6,  r4,  r4,  r2,  rW,  rW,  rB, OUT },
  1994.         { OUT, OUT, r12, r11,  r4,  r4,  r2,  rW, r11,  rB, OUT, OUT },
  1995.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  1996.         },
  1997.  
  1998.         {    // kRadioNormalMixed
  1999.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  2000.         { OUT, OUT,  rB, r10,  r2,  r2,  r2,  r4, r11,  rB, OUT, OUT },
  2001.         { OUT,  rB,  r4,  r2,  r1,  rW,  rW,  rW,  r2,  r7,  rB, OUT },
  2002.         {  r5, r10,  r2,  r1,  rW,  rW,  r1,  r1,  r2,  r4, r11,  r5 },
  2003.         { r11,  r2,  r1,  rW,  rW,  r1,  r1,  r2,  r2,  r4,  r7, r11 },
  2004.         {  rB,  r2,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  r4,  r7,  rB },
  2005.         {  rB,  r2,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  r5,  r7,  rB },
  2006.         { r11,  r4,  rW,  r1,  r2,  r2,  r4,  r4,  r5,  r5,  r7, r11 },
  2007.         {  r5, r10,  r2,  r2,  r2,  r4,  r4,  r5,  r5,  r7, r11,  r5 },
  2008.         { OUT,  rB,  r7,  r4,  r4,  r4,  r5,  r5,  r7,  r7,  rB, OUT },
  2009.         { OUT, OUT,  rB, r10,  r7,  r7,  r7,  r7, r11,  rB, OUT, OUT },
  2010.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  2011.         },
  2012.  
  2013.         {    // kRadioPressedOff
  2014.         { OUT, OUT, OUT,  r5, r12,  rB,  rB, r12,  r5, OUT, OUT, OUT },
  2015.         { OUT, OUT, r12,  rB, r11, r11, r11, r11, r11,  rB, OUT, OUT },
  2016.         { OUT, r12, r11, r11, r10, r10,  r9,  r9,  r9,  r8,  rB, OUT },
  2017.         {  r5,  rB, r11, r10, r10,  r9,  r9,  r8,  r8,  r8, r11,  r5 },
  2018.         { r12, r11, r10, r10,  r9,  r9,  r8,  r8,  r8,  r7,  r6, r11 },
  2019.         {  rB, r11, r10,  r9,  r9,  r8,  r8,  r8,  r7,  r7,  r6,  rB },
  2020.         {  rB, r11,  r9,  r9,  r8,  r8,  r8,  r7,  r7,  r6,  r6,  rB },
  2021.         { r12, r11,  r9,  r8,  r8,  r8,  r7,  r7,  r6,  r6,  r4, r11 },
  2022.         {  r5, r12,  r9,  r8,  r8,  r7,  r7,  r6,  r6,  r4, r10,  r5 },
  2023.         { OUT, r11,  r8,  r8,  r7,  r7,  r6,  r6,  r4,  r4,  rB, OUT },
  2024.         { OUT, OUT, r12, r11,  r6,  r6,  r6,  r4, r10,  rB, OUT, OUT },
  2025.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  2026.         },
  2027.  
  2028.         {    // kRadioPressedOn
  2029.         { OUT, OUT, OUT,  r5, r12,  rB,  rB, r12,  r5, OUT, OUT, OUT },
  2030.         { OUT, OUT, r12,  rB, r11, r11, r11, r11, r11,  rB, OUT, OUT },
  2031.         { OUT, r12, r11, r11, r10, r10,  r9,  r9,  r9,  r8,  rB, OUT },
  2032.         {  r5,  rB, r11, r10,  rB,  rB,  rB,  rB,  r8,  r8, r11,  r5 },
  2033.         { r12, r11, r10,  rB,  rB,  rB,  rB,  rB,  rB,  r7,  r6, r11 },
  2034.         {  rB, r11, r10,  rB,  rB,  rB,  rB,  rB,  rB,  r7,  r6,  rB },
  2035.         {  rB, r11,  r9,  rB,  rB,  rB,  rB,  rB,  rB,  r6,  r6,  rB },
  2036.         { r12, r11,  r9,  rB,  rB,  rB,  rB,  rB,  rB,  r6,  r4, r11 },
  2037.         {  r5, r12,  r9,  r8,  rB,  rB,  rB,  rB,  r6,  r4, r10,  r5 },
  2038.         { OUT, r11,  r8,  r8,  r7,  r7,  r6,  r6,  r4,  r4,  rB, OUT },
  2039.         { OUT, OUT, r12, r11,  r6,  r6,  r6,  r4, r10,  rB, OUT, OUT },
  2040.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  2041.         },
  2042.  
  2043.         {    // kRadioPressedMixed
  2044.         { OUT, OUT, OUT,  r5, r12,  rB,  rB, r12,  r5, OUT, OUT, OUT },
  2045.         { OUT, OUT, r12,  rB, r11, r11, r11, r11, r11,  rB, OUT, OUT },
  2046.         { OUT, r12, r11, r11, r10, r10,  r9,  r9,  r9,  r8,  rB, OUT },
  2047.         {  r5,  rB, r11, r10, r10,  r9,  r9,  r8,  r8,  r8, r11,  r5 },
  2048.         { r12, r11, r10, r10,  r9,  r9,  r8,  r8,  r8,  r7,  r6, r11 },
  2049.         {  rB, r11, r10,  rB,  rB,  rB,  rB,  rB,  rB,  r7,  r6,  rB },
  2050.         {  rB, r11,  r9,  rB,  rB,  rB,  rB,  rB,  rB,  r6,  r6,  rB },
  2051.         { r12, r11,  r9,  r8,  r8,  r8,  r7,  r7,  r6,  r6,  r4, r11 },
  2052.         {  r5, r12,  r9,  r8,  r8,  r7,  r7,  r6,  r6,  r4, r10,  r5 },
  2053.         { OUT, r11,  r8,  r8,  r7,  r7,  r6,  r6,  r4,  r4,  rB, OUT },
  2054.         { OUT, OUT, r12, r11,  r6,  r6,  r6,  r4, r10,  rB, OUT, OUT },
  2055.         { OUT, OUT, OUT,  r5, r11,  rB,  rB, r11,  r5, OUT, OUT, OUT },
  2056.         },
  2057.  
  2058.         {    // kRadioDisabledOff
  2059.         { OUT, OUT, OUT,  r4,  r7,  r7,  r7,  r7,  r4, OUT, OUT, OUT },
  2060.         { OUT, OUT,  r7,  r7,  r3,  r2,  r2,  r3,  r7,  r7, OUT, OUT },
  2061.         { OUT,  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7, OUT },
  2062.         {  r4,  r7,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r7,  r4 },
  2063.         {  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7 },
  2064.         {  r7,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r7 },
  2065.         {  r7,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r7 },
  2066.         {  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7 },
  2067.         {  r4,  r7,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r7,  r4 },
  2068.         { OUT,  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7, OUT },
  2069.         { OUT, OUT,  r7,  r7,  r3,  r2,  r2,  r3,  r7,  r7, OUT, OUT },
  2070.         { OUT, OUT, OUT,  r4,  r7,  r7,  r7,  r7,  r4, OUT, OUT, OUT },
  2071.         },
  2072.  
  2073.         {    // kRadioDisabledOn
  2074.         { OUT, OUT, OUT,  r4,  r7,  r7,  r7,  r7,  r4, OUT, OUT, OUT },
  2075.         { OUT, OUT,  r7,  r7,  r4,  r4,  r4,  r4,  r7,  r7, OUT, OUT },
  2076.         { OUT,  r7,  r5,  r4,  r4,  r4,  r4,  r4,  r4,  r5,  r7, OUT },
  2077.         {  r4,  r7,  r4,  r4,  r8,  r8,  r8,  r8,  r4,  r4,  r7,  r4 },
  2078.         {  r7,  r4,  r4,  r8,  r8,  r8,  r8,  r8,  r8,  r4,  r4,  r7 },
  2079.         {  r7,  r4,  r4,  r8,  r8,  r8,  r8,  r8,  r8,  r4,  r4,  r7 },
  2080.         {  r7,  r4,  r4,  r8,  r8,  r8,  r8,  r8,  r8,  r4,  r4,  r7 },
  2081.         {  r7,  r4,  r4,  r8,  r8,  r8,  r8,  r8,  r8,  r4,  r4,  r7 },
  2082.         {  r4,  r7,  r4,  r4,  r8,  r8,  r8,  r8,  r4,  r4,  r7,  r4 },
  2083.         { OUT,  r7,  r5,  r4,  r4,  r4,  r4,  r4,  r4,  r5,  r7, OUT },
  2084.         { OUT, OUT,  r7,  r7,  r4,  r4,  r4,  r4,  r7,  r7, OUT, OUT },
  2085.         { OUT, OUT, OUT,  r4,  r7,  r7,  r7,  r7,  r4, OUT, OUT, OUT },
  2086.         },
  2087.  
  2088.         {    // kRadioDisabledMixed
  2089.         { OUT, OUT, OUT,  r4,  r7,  r7,  r7,  r7,  r4, OUT, OUT, OUT },
  2090.         { OUT, OUT,  r7,  r7,  r3,  r2,  r2,  r3,  r7,  r7, OUT, OUT },
  2091.         { OUT,  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7, OUT },
  2092.         {  r4,  r7,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r7,  r4 },
  2093.         {  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7 },
  2094.         {  r7,  r2,  r2,  r8,  r8,  r8,  r8,  r8,  r8,  r2,  r2,  r7 },
  2095.         {  r7,  r2,  r2,  r8,  r8,  r8,  r8,  r8,  r8,  r2,  r2,  r7 },
  2096.         {  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7 },
  2097.         {  r4,  r7,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r7,  r4 },
  2098.         { OUT,  r7,  r3,  r2,  r2,  r2,  r2,  r2,  r2,  r3,  r7, OUT },
  2099.         { OUT, OUT,  r7,  r7,  r3,  r2,  r2,  r3,  r7,  r7, OUT, OUT },
  2100.         { OUT, OUT, OUT,  r4,  r7,  r7,  r7,  r7,  r4, OUT, OUT, OUT },
  2101.         }
  2102.  
  2103.     };
  2104.  
  2105. OSErr AGARadioButton::AllocateRadioImages()
  2106.     {
  2107.     // Allocate the offscreen image for each radio button state.
  2108.  
  2109.     OSErr    result = noErr;
  2110.     Point    imageSize;
  2111.     
  2112.     imageSize.h = kRadioImageWidth;
  2113.     imageSize.v = kRadioImageHeight;
  2114.     
  2115.     // A simple round rect defines the radio image clipping region.
  2116.  
  2117.     RgnHandle    radioImageClippingRegion = ::NewRgn();
  2118.     
  2119.     if (radioImageClippingRegion == NULL)
  2120.         result = memFullErr;
  2121.     else
  2122.         {
  2123.         Rect    imageClippingRect;
  2124.         
  2125.         ::SetRect(&imageClippingRect, 0, 0, kRadioImageWidth, kRadioImageHeight);
  2126.         ::OpenRgn();
  2127.         ::FrameRoundRect(&imageClippingRect, 11, 11);
  2128.         //::FrameOval(&imageClippingRect);    ugly AGA 7/96 specs use just the chunky circle -- we'll stick with earlier specs
  2129.         ::CloseRgn(radioImageClippingRegion);
  2130.         }
  2131.  
  2132.     for (UInt32 imageIndex = 0; imageIndex < kNumRadioImages; imageIndex++)
  2133.         {
  2134.         if (result == noErr)
  2135.             {
  2136.             mgOffscreenRadioImages[imageIndex] = new AGAOffscreenImage;
  2137.             
  2138.             result = mgOffscreenRadioImages[imageIndex]->CreateImageData(
  2139.                         imageSize,
  2140.                         &kRadioImageValues[imageIndex][0][0],
  2141.                         radioImageClippingRegion, 
  2142.                         &gAGARamp[rB]);
  2143.             }
  2144.         }
  2145.         
  2146.     if (radioImageClippingRegion != NULL)
  2147.         ::DisposeRgn(radioImageClippingRegion);
  2148.     
  2149.     return result;
  2150.     }
  2151.  
  2152. void AGARadioButton::DisposeRadioImages()
  2153.     {
  2154.     for (UInt32 imageIndex = 0; imageIndex < kNumRadioImages; imageIndex++)
  2155.         if (mgOffscreenRadioImages[imageIndex] != NULL)
  2156.             delete mgOffscreenRadioImages[imageIndex];
  2157.     }
  2158.  
  2159. AGARadioButton::AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
  2160. : AGAObject(bounds), MExclusiveObject(groupIDPart1, groupIDPart2)
  2161.     {
  2162.     // Construct with initial empty button title.
  2163.  
  2164.     mValue = kRadioButtonOff;
  2165.     mAutomaticState = automaticState;
  2166.     mTitle[0];
  2167.     mTextStyle = textStyle;
  2168.     }
  2169.  
  2170. AGARadioButton::AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, StringPtr title, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
  2171. : AGAObject(bounds), MExclusiveObject(groupIDPart1, groupIDPart2)
  2172.     {
  2173.     // Construct with specified button title.
  2174.  
  2175.     mValue = kRadioButtonOff;
  2176.     mAutomaticState = automaticState;
  2177.     AGA_PLstrcpy(mTitle, title);
  2178.     mTextStyle = textStyle;
  2179.     }
  2180.  
  2181. AGARadioButton::AGARadioButton(Rect* bounds, const AGATextStyle& textStyle, SInt16 stringListResourceID, SInt16 stringIndex, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
  2182. : AGAObject(bounds), MExclusiveObject(groupIDPart1, groupIDPart2)
  2183.     {
  2184.     // Construct by getting button title from specified resource.
  2185.  
  2186.     mValue = kRadioButtonOff;
  2187.     mAutomaticState = automaticState;
  2188.     ::GetIndString(mTitle, stringListResourceID, stringIndex);
  2189.     mTextStyle = textStyle;
  2190.     }
  2191.  
  2192. AGARadioButton::~AGARadioButton()
  2193.     {
  2194.     }
  2195.  
  2196. void AGARadioButton::DrawObject()
  2197.     {
  2198.     // Draw button in normal unpressed state.
  2199.  
  2200.     this->DrawButton(kNotPressed);
  2201.     }
  2202.  
  2203. Boolean AGARadioButton::TrackMouse(Point mouseLocation)
  2204.     {
  2205.     // If inherited tracking succeeded and we are set to
  2206.     // automatically change our state, toggle it.
  2207.  
  2208.     Boolean    wasItHit = AGAObject::TrackMouse(mouseLocation);
  2209.  
  2210.     if (wasItHit && mAutomaticState)
  2211.         this->SetValue(kRadioButtonOn, kRedraw);
  2212.  
  2213.     return wasItHit;
  2214.     }
  2215.  
  2216. void AGARadioButton::SetTitle(StringPtr title, Boolean redraw)
  2217.     {
  2218.     // Change button title, redraw if specified.
  2219.  
  2220.     AGA_PLstrcpy(mTitle, title);
  2221.     
  2222.     if (redraw)
  2223.         this->DrawObject();
  2224.     }
  2225.  
  2226. SInt32 AGARadioButton::GetValue()
  2227.     {
  2228.     // Return current state.
  2229.  
  2230.     return mValue;
  2231.     }
  2232.  
  2233. void AGARadioButton::SetValue(SInt32 newValue, Boolean redraw)
  2234.     {
  2235.     // Set current state, redraw if specified and necessary.
  2236.  
  2237.     if (newValue == kRadioButtonOn)
  2238.         gGroupsContainer->AGAHitGroupMember(this);
  2239.  
  2240.     if (newValue != mValue)
  2241.         {
  2242.         mValue = newValue;
  2243.         
  2244.         if (redraw)
  2245.             {
  2246.             this->DrawButton(kNotPressed);
  2247.             }
  2248.         }
  2249.     }
  2250.  
  2251. void AGARadioButton::SetGroupID(UInt32 groupIDPart1, UInt32 groupIDPart2)
  2252.     {
  2253.     MExclusiveObject::SetGroupID(groupIDPart1, groupIDPart2);
  2254.  
  2255.     // If we are being installed into a group, we should turn automatic
  2256.     // mode on.
  2257.     
  2258.     if ((groupIDPart1 != kNoGroupID) && (groupIDPart2 != kNoGroupID))
  2259.         mAutomaticState = true;
  2260.     }
  2261.  
  2262. void AGARadioButton::TurnOff()
  2263.     {
  2264.     // Turn off the radio button, presumably in response
  2265.     // to another button in the group being turned on.
  2266.  
  2267.     this->SetValue(kRadioButtonOff, kRedraw);
  2268.     }
  2269.  
  2270. void AGARadioButton::DrawButton(Boolean pressed)
  2271.     {
  2272.     AGADrawingEnvironment    env;
  2273.  
  2274.     // Draw the button in the appropriate state.
  2275.  
  2276.     GDIterator    iter;
  2277.     Boolean        deep;
  2278.  
  2279.     while (iter.More(deep))
  2280.         {
  2281.         if (! mEnabled)
  2282.             this->DrawButtonDisabled(deep);
  2283.         else if (pressed)
  2284.             this->DrawButtonPressed(deep);
  2285.         else
  2286.             this->DrawButtonNormal(deep);
  2287.         }
  2288.     }
  2289.  
  2290. void AGARadioButton::SetTrackingState(Boolean isIn)
  2291.     {
  2292.     // Draw the button pressed or unpressed as specified.
  2293.  
  2294.     this->DrawButton(isIn);
  2295.     }
  2296.  
  2297. void AGARadioButton::DrawButtonNormal(Boolean deep)
  2298.     {
  2299.     Rect    r = mBounds;
  2300.  
  2301.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  2302.  
  2303.     // Draw the button in enabled/unpressed state.
  2304.  
  2305.     if (deep)
  2306.         {
  2307.         if (mValue == kRadioButtonMixed)
  2308.             this->CopyImage(kRadioNormalMixed);
  2309.         else if (mValue == kRadioButtonOn)
  2310.             this->CopyImage(kRadioNormalOn);
  2311.         else
  2312.             this->CopyImage(kRadioNormalOff);
  2313.         }
  2314.     else
  2315.         {
  2316.         r.right = r.left + kRadioImageWidth;
  2317.         r.bottom = r.top + kRadioImageHeight;
  2318.  
  2319.         // Paint white over previous junk, if any.
  2320.         ::RGBForeColor(&gAGARamp[rW]);
  2321.         ::PaintRect(&r);
  2322.         // Paint frame.
  2323.         ::RGBForeColor(&gAGARamp[rB]);
  2324.         ::FrameOval(&r);
  2325.  
  2326.         // Draw dot or dash.
  2327.         if (mValue == kRadioButtonOn)
  2328.             {
  2329.             ::InsetRect(&r, 3, 3);
  2330.             ::PaintRoundRect(&r, 4, 4);
  2331.             }
  2332.         else if (mValue == kRadioButtonMixed)
  2333.             {
  2334.             ::PenSize(1, 2);
  2335.             ::MoveTo(r.left + 3, r.top + 5);
  2336.             ::Line(5, 0);
  2337.             }
  2338.         
  2339.         ::PenNormal();
  2340.         }
  2341.  
  2342.     // Draw the title.
  2343.     r = mBounds;
  2344.  
  2345.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  2346.  
  2347.     r.left += (kRadioImageWidth + 4);
  2348.     r.bottom = r.top + kRadioImageHeight;
  2349.     AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
  2350.     }
  2351.  
  2352. void AGARadioButton::DrawButtonPressed(Boolean deep)
  2353.     {
  2354.     Rect    r = mBounds;
  2355.  
  2356.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  2357.  
  2358.     // Draw the button in enabled/pressed state.
  2359.  
  2360.     if (deep)
  2361.         {
  2362.         if (mValue == kRadioButtonMixed)
  2363.             this->CopyImage(kRadioPressedMixed);
  2364.         else if (mValue == kRadioButtonOn)
  2365.             this->CopyImage(kRadioPressedOn);
  2366.         else
  2367.             this->CopyImage(kRadioPressedOff);
  2368.         }
  2369.     else
  2370.         {
  2371.         r.right = r.left + kRadioImageWidth;
  2372.         r.bottom = r.top + kRadioImageHeight;
  2373.  
  2374.         // Paint white over previous junk, if any.
  2375.         ::RGBForeColor(&gAGARamp[rW]);
  2376.         ::PaintRect(&r);
  2377.         // Paint frame.
  2378.         ::RGBForeColor(&gAGARamp[rB]);
  2379.         ::PenSize(2, 2);
  2380.         ::FrameOval(&r);
  2381.  
  2382.         // Draw dot or dash.
  2383.         if (mValue == kRadioButtonOn)
  2384.             {
  2385.             ::InsetRect(&r, 3, 3);
  2386.             ::PaintRoundRect(&r, 4, 4);
  2387.             }
  2388.         else if (mValue == kRadioButtonMixed)
  2389.             {
  2390.             ::PenSize(1, 2);
  2391.             ::MoveTo(r.left + 3, r.top + 5);
  2392.             ::Line(5, 0);
  2393.             }
  2394.         
  2395.         ::PenNormal();
  2396.         }
  2397.  
  2398.     // Draw the title.
  2399.     r = mBounds;
  2400.  
  2401.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  2402.  
  2403.     r.left += (kRadioImageWidth + 4);
  2404.     r.bottom = r.top + kRadioImageHeight;
  2405.     AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kNormalOutput, deep, mTextStyle);
  2406.     }
  2407.  
  2408. void AGARadioButton::DrawButtonDisabled(Boolean deep)
  2409.     {
  2410.     Rect    r = mBounds;
  2411.  
  2412.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  2413.  
  2414.     // Draw the button in disabled/unpressed state.
  2415.  
  2416.     if (deep)
  2417.         {
  2418.         if (mValue == kRadioButtonMixed)
  2419.             this->CopyImage(kRadioDisabledMixed);
  2420.         else if (mValue == kRadioButtonOn)
  2421.             this->CopyImage(kRadioDisabledOn);
  2422.         else
  2423.             this->CopyImage(kRadioDisabledOff);
  2424.         }
  2425.     else
  2426.         {
  2427.         r.right = r.left + kRadioImageWidth;
  2428.         r.bottom = r.top + kRadioImageHeight;
  2429.  
  2430.         // Paint white over previous junk, if any.
  2431.         ::RGBForeColor(&gAGARamp[rW]);
  2432.         ::PaintRect(&r);
  2433.  
  2434.         // Paint frame.
  2435.         ::PenPat(&qd.gray);
  2436.         ::RGBForeColor(&gAGARamp[rB]);
  2437.         ::FrameOval(&r);
  2438.  
  2439.         // Draw check or dash.
  2440.         if (mValue == kRadioButtonOn)
  2441.             {
  2442.             ::InsetRect(&r, 3, 3);
  2443.             ::PaintRoundRect(&r, 4, 4);
  2444.             }
  2445.         else if (mValue == kRadioButtonMixed)
  2446.             {
  2447.             ::PenSize(1, 2);
  2448.             ::MoveTo(r.left + 3, r.top + 5);
  2449.             ::Line(5, 0);
  2450.             }
  2451.         
  2452.         ::PenNormal();
  2453.         }
  2454.  
  2455.     // Draw the title.
  2456.     r = mBounds;
  2457.  
  2458.     ::OffsetRect(&r, 2, 2);    // visually match the system CDEF
  2459.  
  2460.     r.left += (kRadioImageWidth + 4);
  2461.     r.bottom = r.top + kRadioImageHeight;
  2462.     AGAStringOut(mTitle, &r, truncMiddle, teJustLeft, kDisabledOutput, deep, mTextStyle);
  2463.     }
  2464.  
  2465. void AGARadioButton::CopyImage(UInt32 index)
  2466.     {
  2467.     // Blast the specified offscreen image into the
  2468.     // radio button's button area. We offset by (2, 2)
  2469.     // to match the positioning of the system CDEF.
  2470.  
  2471.     mgOffscreenRadioImages[index]->DrawImage(mBounds.left + 2, mBounds.top + 2);
  2472.     }
  2473.  
  2474. //
  2475. // MIconButtonObject ---------------------------------------------------------------
  2476. //
  2477. // This mixin class handles button drawing for the different types
  2478. // of icon button classes. This class draws the button, and subclasses
  2479. // for push/radio/checkbox that mix it in handle the behavioral aspects.
  2480. //
  2481. // Ideal button sizes, to match AGA specification:
  2482. // - Large icon button: 40x40 (32x32 iclx plus 4 pixel border on each side)
  2483. // - Small icon button: 22x22 (16x16 icsx plus 3 pixel border on each side)
  2484. // - Mini icon button:  16x16 (12x12 icmx plus 2 pixel border on each side)
  2485. // Note that mini icons are a rather rare resource that ResEdit 2.x doesn't grok.
  2486. //
  2487.  
  2488. MIconButtonObject::MIconButtonObject()
  2489.     {
  2490.     // Construct with no icon IDs.
  2491.  
  2492.     mOffIconID = kNoIconID;
  2493.     mOnIconID = kNoIconID;
  2494.     mFrameType = kAutoFrame;
  2495.     mImageType = kAutoIconFamily;
  2496.     }
  2497.  
  2498. MIconButtonObject::MIconButtonObject(SInt16 offIconID, SInt16 onIconID, ButtonFrameType frameType, ButtonImageType imageType)
  2499.     {
  2500.     // Construct with specified icon IDs.
  2501.  
  2502.     mOffIconID = offIconID;
  2503.     mOnIconID = onIconID;
  2504.     mFrameType = frameType;
  2505.     mImageType = imageType;
  2506.     }
  2507.  
  2508. MIconButtonObject::~MIconButtonObject()
  2509.     {
  2510.     }
  2511.  
  2512. void MIconButtonObject::SetIconIDs(SInt16 offIconID, SInt16 onIconID)
  2513.     {
  2514.     // Set icon IDs as specified.
  2515.  
  2516.     mOffIconID = offIconID;
  2517.     mOnIconID = onIconID;
  2518.     }
  2519.  
  2520. void MIconButtonObject::SetFrameType(ButtonFrameType frameType)
  2521.     {
  2522.     // Set button frame type as specified.
  2523.  
  2524.     mFrameType = frameType;
  2525.     }
  2526.  
  2527. void MIconButtonObject::SetImageType(ButtonImageType imageType)
  2528.     {
  2529.     // Set buttom image type as specified.
  2530.  
  2531.     mImageType = imageType;
  2532.     }
  2533.  
  2534. void MIconButtonObject::DrawIconButton(Rect* bounds,
  2535.                                         Boolean isOn,
  2536.                                         Boolean isPressed,
  2537.                                         Boolean isEnabled,
  2538.                                         Boolean deep)
  2539.     {
  2540.     // Draw the icon button in the appropriate state.
  2541.  
  2542.     Rect    r = *bounds;
  2543.     
  2544.     //
  2545.     // Draw the blank button with the appropriate frame type.
  2546.     //
  2547.  
  2548.     ButtonFrameType    frameType = mFrameType;
  2549.     
  2550.     if (frameType == kAutoFrame)
  2551.         frameType = MIconButtonObject::GetDefaultFrameType(r.right - r.left);
  2552.  
  2553.     if (deep)
  2554.         {
  2555.         if (frameType == kMiniFrame)
  2556.             this->DrawMiniEdges(bounds, isOn, isPressed, isEnabled);
  2557.         else if (frameType == kSmallFrame)
  2558.             this->DrawSmallEdges(bounds, isOn, isPressed, isEnabled);
  2559.         else
  2560.             this->DrawLargeEdges(bounds, isOn, isPressed, isEnabled);
  2561.         }
  2562.     else
  2563.         {
  2564.         if (isPressed || isOn)
  2565.             ::RGBForeColor(&gAGARamp[rB]);
  2566.         else
  2567.             ::RGBForeColor(&gAGARamp[rW]);
  2568.  
  2569.         ::PaintRect(&r);
  2570.         
  2571.         if (! isEnabled)
  2572.             ::PenPat(&qd.gray);
  2573.  
  2574.         ::RGBForeColor(&gAGARamp[rB]);
  2575.         ::FrameRect(&r);
  2576.         ::PenNormal();
  2577.         }
  2578.  
  2579.     //
  2580.     // Determine the target area into which the image must
  2581.     // be drawn.
  2582.     //
  2583.  
  2584.     ButtonImageType    imageType = mImageType;
  2585.     Point            imageSize;
  2586.     Point            imageCenter;
  2587.     SInt16            imageResourceID = isOn ? mOnIconID : mOffIconID;
  2588.     PicHandle        pictureHandle;
  2589.     CIconHandle        colorIconHandle;
  2590.     
  2591.     imageCenter.h = r.left + ((r.right - r.left) / 2);
  2592.     imageCenter.v = r.top + ((r.bottom - r.top) / 2);
  2593.     
  2594.     if (imageType == kAutoIconFamily)
  2595.         imageType = MIconButtonObject::GetDefaultImageType(r.right - r.left);
  2596.  
  2597.     switch (imageType)
  2598.         {
  2599.         case kPictureIcon:
  2600.             pictureHandle = this->GetPictureImage(&imageSize, imageResourceID);
  2601.             break;
  2602.  
  2603.         case kColorIcon:
  2604.             colorIconHandle = this->GetColorIconImage(&imageSize, imageResourceID);
  2605.             break;
  2606.  
  2607.         case kMiniIcon:
  2608.             ::SetPt(&imageSize, 12, 12);    // 12x12 icm#
  2609.             break;
  2610.  
  2611.         case kSmallIcon:
  2612.             ::SetPt(&imageSize, 16, 16);    // 16x16 ics#
  2613.             break;
  2614.  
  2615.         case kLargeIcon:
  2616.         default:
  2617.             ::SetPt(&imageSize, 32, 32);    // 32x32 icl#
  2618.             break;
  2619.         }
  2620.     
  2621.     r.left = imageCenter.h - (imageSize.h / 2);
  2622.     r.right = r.left + imageSize.h;
  2623.     r.top = imageCenter.v - (imageSize.v / 2);
  2624.     r.bottom = r.top + imageSize.v;
  2625.  
  2626.     //
  2627.     // Draw the image onto the blank button.
  2628.     //
  2629.  
  2630.     IconTransformType    aTransform = isPressed ? ttSelected : (isEnabled ? ttNone : ttDisabled);
  2631.  
  2632.     if (imageResourceID != kNoIconID)
  2633.         {
  2634.         ::RGBForeColor(&gAGARamp[rB]);
  2635.  
  2636.         switch (imageType)
  2637.             {
  2638.             case kPictureIcon:
  2639.                 if (pictureHandle != NULL)
  2640.                     {
  2641.                     ::DrawPicture(pictureHandle, &r);
  2642.                     // The PicHandle is not explicitly released. Just let it get purged as needed.
  2643.                     }
  2644.                 break;
  2645.  
  2646.             case kColorIcon:
  2647.                 if (colorIconHandle != NULL)
  2648.                     {
  2649.                     (void) ::PlotCIconHandle(&r, atNone, aTransform, colorIconHandle);
  2650.                     ::DisposeCIcon(colorIconHandle);
  2651.                     }
  2652.                 break;
  2653.  
  2654.             case kMiniIcon:
  2655.             case kSmallIcon:
  2656.             case kLargeIcon:
  2657.             default:
  2658.                 (void) ::PlotIconID(&r, atNone, aTransform, imageResourceID);
  2659.                 break;
  2660.             }
  2661.         }
  2662.     }
  2663.  
  2664. void MIconButtonObject::DrawMiniEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled)
  2665.     {
  2666.     // Draw the button edges as specified for a
  2667.     // "mini" sized button.
  2668.  
  2669.     enum { TLFrame, TLInner, BRFrame, BRInner, CornerFrame, CornerInner, Fill, kNumEdgeColors };
  2670.  
  2671.     UInt8    colorIndexes[kNumEdgeColors];
  2672.  
  2673.     Rect    r = *bounds;
  2674.     
  2675.     if (isPressed)
  2676.         {
  2677.         colorIndexes[TLFrame] = rA2;
  2678.         colorIndexes[BRFrame] = r11;
  2679.         colorIndexes[CornerFrame] = r12;
  2680.         colorIndexes[TLInner] = r10;
  2681.         colorIndexes[BRInner] = r5;
  2682.         colorIndexes[CornerInner] = r8;
  2683.         colorIndexes[Fill] = r7;
  2684.         }
  2685.     else if (isEnabled)
  2686.         {
  2687.         colorIndexes[TLFrame] = isOn ? rA2 : r9;
  2688.         colorIndexes[BRFrame] = isOn ? r11 : rA1;
  2689.         colorIndexes[CornerFrame] = isOn ? r12 : r10;
  2690.         colorIndexes[TLInner] = isOn ? r10 : rW;
  2691.         colorIndexes[BRInner] = isOn ? r5 : r7;
  2692.         colorIndexes[CornerInner] = isOn ? r8 : r3;
  2693.         colorIndexes[Fill] = isOn ? r7 : r3;
  2694.         }
  2695.     else    // disabled
  2696.         {
  2697.         colorIndexes[TLFrame] = isOn ? r8 : r5;
  2698.         colorIndexes[BRFrame] = r6;
  2699.         colorIndexes[CornerFrame] = isOn ? r7 : r5;
  2700.         colorIndexes[TLInner] = isOn ? r4 : r2;
  2701.         colorIndexes[BRInner] = isOn ? r4 : r2;
  2702.         colorIndexes[CornerInner] = isOn ? r4 : r2;
  2703.         colorIndexes[Fill] = isOn ? r4 : r2;
  2704.         }
  2705.     
  2706.     // Draw the outer frame.
  2707.  
  2708.     ::RGBForeColor(&gAGARamp[colorIndexes[TLFrame]]);
  2709.     ::MoveTo(r.left, r.bottom - 2);
  2710.     ::LineTo(r.left, r.top);
  2711.     ::LineTo(r.right - 1, r.top);
  2712.  
  2713.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerFrame]]);
  2714.     ::Line(0, 0);
  2715.  
  2716.     ::RGBForeColor(&gAGARamp[colorIndexes[BRFrame]]);
  2717.     ::Move(0, 1);
  2718.     ::LineTo(r.right - 1, r.bottom - 1);
  2719.     ::LineTo(r.left, r.bottom - 1);
  2720.  
  2721.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerFrame]]);
  2722.     ::Line(0, 0);
  2723.  
  2724.     // Draw the 1st pixel of shading.
  2725.  
  2726.     ::RGBForeColor(&gAGARamp[colorIndexes[TLInner]]);
  2727.     ::MoveTo(r.left + 1, r.bottom - 3);
  2728.     ::LineTo(r.left + 1, r.top + 1);
  2729.     ::LineTo(r.right - 2, r.top + 1);
  2730.  
  2731.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner]]);
  2732.     ::Line(0, 0);
  2733.  
  2734.     ::RGBForeColor(&gAGARamp[colorIndexes[BRInner]]);
  2735.     ::Move(0, 1);
  2736.     ::LineTo(r.right - 2, r.bottom - 2);
  2737.     ::LineTo(r.left + 1, r.bottom - 2);
  2738.  
  2739.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner]]);
  2740.     ::Line(0, 0);
  2741.  
  2742.     // Fill the interior.
  2743.  
  2744.     ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  2745.     ::InsetRect(&r, 2, 2);
  2746.     ::PaintRect(&r);
  2747.     ::InsetRect(&r, -2, -2);
  2748.     }
  2749.  
  2750. void MIconButtonObject::DrawSmallEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled)
  2751.     {
  2752.     // Draw the button edges as specified for a
  2753.     // "small" sized button.
  2754.  
  2755.     enum { TLFrame, TLInner1, TLInner2, BRFrame, BRInner1, BRInner2, CornerFrame, CornerInner1, CornerInner2, Fill, kNumEdgeColors };
  2756.  
  2757.     UInt8    colorIndexes[kNumEdgeColors];
  2758.  
  2759.     Rect    r = *bounds;
  2760.     
  2761.     if (isPressed)
  2762.         {
  2763.         colorIndexes[TLFrame] = rA2;
  2764.         colorIndexes[BRFrame] = r11;
  2765.         colorIndexes[CornerFrame] = rA2;
  2766.         colorIndexes[TLInner1] = r11;
  2767.         colorIndexes[BRInner1] = r4;
  2768.         colorIndexes[CornerInner1] = r8;
  2769.         colorIndexes[TLInner2] = r9;
  2770.         colorIndexes[BRInner2] = r6;
  2771.         colorIndexes[CornerInner2] = r7;
  2772.         colorIndexes[Fill] = r7;
  2773.         }
  2774.     else if (isEnabled)
  2775.         {
  2776.         colorIndexes[TLFrame] = isOn ? rA2 : r9;
  2777.         colorIndexes[BRFrame] = isOn ? r11 : rA1;
  2778.         colorIndexes[CornerFrame] = isOn ? rA2 : r9;
  2779.         colorIndexes[TLInner1] = isOn ? r11 : r3;
  2780.         colorIndexes[BRInner1] = isOn ? r4 : r8;
  2781.         colorIndexes[CornerInner1] = isOn ? r8 : r5;
  2782.         colorIndexes[TLInner2] = isOn ? r9 : rW;
  2783.         colorIndexes[BRInner2] = r6;
  2784.         colorIndexes[CornerInner2] = isOn ? r7 : r3;
  2785.         colorIndexes[Fill] = isOn ? r7 : r3;
  2786.         }
  2787.     else    // disabled
  2788.         {
  2789.         colorIndexes[TLFrame] = isOn ? r8 : r5;
  2790.         colorIndexes[BRFrame] = r6;
  2791.         colorIndexes[CornerFrame] = isOn ? r8 : r5;
  2792.         colorIndexes[TLInner1] = isOn ? r4 : r2;
  2793.         colorIndexes[BRInner1] = isOn ? r4 : r2;
  2794.         colorIndexes[CornerInner1] = isOn ? r4 : r2;
  2795.         colorIndexes[TLInner2] = isOn ? r4 : r2;
  2796.         colorIndexes[BRInner2] = isOn ? r4 : r2;
  2797.         colorIndexes[CornerInner2] = isOn ? r4 : r2;
  2798.         colorIndexes[Fill] = isOn ? r4 : r2;
  2799.         }
  2800.     
  2801.     // Draw the outer frame.
  2802.  
  2803.     ::RGBForeColor(&gAGARamp[colorIndexes[TLFrame]]);
  2804.     ::MoveTo(r.left, r.bottom - 2);
  2805.     ::LineTo(r.left, r.top);
  2806.     ::LineTo(r.right - 1, r.top);
  2807.  
  2808.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerFrame]]);
  2809.     ::Line(0, 0);
  2810.  
  2811.     ::RGBForeColor(&gAGARamp[colorIndexes[BRFrame]]);
  2812.     ::Move(0, 1);
  2813.     ::LineTo(r.right - 1, r.bottom - 1);
  2814.     ::LineTo(r.left, r.bottom - 1);
  2815.  
  2816.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerFrame]]);
  2817.     ::Line(0, 0);
  2818.  
  2819.     // Draw the 1st pixel of shading.
  2820.  
  2821.     ::RGBForeColor(&gAGARamp[colorIndexes[TLInner1]]);
  2822.     ::MoveTo(r.left + 1, r.bottom - 3);
  2823.     ::LineTo(r.left + 1, r.top + 1);
  2824.     ::LineTo(r.right - 2, r.top + 1);
  2825.  
  2826.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner1]]);
  2827.     ::Line(0, 0);
  2828.  
  2829.     ::RGBForeColor(&gAGARamp[colorIndexes[BRInner1]]);
  2830.     ::Move(0, 1);
  2831.     ::LineTo(r.right - 2, r.bottom - 2);
  2832.     ::LineTo(r.left + 1, r.bottom - 2);
  2833.  
  2834.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner1]]);
  2835.     ::Line(0, 0);
  2836.  
  2837.     // Draw the 2nd pixel of shading.
  2838.  
  2839.     ::RGBForeColor(&gAGARamp[colorIndexes[TLInner2]]);
  2840.     ::MoveTo(r.left + 2, r.bottom - 4);
  2841.     ::LineTo(r.left + 2, r.top + 2);
  2842.     ::LineTo(r.right - 3, r.top + 2);
  2843.  
  2844.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner2]]);
  2845.     ::Line(0, 0);
  2846.  
  2847.     ::RGBForeColor(&gAGARamp[colorIndexes[BRInner2]]);
  2848.     ::Move(0, 1);
  2849.     ::LineTo(r.right - 3, r.bottom - 3);
  2850.     ::LineTo(r.left + 2, r.bottom - 3);
  2851.  
  2852.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner2]]);
  2853.     ::Line(0, 0);
  2854.  
  2855.     // Fill the interior.
  2856.  
  2857.     ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  2858.     ::InsetRect(&r, 3, 3);
  2859.     ::PaintRect(&r);
  2860.     ::InsetRect(&r, -3, -3);
  2861.     }
  2862.  
  2863. void MIconButtonObject::DrawLargeEdges(Rect* bounds, Boolean isOn, Boolean isPressed, Boolean isEnabled)
  2864.     {
  2865.     // Draw the button edges as specified for a
  2866.     // "large" sized button.
  2867.  
  2868.     enum { TLFrame, TLInner1, TLInner2, TLInner3, BRFrame, BRInner1, BRInner2, BRInner3, CornerFrame, CornerInner1, CornerInner2, CornerInner3, Fill, kNumEdgeColors };
  2869.  
  2870.     UInt8    colorIndexes[kNumEdgeColors];
  2871.  
  2872.     Rect    r = *bounds;
  2873.     
  2874.     if (isPressed)
  2875.         {
  2876.         colorIndexes[TLFrame] = rA2;
  2877.         colorIndexes[BRFrame] = r11;
  2878.         colorIndexes[CornerFrame] = r12;
  2879.         colorIndexes[TLInner1] = rA1;
  2880.         colorIndexes[BRInner1] = r4;
  2881.         colorIndexes[CornerInner1] = r11;
  2882.         colorIndexes[TLInner2] = r11;
  2883.         colorIndexes[BRInner2] = r5;
  2884.         colorIndexes[CornerInner2] = r8;
  2885.         colorIndexes[TLInner3] = r9;
  2886.         colorIndexes[BRInner3] = r6;
  2887.         colorIndexes[CornerInner3] = r7;
  2888.         colorIndexes[Fill] = r7;
  2889.         }
  2890.     else if (isEnabled)
  2891.         {
  2892.         colorIndexes[TLFrame] = isOn ? rA2 : r9;
  2893.         colorIndexes[BRFrame] = isOn ? r11 : rA1;
  2894.         colorIndexes[CornerFrame] = isOn ? r12 : r10;
  2895.         colorIndexes[TLInner1] = isOn ? rA1 : r3;
  2896.         colorIndexes[BRInner1] = isOn ? r4 : r10;
  2897.         colorIndexes[CornerInner1] = isOn ? r11 : r5;
  2898.         colorIndexes[TLInner2] = isOn ? r11 : r1;
  2899.         colorIndexes[BRInner2] = isOn ? r5 : r8;
  2900.         colorIndexes[CornerInner2] = isOn ? r8 : r4;
  2901.         colorIndexes[TLInner3] = isOn ? r9 : rW;
  2902.         colorIndexes[BRInner3] = r6;
  2903.         colorIndexes[CornerInner3] = isOn ? r7 : r3;
  2904.         colorIndexes[Fill] = isOn ? r7 : r3;
  2905.         }
  2906.     else    // disabled
  2907.         {
  2908.         colorIndexes[TLFrame] = isOn ? r8 : r5;
  2909.         colorIndexes[BRFrame] = isOn ? r6 : r7;
  2910.         colorIndexes[CornerFrame] = isOn ? r7 : r6;
  2911.         colorIndexes[TLInner1] = isOn ? r4 : r2;
  2912.         colorIndexes[BRInner1] = isOn ? r4 : r2;
  2913.         colorIndexes[CornerInner1] = isOn ? r4 : r2;
  2914.         colorIndexes[TLInner2] = isOn ? r4 : r2;
  2915.         colorIndexes[BRInner2] = isOn ? r4 : r2;
  2916.         colorIndexes[CornerInner2] = isOn ? r4 : r2;
  2917.         colorIndexes[TLInner3] = isOn ? r4 : r2;
  2918.         colorIndexes[BRInner3] = isOn ? r4 : r2;
  2919.         colorIndexes[CornerInner3] = isOn ? r4 : r2;
  2920.         colorIndexes[Fill] = isOn ? r4 : r2;
  2921.         }
  2922.     
  2923.     // Draw the outer frame.
  2924.  
  2925.     ::RGBForeColor(&gAGARamp[colorIndexes[TLFrame]]);
  2926.     ::MoveTo(r.left, r.bottom - 2);
  2927.     ::LineTo(r.left, r.top);
  2928.     ::LineTo(r.right - 1, r.top);
  2929.  
  2930.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerFrame]]);
  2931.     ::Line(0, 0);
  2932.  
  2933.     ::RGBForeColor(&gAGARamp[colorIndexes[BRFrame]]);
  2934.     ::Move(0, 1);
  2935.     ::LineTo(r.right - 1, r.bottom - 1);
  2936.     ::LineTo(r.left, r.bottom - 1);
  2937.  
  2938.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerFrame]]);
  2939.     ::Line(0, 0);
  2940.  
  2941.     // Draw the 1st pixel of shading.
  2942.  
  2943.     ::RGBForeColor(&gAGARamp[colorIndexes[TLInner1]]);
  2944.     ::MoveTo(r.left + 1, r.bottom - 3);
  2945.     ::LineTo(r.left + 1, r.top + 1);
  2946.     ::LineTo(r.right - 2, r.top + 1);
  2947.  
  2948.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner1]]);
  2949.     ::Line(0, 0);
  2950.  
  2951.     ::RGBForeColor(&gAGARamp[colorIndexes[BRInner1]]);
  2952.     ::Move(0, 1);
  2953.     ::LineTo(r.right - 2, r.bottom - 2);
  2954.     ::LineTo(r.left + 1, r.bottom - 2);
  2955.  
  2956.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner1]]);
  2957.     ::Line(0, 0);
  2958.  
  2959.     // Draw the 2nd pixel of shading.
  2960.  
  2961.     ::RGBForeColor(&gAGARamp[colorIndexes[TLInner2]]);
  2962.     ::MoveTo(r.left + 2, r.bottom - 4);
  2963.     ::LineTo(r.left + 2, r.top + 2);
  2964.     ::LineTo(r.right - 3, r.top + 2);
  2965.  
  2966.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner2]]);
  2967.     ::Line(0, 0);
  2968.  
  2969.     ::RGBForeColor(&gAGARamp[colorIndexes[BRInner2]]);
  2970.     ::Move(0, 1);
  2971.     ::LineTo(r.right - 3, r.bottom - 3);
  2972.     ::LineTo(r.left + 2, r.bottom - 3);
  2973.  
  2974.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner2]]);
  2975.     ::Line(0, 0);
  2976.  
  2977.     // Draw the 3rd pixel of shading.
  2978.  
  2979.     ::RGBForeColor(&gAGARamp[colorIndexes[TLInner3]]);
  2980.     ::MoveTo(r.left + 3, r.bottom - 5);
  2981.     ::LineTo(r.left + 3, r.top + 3);
  2982.     ::LineTo(r.right - 4, r.top + 3);
  2983.  
  2984.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner3]]);
  2985.     ::Line(0, 0);
  2986.  
  2987.     ::RGBForeColor(&gAGARamp[colorIndexes[BRInner3]]);
  2988.     ::Move(0, 1);
  2989.     ::LineTo(r.right - 4, r.bottom - 4);
  2990.     ::LineTo(r.left + 3, r.bottom - 4);
  2991.  
  2992.     ::RGBForeColor(&gAGARamp[colorIndexes[CornerInner3]]);
  2993.     ::Line(0, 0);
  2994.  
  2995.     // Fill the interior.
  2996.  
  2997.     ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  2998.     ::InsetRect(&r, 4, 4);
  2999.     ::PaintRect(&r);
  3000.     ::InsetRect(&r, -4, -4);
  3001.     }
  3002.  
  3003. PicHandle MIconButtonObject::GetPictureImage(Point* imageSize, SInt16 pictureResourceID)
  3004.     {
  3005.     PicHandle    pictureHandle = ::GetPicture(pictureResourceID);
  3006.                     
  3007.     if (pictureHandle != NULL)
  3008.         {
  3009.         Rect    frame = (**pictureHandle).picFrame;
  3010.  
  3011.         ::SetPt(imageSize, frame.right - frame.left, frame.bottom - frame.top);
  3012.         }
  3013.  
  3014.     return pictureHandle;
  3015.     }
  3016.  
  3017. CIconHandle MIconButtonObject::GetColorIconImage(Point* imageSize, SInt16 cicnResourceID)
  3018.     {
  3019.     CIconHandle    colorIconHandle = ::GetCIcon(cicnResourceID);
  3020.                     
  3021.     if (colorIconHandle != NULL)
  3022.         {
  3023.         Rect    frame = (**colorIconHandle).iconBMap.bounds;
  3024.  
  3025.         ::SetPt(imageSize, frame.right - frame.left, frame.bottom - frame.top);
  3026.         }
  3027.  
  3028.     return colorIconHandle;
  3029.     }
  3030.  
  3031. MIconButtonObject::ButtonFrameType MIconButtonObject::GetDefaultFrameType(SInt16 buttonWidth)
  3032.     {
  3033.     if (buttonWidth > 39)
  3034.         return kLargeFrame;
  3035.     else if (buttonWidth > 21)
  3036.         return kSmallFrame;
  3037.     else
  3038.         return kMiniFrame;
  3039.     }
  3040.  
  3041. MIconButtonObject::ButtonImageType MIconButtonObject::GetDefaultImageType(SInt16 buttonWidth)
  3042.     {
  3043.     if (buttonWidth > 39)
  3044.         return kLargeIcon;
  3045.     else if (buttonWidth > 21)
  3046.         return kSmallIcon;
  3047.     else
  3048.         return kMiniIcon;
  3049.     }
  3050.  
  3051. //
  3052. // AGAIconPushButton ---------------------------------------------------------------
  3053. //
  3054. // This class implements an icon-based pushbutton object, such as
  3055. // a toolbar icon command button.
  3056. //
  3057.  
  3058. AGAIconPushButton::AGAIconPushButton(Rect* bounds)
  3059. : AGAPushButton(bounds, gAGAStdSystemStyle), MIconButtonObject()
  3060.     {
  3061.     // Just call through to mixed in constructors.
  3062.     }
  3063.  
  3064. AGAIconPushButton::AGAIconPushButton(Rect* bounds, SInt16 iconID, ButtonFrameType frameType, ButtonImageType imageType)
  3065. : AGAPushButton(bounds, gAGAStdSystemStyle), MIconButtonObject(iconID, iconID, frameType, imageType)
  3066.     {
  3067.     // Just call through to mixed in constructors.
  3068.     }
  3069.  
  3070. AGAIconPushButton::~AGAIconPushButton()
  3071.     {
  3072.     }
  3073.  
  3074. void AGAIconPushButton::DrawButtonNormal(Boolean deep)
  3075.     {
  3076.     // Call icon button parent class with appropriate parameters.
  3077.  
  3078.     MIconButtonObject::DrawIconButton(&mBounds, false, kNotPressed, kEnabled, deep);
  3079.     }
  3080.  
  3081. void AGAIconPushButton::DrawButtonPressed(Boolean deep)
  3082.     {
  3083.     // Call icon button parent class with appropriate parameters.
  3084.  
  3085.     MIconButtonObject::DrawIconButton(&mBounds, false, kPressed, kEnabled, deep);
  3086.     }
  3087.  
  3088. void AGAIconPushButton::DrawButtonDisabled(Boolean deep)
  3089.     {
  3090.     // Call icon button parent class with appropriate parameters.
  3091.  
  3092.     MIconButtonObject::DrawIconButton(&mBounds, false, kNotPressed, kDisabled, deep);
  3093.     }
  3094.  
  3095. //
  3096. // AGAIconCheckBox ---------------------------------------------------------------
  3097. //
  3098. // This class implements an icon-based checkbox object, such as
  3099. // a toolbar icon on/off button.
  3100. //
  3101.  
  3102. AGAIconCheckBox::AGAIconCheckBox(Rect* bounds, Boolean automaticState)
  3103. : AGACheckBox(bounds, gAGAStdSystemStyle, automaticState), MIconButtonObject()
  3104.     {
  3105.     // Just call through to mixed in constructors.
  3106.     }
  3107.  
  3108. AGAIconCheckBox::AGAIconCheckBox(Rect* bounds, Boolean automaticState, SInt16 offIconID, SInt16 onIconID, ButtonFrameType frameType, ButtonImageType imageType)
  3109. : AGACheckBox(bounds, gAGAStdSystemStyle, automaticState), MIconButtonObject(offIconID, onIconID, frameType, imageType)
  3110.     {
  3111.     // Just call through to mixed in constructors.
  3112.     }
  3113.  
  3114. AGAIconCheckBox::~AGAIconCheckBox()
  3115.     {
  3116.     }
  3117.  
  3118. void AGAIconCheckBox::DrawButtonNormal(Boolean deep)
  3119.     {
  3120.     // Call icon button parent class with appropriate parameters.
  3121.  
  3122.     MIconButtonObject::DrawIconButton(&mBounds, mValue != kCheckBoxOff, kNotPressed, kEnabled, deep);
  3123.     }
  3124.  
  3125. void AGAIconCheckBox::DrawButtonPressed(Boolean deep)
  3126.     {
  3127.     // Call icon button parent class with appropriate parameters.
  3128.  
  3129.     MIconButtonObject::DrawIconButton(&mBounds, mValue != kCheckBoxOff, kPressed, kEnabled, deep);
  3130.     }
  3131.  
  3132. void AGAIconCheckBox::DrawButtonDisabled(Boolean deep)
  3133.     {
  3134.     // Call icon button parent class with appropriate parameters.
  3135.  
  3136.     MIconButtonObject::DrawIconButton(&mBounds, mValue != kCheckBoxOff, kNotPressed, kDisabled, deep);
  3137.     }
  3138.  
  3139. //
  3140. // AGAIconRadioButton ---------------------------------------------------------------
  3141. //
  3142. // This class implements an icon-based pushbutton object, such as
  3143. // a toolbar icon XOR group member button.
  3144. //
  3145.  
  3146. AGAIconRadioButton::AGAIconRadioButton(Rect* bounds, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState)
  3147. : AGARadioButton(bounds, gAGAStdSystemStyle, groupIDPart1, groupIDPart2, automaticState), MIconButtonObject()
  3148.     {
  3149.     // Just call through to mixed in constructors.
  3150.     }
  3151.  
  3152. AGAIconRadioButton::AGAIconRadioButton(Rect* bounds, UInt32 groupIDPart1, UInt32 groupIDPart2, Boolean automaticState, SInt16 offIconID, SInt16 onIconID, ButtonFrameType frameType, ButtonImageType imageType)
  3153. : AGARadioButton(bounds, gAGAStdSystemStyle, groupIDPart1, groupIDPart2, automaticState), MIconButtonObject(offIconID, onIconID, frameType, imageType)
  3154.     {
  3155.     // Just call through to mixed in constructors.
  3156.     }
  3157.  
  3158. AGAIconRadioButton::~AGAIconRadioButton()
  3159.     {
  3160.     }
  3161.  
  3162. void AGAIconRadioButton::DrawButtonNormal(Boolean deep)
  3163.     {
  3164.     // Call icon button parent class with appropriate parameters.
  3165.  
  3166.     MIconButtonObject::DrawIconButton(&mBounds, mValue != kRadioButtonOff, kNotPressed, kEnabled, deep);
  3167.     }
  3168.  
  3169. void AGAIconRadioButton::DrawButtonPressed(Boolean deep)
  3170.     {
  3171.     // Call icon button parent class with appropriate parameters.
  3172.  
  3173.     MIconButtonObject::DrawIconButton(&mBounds, mValue != kRadioButtonOff, kPressed, kEnabled, deep);
  3174.     }
  3175.  
  3176. void AGAIconRadioButton::DrawButtonDisabled(Boolean deep)
  3177.     {
  3178.     // Call icon button parent class with appropriate parameters.
  3179.  
  3180.     MIconButtonObject::DrawIconButton(&mBounds, mValue != kRadioButtonOff, kNotPressed, kDisabled, deep);
  3181.     }
  3182.  
  3183. //
  3184. // AGATrackingIndicator ---------------------------------------------------------------
  3185. //
  3186. // This is the abstract superclass for scroll bars and sliders.
  3187. // They all have a range, and a value shown by a draggable indicator.
  3188. //
  3189.  
  3190. #pragma segment GrayCouncilCore2
  3191.  
  3192. AGATrackingIndicator::AGATrackingIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue)
  3193.     : AGAObject(bounds)
  3194.     {
  3195.     // Construct with default options.
  3196.  
  3197.     mMinimum = minimum;
  3198.     mMaximum = maximum;
  3199.     mValue = initialValue;
  3200.     
  3201.     mPageSize = 1;
  3202.     mGhostValue = mValue;
  3203.     mLiveTracking = false;
  3204.     mIsProportional = false;
  3205.     mIsHorizontal = (bounds->right - bounds->left) > (bounds->bottom - bounds->top);
  3206.     mIsPressed = false;
  3207.     
  3208.     mNotificationRoutine = NULL;
  3209.     }
  3210.  
  3211. AGATrackingIndicator::AGATrackingIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, SInt32 pageSize, Boolean liveTracking, Boolean proportional)
  3212.     : AGAObject(bounds)
  3213.     {
  3214.     // Construct with specified options.
  3215.  
  3216.     mMinimum = minimum;
  3217.     mMaximum = maximum;
  3218.     mValue = initialValue;
  3219.     mPageSize = pageSize;
  3220.     mGhostValue = mValue;
  3221.     mLiveTracking = liveTracking;
  3222.     mIsProportional = proportional;
  3223.     mIsHorizontal = (bounds->right - bounds->left) > (bounds->bottom - bounds->top);
  3224.     mIsPressed = false;
  3225.     
  3226.     mNotificationRoutine = NULL;
  3227.     }
  3228.  
  3229. AGATrackingIndicator::~AGATrackingIndicator()
  3230.     {
  3231.     }
  3232.  
  3233. void AGATrackingIndicator::InstallNotificationRoutine(AGATrackingIndicatorNotifyPtr notificationRoutine, void* userData)
  3234.     {
  3235.     // Install the supplied function pointer and user data to
  3236.     // be called during notification.
  3237.  
  3238.     mNotificationRoutine = notificationRoutine;
  3239.     mUserData = userData;
  3240.     }
  3241.  
  3242. void AGATrackingIndicator::SetAttributes(Boolean isHorizontal, Boolean liveTracking, Boolean isProportional)
  3243.     {
  3244.     // Set options as specified.
  3245.  
  3246.     mIsHorizontal = isHorizontal;
  3247.     mLiveTracking = liveTracking;
  3248.     mIsProportional = isProportional;
  3249.     }
  3250.  
  3251. void AGATrackingIndicator::SetLiveTracking(Boolean liveTracking)
  3252.     {
  3253.     // Turn live tracking on or off.
  3254.  
  3255.     mLiveTracking = liveTracking;
  3256.     }
  3257.  
  3258. void AGATrackingIndicator::DrawObject()
  3259.     {
  3260.     // Call component drawing functions. These are all overridden
  3261.     // by subclasses.
  3262.  
  3263.     this->DrawBackground();
  3264.     this->DrawIndicatorTrack();
  3265.     this->DrawTrackEnds();
  3266.     this->DrawIndicator();
  3267.     }
  3268.  
  3269. Boolean AGATrackingIndicator::TrackMouse(Point mouseLocation)
  3270.     {
  3271.     if (! mEnabled)
  3272.         return false;
  3273.  
  3274.     // Track the mouse and return true if the indicator
  3275.     // value was changed.
  3276.  
  3277.     return this->TrackPart(mouseLocation, this->TrackTestPart(mouseLocation));
  3278.     }
  3279.  
  3280. Boolean AGATrackingIndicator::TrackPart(Point mouseLocation, SInt32 partHit)
  3281.     {
  3282.     // Track the mouse in the specified part and return true
  3283.     // if the indicator value was changed.
  3284.  
  3285.     if (partHit != kIndicatorPress)
  3286.         return false;
  3287.  
  3288.     SInt32    originalValue = mValue;
  3289.     Point    oldPoint = mouseLocation;
  3290.     Point    newPoint = mouseLocation;
  3291.     SInt32    oldValue = originalValue;
  3292.     SInt32    newValue = originalValue;
  3293.     Boolean    isButtonDown = true;    // ensure at least one time through
  3294.     
  3295.     mGhostValue = mValue;
  3296.     mIsPressed = true;
  3297.     this->DrawIndicator();    // will draw it pressed
  3298.     
  3299.     while (isButtonDown)
  3300.         {
  3301.         ::GetMouse(&newPoint);    // gives local coordinates
  3302.         
  3303.         if (this->IsValidIndicatorTrackMouse(newPoint) &&
  3304.             ! ::EqualPt(newPoint, oldPoint))
  3305.             {
  3306.             newValue = this->GetValueFromMouseDelta(oldValue, mouseLocation, newPoint);
  3307.         
  3308.             if (mLiveTracking)
  3309.                 {
  3310.                 SInt32    oldValue = mValue;
  3311.  
  3312.                 this->SetValue(newValue, kRedraw);
  3313.                 
  3314.                 if (mValue != oldValue)
  3315.                     this->NotifyValue();
  3316.                 }
  3317.             else
  3318.                 this->SetGhostValue(newValue, kRedraw);
  3319.             
  3320.             oldPoint = newPoint;
  3321.             }
  3322.         
  3323.         isButtonDown = ::StillDown();
  3324.         }
  3325.     
  3326.     mIsPressed = false;
  3327.     
  3328.     if (mLiveTracking)
  3329.         this->DrawIndicator();    // unpressed
  3330.     else
  3331.         {
  3332.         this->RemoveGhost(newValue);
  3333.         this->DrawIndicator();    // unpressed
  3334.  
  3335.         if (newValue != mValue)    // don't notify if no change
  3336.             {
  3337.             this->SetValue(newValue, kRedraw);    // will draw new indicator
  3338.             this->NotifyValue();
  3339.             }
  3340.         }
  3341.     
  3342.     return (mValue != originalValue);
  3343.     }
  3344.  
  3345. SInt32 AGATrackingIndicator::GetValue()
  3346.     {
  3347.     // Return the current indicator value.
  3348.  
  3349.     return mValue;
  3350.     }
  3351.  
  3352. void AGATrackingIndicator::SetGhostValue(SInt32 newValue, Boolean redraw)
  3353.     {
  3354.     // Set the ghost indicator value, and optionally redraw it
  3355.     // at its new position.
  3356.  
  3357.     if (newValue > mMaximum)
  3358.         newValue = mMaximum;
  3359.     else if (newValue < mMinimum)
  3360.         newValue = mMinimum;
  3361.  
  3362.     if (newValue != mGhostValue)
  3363.         {
  3364.         if (redraw)
  3365.             this->RemoveGhost(newValue);
  3366.  
  3367.         mGhostValue = newValue;
  3368.         
  3369.         if (redraw)
  3370.             this->DrawGhost();
  3371.         }
  3372.     }
  3373.  
  3374. void AGATrackingIndicator::SetValue(SInt32 newValue, Boolean redraw)
  3375.     {
  3376.     // Set the indicator value, and optionally redraw it
  3377.     // at its new position.
  3378.  
  3379.     if (newValue > mMaximum)
  3380.         newValue = mMaximum;
  3381.     else if (newValue < mMinimum)
  3382.         newValue = mMinimum;
  3383.  
  3384.     if (newValue != mValue)
  3385.         {
  3386.         if (redraw)
  3387.             this->RemoveIndicator(newValue);
  3388.  
  3389.         mValue = newValue;
  3390.         
  3391.         if (redraw)
  3392.             this->DrawIndicator();
  3393.         }
  3394.     }
  3395.  
  3396. void AGATrackingIndicator::GetRange(SInt32* minimum, SInt32* maximum)
  3397.     {
  3398.     // Return the current min/max range.
  3399.  
  3400.     *minimum = mMinimum;
  3401.     *maximum = mMaximum;
  3402.     }
  3403.  
  3404. void AGATrackingIndicator::SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw)
  3405.     {
  3406.     // Set the min/max range, and optionally redraw.
  3407.  
  3408.     if ((newMinimum != mMinimum) ||
  3409.         (newMaximum != mMaximum))
  3410.         {
  3411.         if (redraw)
  3412.             this->RemoveIndicator(mValue);
  3413.  
  3414.         mMinimum = newMinimum;
  3415.         mMaximum = newMaximum;
  3416.         
  3417.         mValue = MaxSInt32(mMinimum, MinSInt32(mValue, mMaximum));
  3418.  
  3419.         if (redraw)
  3420.             this->DrawIndicator();
  3421.         }
  3422.     }
  3423.  
  3424. SInt32 AGATrackingIndicator::GetPageSize()
  3425.     {
  3426.     // Return the current indicator page size.
  3427.  
  3428.     return mPageSize;
  3429.     }
  3430.  
  3431. void AGATrackingIndicator::SetPageSize(SInt32 newPageSize, Boolean redraw)
  3432.     {
  3433.     // Set the indicator page size. Redraw is not
  3434.     // necessary if the indicator is not proportional.
  3435.  
  3436.     if (newPageSize != mPageSize)
  3437.         {
  3438.         if (redraw && mIsProportional)
  3439.             this->RemoveIndicator(mValue);
  3440.  
  3441.         mPageSize = newPageSize;
  3442.         
  3443.         if (redraw && mIsProportional)
  3444.             this->DrawIndicator();
  3445.         }
  3446.     }
  3447.  
  3448. SInt32 AGATrackingIndicator::TrackTestPart(Point /*mouseLocation*/)
  3449.     {
  3450.     // Must be overridden. Return the part value that the
  3451.     // specified mouse position would hit.
  3452.  
  3453.     return kNoTrackPress;
  3454.     }
  3455.  
  3456. Boolean AGATrackingIndicator::IsValidIndicatorTrackMouse(Point mouseLocation)
  3457.     {
  3458.     // Usually overridden. Return true if the specified mouse
  3459.     // position should be considered "in" for tracking purposes
  3460.     // after the initial hit has succeeded. Return false if the
  3461.     // specified mouse position is too far away from the control
  3462.     // to use it for the next momentary tracking position.
  3463.  
  3464.     return ::PtInRect(mouseLocation, &mBounds);
  3465.     }
  3466.  
  3467. SInt32 AGATrackingIndicator::GetValueFromMouseDelta(SInt32 originalValue, Point /*originalMouseLocation*/, Point /*newMouseLocation*/)
  3468.     {
  3469.     // Must be overridden. Return the indicator value that should be
  3470.     // applied assuming the supplied starting value and mouse hit point,
  3471.     // and the supplied current mouse tracking location.
  3472.     return originalValue;
  3473.     }
  3474.  
  3475. void AGATrackingIndicator::DrawBackground()
  3476.     {
  3477.     // Override to paint the background area so that the
  3478.     // indicator drawn at its old position will be wiped out.
  3479.     // Clipping will be already set up to avoid excess flicker.
  3480.     }
  3481.  
  3482. void AGATrackingIndicator::DrawIndicatorTrack()
  3483.     {
  3484.     // Override to draw the empty indicator track. Must include
  3485.     // all possible indicator coverage.
  3486.     }
  3487.  
  3488. void AGATrackingIndicator::DrawTrackEnds()
  3489.     {
  3490.     // Override to draw the track ends outside the possible
  3491.     // indicator coverage if not drawn in DrawIndicatorTrack.
  3492.     }
  3493.  
  3494. void AGATrackingIndicator::DrawIndicator()
  3495.     {
  3496.     // Override to draw the indicator at its current value/state.
  3497.     }
  3498.  
  3499. void AGATrackingIndicator::RemoveIndicator(SInt32 /*newValue*/)
  3500.     {
  3501.     // Override to draw/erase whatever is needed to remove the
  3502.     // current indicator in preparation for being drawn at
  3503.     // the specified new value. The new value is supplied so
  3504.     // that erasing can be kept to a minimal area.
  3505.     }
  3506.  
  3507. void AGATrackingIndicator::DrawGhost()
  3508.     {
  3509.     // Override to draw the indicator in ghost mode at
  3510.     // the current ghost value.
  3511.     }
  3512.  
  3513. void AGATrackingIndicator::RemoveGhost(SInt32 /*newValue*/)
  3514.     {
  3515.     // Override to draw/erase whatever is needed to remove the
  3516.     // ghost indicator in preparation for being drawn at
  3517.     // the specified new value. The new value is supplied so
  3518.     // that erasing can be kept to a minimal area.
  3519.     }
  3520.  
  3521. void AGATrackingIndicator::NotifyValue()
  3522.     {
  3523.     // Call the installed notification routine, if any, with
  3524.     // the installed user data and our new value.
  3525.  
  3526.     if (mNotificationRoutine != NULL)
  3527.         (*(mNotificationRoutine))(this, mValue, mUserData);
  3528.     }
  3529.  
  3530. //
  3531. // AGAScrollBar ---------------------------------------------------------------
  3532. //
  3533. // This class implements a standard AGA scroll bar, with the additional
  3534. // ability to perform live tracking and a proportional thumb.
  3535. //
  3536.  
  3537. // These regions are used momentarily while tracking the scroll
  3538. // bar indicator to clip and optimize redrawing.
  3539. RgnHandle AGAScrollBar::mgSavedIndicatorClip = ::NewRgn();
  3540. RgnHandle AGAScrollBar::mgOldIndicatorClip = ::NewRgn();
  3541. RgnHandle AGAScrollBar::mgNewIndicatorClip = ::NewRgn();
  3542.  
  3543. AGAScrollBar::AGAScrollBar(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue)
  3544.     : AGATrackingIndicator(bounds, minimum, maximum, initialValue)
  3545.     {
  3546.     // Construct with default options.
  3547.     mLiveTracking = TestGrayCouncilDefault(kAGALiveScrolling);
  3548.     mIsProportional = TestGrayCouncilDefault(kAGAProportionalScrolling);
  3549.  
  3550.     mSingleStepSize = 1;
  3551.     mPageStepSize = 1;
  3552.     mActive = true;
  3553.     }
  3554.  
  3555. AGAScrollBar::AGAScrollBar(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, SInt32 singleStepSize, SInt32 pageStepSize, SInt32 pageSize, Boolean liveTracking, Boolean proportional)
  3556.     : AGATrackingIndicator(bounds, minimum, maximum, initialValue, pageSize, liveTracking, proportional)
  3557.     {
  3558.     // Construct with specified options.
  3559.  
  3560.     mSingleStepSize = singleStepSize;
  3561.     mPageStepSize = pageStepSize;
  3562.     mActive = true;
  3563.     }
  3564.  
  3565. AGAScrollBar::~AGAScrollBar()
  3566.     {
  3567.     }
  3568.  
  3569. void AGAScrollBar::SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw)
  3570.     {
  3571.     // For scroll bars, min==max means the scroll bar is drawn disabled.
  3572.     // So we need to catch a range change that changes this implicit state
  3573.     // that is peculiar to this subclass. When this happens, we don't want
  3574.     // the normal indicator redraw to happen; rather, we want to redraw the
  3575.     // whole object in its new state.
  3576.     
  3577.     Boolean    wasEnabled = (mMaximum > mMinimum);
  3578.     Boolean    isEnabled = (newMaximum > newMinimum);
  3579.     Boolean    changedState = (isEnabled != wasEnabled);
  3580.     
  3581.     AGATrackingIndicator::SetRange(newMinimum, newMaximum, redraw && ! changedState);
  3582.  
  3583.     if (redraw && changedState)
  3584.         this->DrawObject();
  3585.     }
  3586.  
  3587. void AGAScrollBar::SetStepSizes(SInt32 singleStepSize, SInt32 pageStepSize)
  3588.     {
  3589.     // Set the scrolling step delta amounts.
  3590.  
  3591.     mSingleStepSize = singleStepSize;
  3592.     mPageStepSize = pageStepSize;
  3593.     }
  3594.  
  3595. void AGAScrollBar::Activate(Boolean activateState, Boolean redraw)
  3596.     {
  3597.     // Set the active/inactive state. Scroll bars are the
  3598.     // only control that have a different appearance when
  3599.     // in an inactive window.
  3600.  
  3601.     mActive = activateState;
  3602.     
  3603.     if (redraw)
  3604.         this->DrawObject();
  3605.     }
  3606.  
  3607. Boolean AGAScrollBar::TrackPart(Point mouseLocation, SInt32 partHit)
  3608.     {
  3609.     // Track the mouse and return true if tracking changed the
  3610.     // indicator value. Thumb tracking is handled by superclass.
  3611.     // Scroll bar just handles arrow and page tracking.
  3612.  
  3613.     if ((partHit != kArrowMinusPress) && (partHit != kArrowPlusPress) &&
  3614.         (partHit != kPageMinusPress) && (partHit != kPagePlusPress))
  3615.         return AGATrackingIndicator::TrackPart(mouseLocation, partHit);
  3616.  
  3617.     if (mMaximum <= mMinimum)    // implicitly disabled (no range)
  3618.         return false;
  3619.  
  3620.     Boolean    wasIn = false;
  3621.     Boolean    isIn = true;
  3622.     Boolean    isButtonDown = true;    // ensure at least one time through
  3623.     Point    newMouseLocation;
  3624.     UInt32    accelerationDelay = 18;    // will divide by 2 each time
  3625.     
  3626.     while (isButtonDown)
  3627.         {
  3628.         if (isIn)
  3629.             this->TrackDelta(partHit);
  3630.  
  3631.         ::GetMouse(&newMouseLocation);    // gives local coordinates
  3632.         
  3633.         isIn = (this->TrackTestPart(newMouseLocation) == partHit);
  3634.         
  3635.         if (isIn != wasIn)
  3636.             this->DrawArrow(partHit, isIn);
  3637.         
  3638.         wasIn = isIn;
  3639.  
  3640.         if (isButtonDown && (accelerationDelay != 0))
  3641.             {
  3642.             DelayFutureWhileStillDown(accelerationDelay);
  3643.             accelerationDelay = accelerationDelay >> 1;    // divide by 2
  3644.             }
  3645.  
  3646.         isButtonDown = ::StillDown();
  3647.         }
  3648.     
  3649.     if (isIn)    // if finished IN, restore normal appearance
  3650.         this->DrawArrow(partHit, kNotPressed);
  3651.     
  3652.     return true;
  3653.     }
  3654.  
  3655. SInt32 AGAScrollBar::TrackTestPart(Point mouseLocation)
  3656.     {
  3657.     // Return the part value that the specified mouse
  3658.     // position would hit.
  3659.  
  3660.     Rect    arrowMinusRect = mBounds;
  3661.     Rect    arrowPlusRect = mBounds;
  3662.     Rect    pageMinusRect = mBounds;
  3663.     Rect    pagePlusRect = mBounds;
  3664.     Rect    indicatorRect;
  3665.     
  3666.     this->GetIndicatorBox(mValue, &indicatorRect);
  3667.     
  3668.     if (mIsHorizontal)
  3669.         {
  3670.         arrowPlusRect.left = arrowPlusRect.right - kArrowSize;
  3671.         arrowMinusRect.right = arrowMinusRect.left + kArrowSize;
  3672.         
  3673.         pageMinusRect.left = arrowMinusRect.right;
  3674.         pageMinusRect.right = indicatorRect.left;
  3675.         
  3676.         pagePlusRect.left = indicatorRect.right;
  3677.         pagePlusRect.right = arrowPlusRect.left;
  3678.         }
  3679.     else
  3680.         {
  3681.         arrowPlusRect.top = arrowPlusRect.bottom - kArrowSize;
  3682.         arrowMinusRect.bottom = arrowMinusRect.top + kArrowSize;
  3683.         
  3684.         pageMinusRect.top = arrowMinusRect.bottom;
  3685.         pageMinusRect.bottom = indicatorRect.top;
  3686.         
  3687.         pagePlusRect.top = indicatorRect.bottom;
  3688.         pagePlusRect.bottom = arrowPlusRect.top;
  3689.         }
  3690.     
  3691.     if (::PtInRect(mouseLocation, &arrowMinusRect))
  3692.         return kArrowMinusPress;
  3693.     else if (::PtInRect(mouseLocation, &arrowPlusRect))
  3694.         return kArrowPlusPress;
  3695.     else if (::PtInRect(mouseLocation, &pageMinusRect))
  3696.         return kPageMinusPress;
  3697.     else if (::PtInRect(mouseLocation, &pagePlusRect))
  3698.         return kPagePlusPress;
  3699.     else if (::PtInRect(mouseLocation, &indicatorRect))
  3700.         return kIndicatorPress;
  3701.     else
  3702.         return kNoTrackPress;
  3703.     }
  3704.  
  3705. Boolean AGAScrollBar::IsValidIndicatorTrackMouse(Point mouseLocation)
  3706.     {
  3707.     // Return true if the mouse is reasonably near
  3708.     // the track.
  3709.  
  3710.     Rect    okRect = mBounds;
  3711.     
  3712.     ::InsetRect(&okRect, -32, -32);    // slop for mouse tracking
  3713.  
  3714.     return ::PtInRect(mouseLocation, &okRect);
  3715.     }
  3716.  
  3717. SInt32 AGAScrollBar::GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation)
  3718.     {
  3719.     // Return the new indicator value based on the mouse delta
  3720.     // from the original mouse location and indicator value.
  3721.  
  3722.     SInt32    dontCare;
  3723.     SInt32    valueRange = mMaximum - mMinimum;
  3724.     SInt32    pixelRange = this->GetIndicatorPixelRange(&dontCare);
  3725.     SInt32    pixelDelta;
  3726.     float    pixelFraction;
  3727.     
  3728.     if (mIsHorizontal)
  3729.         pixelDelta = newMouseLocation.h - originalMouseLocation.h;
  3730.     else
  3731.         pixelDelta = newMouseLocation.v - originalMouseLocation.v;
  3732.  
  3733.     pixelFraction = ((float) pixelDelta) / (float) pixelRange;
  3734.     
  3735.     float delta = pixelFraction * ((float) valueRange);
  3736.     delta += (float) 0.5;    // round to nearest integer, don't just truncate fraction
  3737.     
  3738.     return originalValue + delta;
  3739.     }
  3740.  
  3741. void AGAScrollBar::DrawIndicatorTrack()
  3742.     {
  3743.     AGADrawingEnvironment    env;
  3744.  
  3745.     // Draw the empty scroll bar track.
  3746.  
  3747.     GDIterator    iter;
  3748.     Boolean        deep;
  3749.  
  3750.     Boolean    enabled = mEnabled && (mMaximum > mMinimum);
  3751.  
  3752.     while (iter.More(deep))
  3753.         {
  3754.         if (deep)
  3755.             {
  3756.             Rect    r = mBounds;
  3757.  
  3758.             if (mActive)
  3759.                 ::RGBForeColor(&gAGARamp[rB]);
  3760.             else
  3761.                 ::RGBForeColor(&gAGARamp[r10]);
  3762.  
  3763.             ::FrameRect(&r);
  3764.             
  3765.             if (mIsHorizontal)
  3766.                 ::InsetRect(&r, kArrowSize - 1, 0);
  3767.             else
  3768.                 ::InsetRect(&r, 0, kArrowSize - 1);
  3769.             
  3770.             if ((! mActive) || (! enabled))
  3771.                 {
  3772.                 ::RGBForeColor(&gAGARamp[r1]);
  3773.                 ::InsetRect(&r, 1, 1);
  3774.                 ::PaintRect(&r);
  3775.                 ::InsetRect(&r, -1, -1);
  3776.                 
  3777.                 if (mActive)
  3778.                     ::RGBForeColor(&gAGARamp[r8]);
  3779.                 
  3780.                 if (mIsHorizontal)
  3781.                     {
  3782.                     ::MoveTo(r.left, r.top + 1);
  3783.                     ::LineTo(r.left, r.bottom - 2);
  3784.                     ::MoveTo(r.right - 1, r.top + 1);
  3785.                     ::LineTo(r.right - 1, r.bottom - 2);
  3786.                     }
  3787.                 else
  3788.                     {
  3789.                     ::MoveTo(r.left + 1, r.top);
  3790.                     ::LineTo(r.right - 2, r.top);
  3791.                     ::MoveTo(r.left + 1, r.bottom - 1);
  3792.                     ::LineTo(r.right - 2, r.bottom - 1);
  3793.                     }
  3794.                 }
  3795.             else    // enabled
  3796.                 {
  3797.                 ::RGBForeColor(&gAGARamp[r5]);
  3798.                 ::InsetRect(&r, 1, 1);
  3799.                 ::PaintRect(&r);
  3800.                 ::InsetRect(&r, -1, -1);
  3801.                 
  3802.                 ::RGBForeColor(&gAGARamp[rB]);
  3803.                 
  3804.                 if (mIsHorizontal)
  3805.                     {
  3806.                     ::MoveTo(r.left, r.top + 1);
  3807.                     ::LineTo(r.left, r.bottom - 2);
  3808.                     ::MoveTo(r.right - 1, r.top + 1);
  3809.                     ::LineTo(r.right - 1, r.bottom - 2);
  3810.                     
  3811.                     // Draw the shadowing.
  3812.  
  3813.                     ::RGBForeColor(&gAGARamp[r8]);
  3814.                     ::MoveTo(r.left + 1, r.bottom - 3);
  3815.                     ::LineTo(r.left + 1, r.top + 1);
  3816.                     ::LineTo(r.right - 2, r.top + 1);
  3817.  
  3818.                     ::RGBForeColor(&gAGARamp[r7]);
  3819.                     ::MoveTo(r.left + 2, r.bottom - 4);
  3820.                     ::LineTo(r.left + 2, r.top + 2);
  3821.                     ::LineTo(r.right - 3, r.top + 2);
  3822.  
  3823.                     ::RGBForeColor(&gAGARamp[r3]);
  3824.                     ::MoveTo(r.left + 2, r.bottom - 2);
  3825.                     ::LineTo(r.right - 2, r.bottom - 2);
  3826.  
  3827.                     ::RGBForeColor(&gAGARamp[r4]);
  3828.                     ::MoveTo(r.left + 3, r.bottom - 3);
  3829.                     ::LineTo(r.right - 2, r.bottom - 3);
  3830.                     }
  3831.                 else
  3832.                     {
  3833.                     ::MoveTo(r.left + 1, r.top);
  3834.                     ::LineTo(r.right - 2, r.top);
  3835.                     ::MoveTo(r.left + 1, r.bottom - 1);
  3836.                     ::LineTo(r.right - 2, r.bottom - 1);
  3837.                     
  3838.                     // Draw the shadowing.
  3839.  
  3840.                     ::RGBForeColor(&gAGARamp[r8]);
  3841.                     ::MoveTo(r.left + 1, r.bottom - 2);
  3842.                     ::LineTo(r.left + 1, r.top + 1);
  3843.                     ::LineTo(r.right - 3, r.top + 1);
  3844.  
  3845.                     ::RGBForeColor(&gAGARamp[r7]);
  3846.                     ::MoveTo(r.left + 2, r.bottom - 2);
  3847.                     ::LineTo(r.left + 2, r.top + 2);
  3848.                     ::LineTo(r.right - 4, r.top + 2);
  3849.  
  3850.                     ::RGBForeColor(&gAGARamp[r3]);
  3851.                     ::MoveTo(r.right - 2, r.top + 2);
  3852.                     ::LineTo(r.right - 2, r.bottom - 2);
  3853.  
  3854.                     ::RGBForeColor(&gAGARamp[r4]);
  3855.                     ::MoveTo(r.right - 3, r.top + 3);
  3856.                     ::LineTo(r.right - 3, r.bottom - 2);
  3857.                     }
  3858.                 }
  3859.             }
  3860.         else    // 1-bit
  3861.             {
  3862.             Rect    r = mBounds;
  3863.  
  3864.             ::InsetRect(&r, 1, 1);
  3865.             ::RGBForeColor(&gAGARamp[rW]);
  3866.             ::PaintRect(&r);
  3867.             ::InsetRect(&r, -1, -1);
  3868.  
  3869.             ::RGBForeColor(&gAGARamp[rB]);
  3870.             ::FrameRect(&mBounds);
  3871.  
  3872.             if (enabled && mActive)
  3873.                 {
  3874.                 if (mIsHorizontal)
  3875.                     {
  3876.                     ::InsetRect(&r, kArrowSize - 1, 0);
  3877.                     ::MoveTo(r.left, r.top + 1);
  3878.                     ::LineTo(r.left, r.bottom - 2);
  3879.                     ::MoveTo(r.right - 1, r.top + 1);
  3880.                     ::LineTo(r.right - 1, r.bottom - 2);
  3881.                     }
  3882.                 else
  3883.                     {
  3884.                     ::InsetRect(&r, 0, kArrowSize - 1);
  3885.                     ::MoveTo(r.left + 1, r.top);
  3886.                     ::LineTo(r.right - 2, r.top);
  3887.                     ::MoveTo(r.left + 1, r.bottom - 1);
  3888.                     ::LineTo(r.right - 2, r.bottom - 1);
  3889.                     }
  3890.                 }
  3891.             }
  3892.         }
  3893.     }
  3894.  
  3895. void AGAScrollBar::DrawTrackEnds()
  3896.     {
  3897.     AGADrawingEnvironment    env;
  3898.  
  3899.     // Draw the scroll arrows.
  3900.  
  3901.     this->DrawArrow(kArrowMinusPress, kNotPressed);
  3902.     this->DrawArrow(kArrowPlusPress, kNotPressed);
  3903.     }
  3904.  
  3905. void AGAScrollBar::DrawIndicator()
  3906.     {
  3907.     Boolean    enabled = mEnabled && (mMaximum > mMinimum);
  3908.  
  3909.     if ((! enabled) || (! mActive))
  3910.         return;
  3911.  
  3912.     AGADrawingEnvironment    env;
  3913.  
  3914.     // Draw the thumb indicator.
  3915.  
  3916.     GDIterator    iter;
  3917.     Boolean        deep;
  3918.  
  3919.     while (iter.More(deep))
  3920.         {
  3921.         enum { Fill, Light, TL, BR, Dark, kIndicatorColors };
  3922.  
  3923.         UInt8    colorIndexes[kIndicatorColors];
  3924.         Rect    r = mBounds;
  3925.         SInt32    startPt;
  3926.         SInt32    valuePt;
  3927.         SInt32    stopPt;
  3928.         Point    drawDirection;
  3929.         Point    moveDirection;
  3930.         SInt16    lineLength;
  3931.         
  3932.         if (deep)
  3933.             {
  3934.             if (mIsPressed)
  3935.                 {
  3936.                 colorIndexes[Fill] = r8;
  3937.                 colorIndexes[Light] = r3;
  3938.                 colorIndexes[TL] = r5;
  3939.                 colorIndexes[BR] = r10;
  3940.                 colorIndexes[Dark] = r12;
  3941.                 }
  3942.             else
  3943.                 {
  3944.                 colorIndexes[Fill] = r5;
  3945.                 colorIndexes[Light] = r1;
  3946.                 colorIndexes[TL] = r3;
  3947.                 colorIndexes[BR] = r8;
  3948.                 colorIndexes[Dark] = r10;
  3949.                 }
  3950.             }
  3951.         else
  3952.             {
  3953.             if (mIsPressed)
  3954.                 {
  3955.                 colorIndexes[Fill] = rB;
  3956.                 colorIndexes[Light] = rB;
  3957.                 colorIndexes[TL] = rW;
  3958.                 colorIndexes[BR] = rB;
  3959.                 colorIndexes[Dark] = rB;
  3960.                 }
  3961.             else
  3962.                 {
  3963.                 colorIndexes[Fill] = rW;
  3964.                 colorIndexes[Light] = rW;
  3965.                 colorIndexes[TL] = rB;
  3966.                 colorIndexes[BR] = rW;
  3967.                 colorIndexes[Dark] = rW;
  3968.                 }
  3969.             }
  3970.         
  3971.         this->GetIndicatorSpan(mValue, &startPt, &valuePt, &stopPt);
  3972.         this->GetIndicatorBox(mValue, &r);
  3973.         
  3974.         if (mIsHorizontal)
  3975.             {
  3976.             ::SetPt(&drawDirection, 0, 1);
  3977.             ::SetPt(&moveDirection, 1, 0);
  3978.             lineLength = r.bottom - r.top - 11;
  3979.             }
  3980.         else
  3981.             {
  3982.             ::SetPt(&drawDirection, 1, 0);
  3983.             ::SetPt(&moveDirection, 0, 1);
  3984.             lineLength = r.right - r.left - 11;
  3985.             }
  3986.  
  3987.         ::RGBForeColor(&gAGARamp[rB]);
  3988.         ::FrameRect(&r);
  3989.         
  3990.         ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  3991.         ::InsetRect(&r, 1, 1);
  3992.         ::PaintRect(&r);
  3993.         ::InsetRect(&r, -1, -1);
  3994.         
  3995.         if (deep)
  3996.             {
  3997.             ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  3998.             ::MoveTo(r.left + 1, r.bottom - 3);
  3999.             ::LineTo(r.left + 1, r.top + 2);
  4000.             ::Move(1, -1);
  4001.             ::LineTo(r.right - 3, r.top + 1);
  4002.             
  4003.             ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  4004.             ::MoveTo(r.right - 2, r.top + 2);
  4005.             ::LineTo(r.right - 2, r.bottom - 2);
  4006.             ::LineTo(r.left + 2, r.bottom - 2);
  4007.  
  4008.             ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
  4009.             ::MoveTo(r.left + 1, r.top + 1);
  4010.             ::Line(0, 0);
  4011.             }
  4012.         
  4013.         ::MoveTo(r.left + 4 + (moveDirection.h * (((r.right - r.left) / 2) - 8)),
  4014.                 r.top + 4 + (moveDirection.v * (((r.bottom - r.top) / 2) - 8)));
  4015.  
  4016.         if (! deep)
  4017.             ::Move(moveDirection.h, moveDirection.v);
  4018.  
  4019.         for (SInt32 i = 0; i < 4; i++)
  4020.             {
  4021.             ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
  4022.             ::Line(0, 0);
  4023.             
  4024.             ::Move(drawDirection.h, drawDirection.v);
  4025.             ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  4026.             ::Line(drawDirection.h * lineLength, drawDirection.v * lineLength);
  4027.             
  4028.             ::Move(moveDirection.h, moveDirection.v);
  4029.             ::Move(drawDirection.h, drawDirection.v);
  4030.             ::RGBForeColor(&gAGARamp[colorIndexes[Dark]]);
  4031.             ::Line(- (drawDirection.h * (lineLength+1)), - (drawDirection.v * (lineLength+1)));
  4032.  
  4033.             ::Move(moveDirection.h, moveDirection.v);
  4034.             ::Move(- drawDirection.h, - drawDirection.v);
  4035.             }
  4036.         }
  4037.     }
  4038.  
  4039. void AGAScrollBar::RemoveIndicator(SInt32 newValue)
  4040.     {
  4041.     AGADrawingEnvironment    env;
  4042.  
  4043.     // Draw the track/background to remove the current
  4044.     // indicator.
  4045.  
  4046.     //
  4047.     // Set clipping so we only draw the track to
  4048.     // wipe out the old indicator, but not where
  4049.     // the new indicator will get drawn anyway.
  4050.     // This reduces flicker.
  4051.     //
  4052.  
  4053.     ::GetClip(mgSavedIndicatorClip);
  4054.  
  4055.     if (newValue != mValue)
  4056.         {
  4057.         Rect    oldIndicatorBox;
  4058.         Rect    newIndicatorBox;
  4059.  
  4060.         this->GetIndicatorBox(mValue, &oldIndicatorBox);
  4061.         this->GetIndicatorBox(newValue, &newIndicatorBox);
  4062.         
  4063.         ::RectRgn(mgOldIndicatorClip, &oldIndicatorBox);
  4064.         ::RectRgn(mgNewIndicatorClip, &newIndicatorBox);
  4065.         ::DiffRgn(mgOldIndicatorClip, mgNewIndicatorClip, mgOldIndicatorClip);
  4066.  
  4067.         ::SetClip(mgOldIndicatorClip);
  4068.         }
  4069.  
  4070.     this->DrawIndicatorTrack();
  4071.  
  4072.     ::SetClip(mgSavedIndicatorClip);
  4073.     }
  4074.  
  4075. void AGAScrollBar::DrawGhost()
  4076.     {
  4077.     AGADrawingEnvironment    env;
  4078.  
  4079.     // Draw the indicator as a ghost at the current mGhostValue
  4080.     // position.
  4081.  
  4082.     GDIterator    iter;
  4083.     Boolean        deep;
  4084.  
  4085.     while (iter.More(deep))
  4086.         {
  4087.         Rect    r = mBounds;
  4088.         SInt32    startPt;
  4089.         SInt32    valuePt;
  4090.         SInt32    stopPt;
  4091.         Point    drawDirection;
  4092.         Point    moveDirection;
  4093.         SInt16    lineLength;
  4094.         
  4095.         this->GetIndicatorSpan(mGhostValue, &startPt, &valuePt, &stopPt);
  4096.         this->GetIndicatorBox(mGhostValue, &r);
  4097.         
  4098.         if (deep)
  4099.             {
  4100.             if (mIsHorizontal)
  4101.                 {
  4102.                 ::SetPt(&drawDirection, 0, 1);
  4103.                 ::SetPt(&moveDirection, 1, 0);
  4104.                 lineLength = r.bottom - r.top - 11;
  4105.                 
  4106.                 ::RGBForeColor(&gAGARamp[r4]);
  4107.                 ::InsetRect(&r, 1, 3);
  4108.                 ::PaintRect(&r);
  4109.                 ::InsetRect(&r, -1, -3);
  4110.                 
  4111.                 ::RGBForeColor(&gAGARamp[r11]);
  4112.                 ::MoveTo(r.left, r.top + 1);
  4113.                 ::Line(0, 0);
  4114.                 ::MoveTo(r.right - 1, r.top + 1);
  4115.                 ::Line(0, 0);
  4116.                 
  4117.                 ::RGBForeColor(&gAGARamp[r10]);
  4118.                 ::MoveTo(r.left, r.top + 2);
  4119.                 ::Line(0, 0);
  4120.                 ::MoveTo(r.right - 1, r.top + 2);
  4121.                 ::Line(0, 0);
  4122.                 
  4123.                 ::RGBForeColor(&gAGARamp[r8]);
  4124.                 ::MoveTo(r.left, r.top + 3);
  4125.                 ::LineTo(r.left, r.bottom - 4);
  4126.                 ::MoveTo(r.right - 1, r.top + 3);
  4127.                 ::LineTo(r.right - 1, r.bottom - 4);
  4128.                 
  4129.                 ::RGBForeColor(&gAGARamp[r6]);
  4130.                 ::MoveTo(r.left, r.bottom - 3);
  4131.                 ::Line(0, 0);
  4132.                 ::MoveTo(r.right - 1, r.bottom - 3);
  4133.                 ::Line(0, 0);
  4134.                 
  4135.                 ::RGBForeColor(&gAGARamp[r4]);
  4136.                 ::MoveTo(r.left, r.bottom - 2);
  4137.                 ::Line(0, 0);
  4138.                 ::MoveTo(r.right - 1, r.bottom - 2);
  4139.                 ::Line(0, 0);
  4140.                 
  4141.                 ::RGBForeColor(&gAGARamp[r6]);
  4142.                 ::MoveTo(r.left + 1, r.top + 1);
  4143.                 ::LineTo(r.right - 2, r.top + 1);
  4144.                 
  4145.                 ::RGBForeColor(&gAGARamp[r5]);
  4146.                 ::MoveTo(r.left + 1, r.top + 2);
  4147.                 ::LineTo(r.right - 2, r.top + 2);
  4148.                 
  4149.                 ::RGBForeColor(&gAGARamp[r3]);
  4150.                 ::MoveTo(r.left + 1, r.bottom - 3);
  4151.                 ::LineTo(r.right - 2, r.bottom - 3);
  4152.                 
  4153.                 ::RGBForeColor(&gAGARamp[r2]);
  4154.                 ::MoveTo(r.left + 1, r.bottom - 2);
  4155.                 ::LineTo(r.right - 2, r.bottom - 2);
  4156.                 }
  4157.             else
  4158.                 {
  4159.                 ::SetPt(&drawDirection, 1, 0);
  4160.                 ::SetPt(&moveDirection, 0, 1);
  4161.                 lineLength = r.right - r.left - 11;
  4162.                 
  4163.                 ::RGBForeColor(&gAGARamp[r4]);
  4164.                 ::InsetRect(&r, 3, 1);
  4165.                 ::PaintRect(&r);
  4166.                 ::InsetRect(&r, -3, -1);
  4167.                 
  4168.                 ::RGBForeColor(&gAGARamp[r11]);
  4169.                 ::MoveTo(r.left + 1, r.top);
  4170.                 ::Line(0, 0);
  4171.                 ::MoveTo(r.left + 1, r.bottom - 1);
  4172.                 ::Line(0, 0);
  4173.                 
  4174.                 ::RGBForeColor(&gAGARamp[r10]);
  4175.                 ::MoveTo(r.left + 2, r.top);
  4176.                 ::Line(0, 0);
  4177.                 ::MoveTo(r.left + 2, r.bottom - 1);
  4178.                 ::Line(0, 0);
  4179.                 
  4180.                 ::RGBForeColor(&gAGARamp[r8]);
  4181.                 ::MoveTo(r.left + 3, r.top);
  4182.                 ::LineTo(r.right - 4, r.top);
  4183.                 ::MoveTo(r.left + 3, r.bottom - 1);
  4184.                 ::LineTo(r.right - 4, r.bottom - 1);
  4185.                 
  4186.                 ::RGBForeColor(&gAGARamp[r6]);
  4187.                 ::MoveTo(r.right - 3, r.top);
  4188.                 ::Line(0, 0);
  4189.                 ::MoveTo(r.right - 3, r.bottom - 1);
  4190.                 ::Line(0, 0);
  4191.                 
  4192.                 ::RGBForeColor(&gAGARamp[r4]);
  4193.                 ::MoveTo(r.right - 2, r.top);
  4194.                 ::Line(0, 0);
  4195.                 ::MoveTo(r.right - 2, r.bottom - 1);
  4196.                 ::Line(0, 0);
  4197.                 
  4198.                 ::RGBForeColor(&gAGARamp[r6]);
  4199.                 ::MoveTo(r.left + 1, r.top + 1);
  4200.                 ::LineTo(r.left + 1, r.bottom - 2);
  4201.                 
  4202.                 ::RGBForeColor(&gAGARamp[r5]);
  4203.                 ::MoveTo(r.left + 2, r.top + 1);
  4204.                 ::LineTo(r.left + 2, r.bottom - 2);
  4205.                 
  4206.                 ::RGBForeColor(&gAGARamp[r3]);
  4207.                 ::MoveTo(r.right - 3, r.top + 1);
  4208.                 ::LineTo(r.right - 3, r.bottom - 2);
  4209.                 
  4210.                 ::RGBForeColor(&gAGARamp[r2]);
  4211.                 ::MoveTo(r.right - 2, r.top + 1);
  4212.                 ::LineTo(r.right - 2, r.bottom - 2);
  4213.                 }
  4214.  
  4215.             ::MoveTo(r.left + 4 + (moveDirection.h * (((r.right - r.left) / 2) - 8)),
  4216.                     r.top + 4 + (moveDirection.v * (((r.bottom - r.top) / 2) - 8)));
  4217.  
  4218.             for (SInt32 i = 0; i < 4; i++)
  4219.                 {
  4220.                 ::RGBForeColor(&gAGARamp[r2]);
  4221.                 ::Line(drawDirection.h * (lineLength+1), drawDirection.v * (lineLength+1));
  4222.                 
  4223.                 ::Move(moveDirection.h, moveDirection.v);
  4224.                 ::Move(drawDirection.h, drawDirection.v);
  4225.                 ::RGBForeColor(&gAGARamp[r6]);
  4226.                 ::Line(- (drawDirection.h * (lineLength+1)), - (drawDirection.v * (lineLength+1)));
  4227.  
  4228.                 ::Move(moveDirection.h, moveDirection.v);
  4229.                 ::Move(- drawDirection.h, - drawDirection.v);
  4230.                 }
  4231.             }
  4232.         else
  4233.             {
  4234.             ::RGBForeColor(&gAGARamp[rB]);
  4235.             ::FrameRect(&r);
  4236.             }
  4237.         }
  4238.     }
  4239.  
  4240. void AGAScrollBar::RemoveGhost(SInt32 /*newValue*/)
  4241.     {
  4242.     AGADrawingEnvironment    env;
  4243.  
  4244.     // Draw the track/background to remove the current
  4245.     // ghost indicator.
  4246.  
  4247.     Rect    r;
  4248.     RgnHandle    savedClip = ::NewRgn();
  4249.     
  4250.     ::GetClip(savedClip);
  4251.  
  4252.     this->GetIndicatorBox(mGhostValue, &r);
  4253.     ::ClipRect(&r);
  4254.     this->DrawIndicatorTrack();
  4255.     this->DrawIndicator();
  4256.     
  4257.     ::SetClip(savedClip);
  4258.     }
  4259.  
  4260. void AGAScrollBar::TrackDelta(SInt32 partHit)
  4261.     {
  4262.     // Change our value based on the delta amount
  4263.     // for the part that was hit. Do notification
  4264.     // of the value change.
  4265.  
  4266.     SInt32    oldValue = mValue;
  4267.     SInt32    newValue = mValue;
  4268.     
  4269.     switch (partHit)
  4270.         {
  4271.         case kPageMinusPress:
  4272.             newValue -= mPageStepSize;
  4273.             break;
  4274.         case kArrowMinusPress:
  4275.             newValue -= mSingleStepSize;
  4276.             break;
  4277.         case kArrowPlusPress:
  4278.             newValue += mSingleStepSize;
  4279.             break;
  4280.         case kPagePlusPress:
  4281.             newValue += mPageStepSize;
  4282.             break;
  4283.         }
  4284.     
  4285.     this->SetValue(newValue, kRedraw);
  4286.     
  4287.     if (mValue != oldValue)
  4288.         this->NotifyValue();
  4289.     }
  4290.  
  4291. void AGAScrollBar::DrawArrow(SInt32 arrowPart, Boolean pressed)
  4292.     {
  4293.     AGADrawingEnvironment    env;
  4294.  
  4295.     // Draw the specified arrow in the specified mode.
  4296.  
  4297.     if ((arrowPart != kArrowMinusPress) &&
  4298.         (arrowPart != kArrowPlusPress))
  4299.         return;
  4300.  
  4301.     enum { Fill, TL, BR, Arrow, kNumArrowColors };
  4302.  
  4303.     Boolean    enabled = mEnabled && (mMaximum > mMinimum);
  4304.     UInt8    colorIndexes[kNumArrowColors];
  4305.     Rect    r = mBounds;
  4306.     
  4307.     if (mIsHorizontal)
  4308.         {
  4309.         if (arrowPart == kArrowPlusPress)
  4310.             r.left = r.right - kArrowSize;
  4311.         else
  4312.             r.right = r.left + kArrowSize;
  4313.         }
  4314.     else
  4315.         {
  4316.         if (arrowPart == kArrowPlusPress)
  4317.             r.top = r.bottom - kArrowSize;
  4318.         else
  4319.             r.bottom = r.top + kArrowSize;
  4320.         }
  4321.     
  4322.     // Note: we don't draw the outer frame.
  4323.     // That's already been drawn.
  4324.  
  4325.     GDIterator    iter;
  4326.     Boolean        deep;
  4327.  
  4328.     while (iter.More(deep))
  4329.         {
  4330.         if (deep)
  4331.             {
  4332.             if (! mActive)
  4333.                 {
  4334.                 colorIndexes[Fill] = r1;
  4335.                 colorIndexes[TL] = r1;
  4336.                 colorIndexes[BR] = r1;
  4337.                 colorIndexes[Arrow] = r1;
  4338.                 }
  4339.             else if (pressed)
  4340.                 {
  4341.                 colorIndexes[Fill] = r8;
  4342.                 colorIndexes[TL] = r10;
  4343.                 colorIndexes[BR] = r6;
  4344.                 colorIndexes[Arrow] = rB;
  4345.                 }
  4346.             else if (enabled)
  4347.                 {
  4348.                 colorIndexes[Fill] = r2;
  4349.                 colorIndexes[TL] = rW;
  4350.                 colorIndexes[BR] = r5;
  4351.                 colorIndexes[Arrow] = rB;
  4352.                 }
  4353.             else    // disabled
  4354.                 {
  4355.                 colorIndexes[Fill] = r2;
  4356.                 colorIndexes[TL] = rW;
  4357.                 colorIndexes[BR] = r4;
  4358.                 colorIndexes[Arrow] = r8;
  4359.                 }
  4360.             }
  4361.         else
  4362.             {
  4363.             if ((! mActive) || ! enabled)
  4364.                 {
  4365.                 colorIndexes[Fill] = rW;
  4366.                 colorIndexes[TL] = rW;
  4367.                 colorIndexes[BR] = rW;
  4368.                 colorIndexes[Arrow] = rW;
  4369.                 }
  4370.             else if (pressed)
  4371.                 {
  4372.                 colorIndexes[Fill] = rB;
  4373.                 colorIndexes[TL] = rB;
  4374.                 colorIndexes[BR] = rB;
  4375.                 colorIndexes[Arrow] = rW;
  4376.                 }
  4377.             else // unpressed + enabled
  4378.                 {
  4379.                 colorIndexes[Fill] = rW;
  4380.                 colorIndexes[TL] = rW;
  4381.                 colorIndexes[BR] = rW;
  4382.                 colorIndexes[Arrow] = rB;
  4383.                 }
  4384.             }
  4385.  
  4386.         ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  4387.         ::InsetRect(&r, 1, 1);
  4388.         ::PaintRect(&r);
  4389.         ::InsetRect(&r, -1, -1);
  4390.         
  4391.         ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  4392.         ::MoveTo(r.left + 1, r.bottom - 3);
  4393.         ::LineTo(r.left + 1, r.top + 1);
  4394.         ::LineTo(r.right - 3, r.top + 1);
  4395.  
  4396.         ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  4397.         ::MoveTo(r.right - 2, r.top + 2);
  4398.         ::LineTo(r.right - 2, r.bottom - 2);
  4399.         ::LineTo(r.left + 2, r.bottom - 2);
  4400.  
  4401.         ::RGBForeColor(&gAGARamp[colorIndexes[Arrow]]);
  4402.         SInt16    direction = (arrowPart == kArrowPlusPress) ? 1 : -1;
  4403.         SInt16    offset = (arrowPart == kArrowPlusPress) ? 6 : 9;
  4404.         
  4405.         if (mIsHorizontal)
  4406.             {
  4407.             ::MoveTo(r.left + offset, ((r.top + r.bottom) / 2) - 4);
  4408.             ::Line(0, 7);
  4409.             ::Move(direction, -6);
  4410.             ::Line(0, 5);
  4411.             ::Move(direction, -4);
  4412.             ::Line(0, 3);
  4413.             ::Move(direction, -2);
  4414.             ::Line(0, 1);
  4415.             }
  4416.         else
  4417.             {
  4418.             ::MoveTo(((r.left + r.right) / 2) - 4, r.top + offset);
  4419.             ::Line(7, 0);
  4420.             ::Move(-6, direction);
  4421.             ::Line(5, 0);
  4422.             ::Move(-4, direction);
  4423.             ::Line(3, 0);
  4424.             ::Move(-2, direction);
  4425.             ::Line(1, 0);
  4426.             }
  4427.         }
  4428.     }
  4429.  
  4430. void AGAScrollBar::GetIndicatorBox(SInt32 indicatorValue, Rect* indicatorBox)
  4431.     {
  4432.     // Return the bounds of the indicator box assuming that
  4433.     // it has specified indicator value.
  4434.  
  4435.     Rect    r = mBounds;
  4436.     SInt32    startPt;
  4437.     SInt32    valuePt;
  4438.     SInt32    stopPt;
  4439.  
  4440.     this->GetIndicatorSpan(indicatorValue, &startPt, &valuePt, &stopPt);
  4441.     
  4442.     if (mIsHorizontal)
  4443.         {
  4444.         r.left = startPt;
  4445.         r.right = stopPt;
  4446.         }
  4447.     else
  4448.         {
  4449.         r.top = startPt;
  4450.         r.bottom = stopPt;
  4451.         }
  4452.     
  4453.     *indicatorBox = r;
  4454.     }
  4455.  
  4456. SInt32 AGAScrollBar::GetIndicatorPixelRange(SInt32* proportionalIndicatorPixels)
  4457.     {
  4458.     // Return the pixel range that the center point of the indicator
  4459.     // can travel along the track, and also return the amount of
  4460.     // range reduction that is caused by proportional indicator growth.
  4461.     // Non-proportional indicators use the full track range, minus
  4462.     // the size of the indicator itself.
  4463.  
  4464.     SInt32    range;
  4465.     
  4466.     *proportionalIndicatorPixels = 0;
  4467.  
  4468.     if (mIsHorizontal)
  4469.         range = mBounds.right - mBounds.left - (2 * (kArrowSize + kIndicatorPixelInset)) + 1;
  4470.     else
  4471.         range = mBounds.bottom - mBounds.top - (2 * (kArrowSize + kIndicatorPixelInset)) + 1;
  4472.  
  4473.     if (mIsProportional)
  4474.         {
  4475.         SInt32    pagePixels;
  4476.         
  4477.         pagePixels =
  4478.             (range * (((float) mPageSize) / ((float) (mMaximum - mMinimum))));
  4479.         
  4480.         if (pagePixels > 0)
  4481.             {
  4482.             range -= pagePixels;
  4483.             *proportionalIndicatorPixels = pagePixels;
  4484.             }
  4485.         }
  4486.     
  4487.     return range;
  4488.     }
  4489.  
  4490. void AGAScrollBar::GetIndicatorPixelEnds(SInt32* startPt, SInt32* stopPt)
  4491.     {
  4492.     // Return the start and end pixel locations of the indicator
  4493.     // track traveled by the center point of the indicator.
  4494.  
  4495.     SInt32    dontCare;
  4496.     SInt32    range = this->GetIndicatorPixelRange(&dontCare);
  4497.  
  4498.     if (mIsHorizontal)
  4499.         {
  4500.         *startPt = ((mBounds.left + mBounds.right) / 2) - (range / 2) - 1;
  4501.         
  4502.         // Bump by 1 if width is odd but range isn't.
  4503.         if ((((mBounds.right - mBounds.left) & 1) != 0) &&
  4504.             ((range & 1) == 0))
  4505.             (*startPt)++;
  4506.         }
  4507.     else
  4508.         {
  4509.         *startPt = ((mBounds.top + mBounds.bottom) / 2) - (range / 2) - 1;
  4510.         
  4511.         // Bump by 1 if height is odd but range isn't.
  4512.         if ((((mBounds.bottom - mBounds.top) & 1) != 0) &&
  4513.             ((range & 1) == 0))
  4514.             (*startPt)++;
  4515.         }
  4516.  
  4517.     *stopPt = *startPt + range;    // avoid rounding of 1/2 pixel twice
  4518.     }
  4519.  
  4520. void AGAScrollBar::GetIndicatorSpan(SInt32 value, SInt32* startPt, SInt32* valuePt, SInt32* stopPt)
  4521.     {
  4522.     // Return the pixel locations of the indicator's ends and value.
  4523.  
  4524.     SInt32    proportionalIndicatorPixels;
  4525.     SInt32    trackStart;
  4526.     SInt32    trackStop;
  4527.     SInt32    trackRange = this->GetIndicatorPixelRange(&proportionalIndicatorPixels);
  4528.     
  4529.     this->GetIndicatorPixelEnds(&trackStart, &trackStop);
  4530.     
  4531.     *valuePt = trackStart +
  4532.         (trackRange * (((float) (value - mMinimum)) / ((float) (mMaximum - mMinimum))));
  4533.  
  4534.     *startPt = *valuePt - kIndicatorPixelInset - (proportionalIndicatorPixels / 2);
  4535.     *stopPt = *startPt + (2 * kIndicatorPixelInset) + proportionalIndicatorPixels + 1;
  4536.     }
  4537.  
  4538. //
  4539. // AGASlider ---------------------------------------------------------------
  4540. //
  4541. // This class implements a standard AGA slider, with the additional
  4542. // ability to perform live tracking and a proportional thumb.
  4543. //
  4544.  
  4545. // These regions are used momentarily while tracking the slider
  4546. // indicator to clip and optimize redrawing.
  4547. RgnHandle AGASlider::mgSavedIndicatorClip = ::NewRgn();
  4548. RgnHandle AGASlider::mgOldIndicatorClip = ::NewRgn();
  4549. RgnHandle AGASlider::mgNewIndicatorClip = ::NewRgn();
  4550.  
  4551. AGASlider::AGASlider(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, const AGATextStyle& textStyle, SInt16 labelsID)
  4552.     : AGATrackingIndicator(bounds, minimum, maximum, initialValue)
  4553.     {
  4554.     // Construct with default options.
  4555.     mPageSize = 0;
  4556.  
  4557.     mLabelStringHandles = NULL;
  4558.     mJustification = teFlushDefault;
  4559.     mTextStyle = textStyle;
  4560.  
  4561.     if (labelsID == 0)
  4562.         {
  4563.         mSliderKind = kRectSlider;
  4564.  
  4565.         mLiveTracking = TestGrayCouncilDefault(kAGALiveRSliders);
  4566.         mIsProportional = TestGrayCouncilDefault(kAGAProportionalRSliders);
  4567.         }
  4568.     else
  4569.         {
  4570.         mSliderKind = kPointerSlider;
  4571.         this->SetLabelsFromResource(labelsID);
  4572.  
  4573.         mLiveTracking = TestGrayCouncilDefault(kAGALivePSliders);
  4574.         mIsProportional = TestGrayCouncilDefault(kAGAProportionalPSliders);
  4575.         }
  4576.     }
  4577.  
  4578. AGASlider::AGASlider(Rect* bounds, SInt32 minimum, SInt32 maximum, SInt32 initialValue, const AGATextStyle& textStyle, SInt16 labelsID, SliderKind kind, Boolean liveTracking, Boolean proportional)
  4579.     : AGATrackingIndicator(bounds, minimum, maximum, initialValue, 1, liveTracking, proportional)
  4580.     {
  4581.     // Construct with specified options.
  4582.  
  4583.     mPageSize = 0;
  4584.  
  4585.     mLabelStringHandles = NULL;
  4586.     mJustification = teFlushDefault;
  4587.     mSliderKind = kind;
  4588.     mTextStyle = textStyle;
  4589.  
  4590.     this->SetLabelsFromResource(labelsID);
  4591.     }
  4592.  
  4593. AGASlider::~AGASlider()
  4594.     {
  4595.     // Destruct by releasing memory allocated for labels.
  4596.  
  4597.     this->DisposeLabels();
  4598.     }
  4599.  
  4600. void AGASlider::SetSliderKind(SliderKind kind)
  4601.     {
  4602.     // Set the slider kind (pointy or rectangular).
  4603.  
  4604.     mSliderKind = kind;
  4605.     }
  4606.  
  4607. void AGASlider::SetLabelsFromResource(SInt16 stringListResourceID)
  4608.     {
  4609.     // Build the slider labels from the specified 'STR#' resource.
  4610.     // A label slot is allocated for each string in the resource;
  4611.     // there will be a visual label tick for each of these strings.
  4612.     // If the current min/max range is smaller than the number of
  4613.     // labels (i.e., it's uninitialized), the min/max range will
  4614.     // be set to match the number of labels.
  4615.  
  4616.     this->DisposeLabels();
  4617.     
  4618.     if (stringListResourceID != 0)
  4619.         {
  4620.         SInt16**    stringListHandle = (SInt16**) ::GetResource('STR#', stringListResourceID);
  4621.         SInt16        numLabels = (stringListHandle == NULL) ? 0 : **stringListHandle;
  4622.         
  4623.         if (numLabels != 0)
  4624.             {
  4625.             mLabelStringHandles = ::NewHandleClear(numLabels * sizeof(StringHandle));
  4626.             
  4627.             for (SInt16 i = 0; i < numLabels; i++)
  4628.                 {
  4629.                 Str255            aLabel;
  4630.                 StringHandle    aStringHandle;
  4631.                 
  4632.                 ::GetIndString(aLabel, stringListResourceID, i+1);
  4633.                 aStringHandle = ::NewString(aLabel);
  4634.                 
  4635.                 ((StringHandle*)(*mLabelStringHandles))[i] = aStringHandle;
  4636.                 }
  4637.             }
  4638.     
  4639.         if ((mMaximum - mMinimum + 1) < numLabels)
  4640.             mMaximum = mMinimum + numLabels - 1;
  4641.         }
  4642.     }
  4643.  
  4644. void AGASlider::SetNumLabels(UInt32 numLabels)
  4645.     {
  4646.     // Allocate slots for the specified number of labels.
  4647.     // Any existing labels are thrown away.
  4648.  
  4649.     this->DisposeLabels();
  4650.     
  4651.     mLabelStringHandles = ::NewHandleClear(numLabels * sizeof(StringHandle));
  4652.  
  4653.     if ((mMaximum - mMinimum + 1) < numLabels)
  4654.         mMaximum = mMinimum + numLabels - 1;
  4655.     }
  4656.  
  4657. void AGASlider::SetLabel(UInt32 labelIndex, StringPtr itsLabel)
  4658.     {
  4659.     // Assign the specified string to the specified label slot.
  4660.  
  4661.     if (mLabelStringHandles != NULL)
  4662.         {
  4663.         UInt32    numLabels = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
  4664.         
  4665.         if (labelIndex < numLabels)
  4666.             ((StringHandle*)(*mLabelStringHandles))[labelIndex] = ::NewString(itsLabel);
  4667.         }
  4668.     }
  4669.  
  4670. void AGASlider::GetLabel(UInt32 labelIndex, StringPtr itsLabel)
  4671.     {
  4672.     // Return the label string of the specified label slot.
  4673.  
  4674.     itsLabel[0] = 0;
  4675.  
  4676.     if (mLabelStringHandles != NULL)
  4677.         {
  4678.         UInt32    numLabels = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
  4679.         
  4680.         if (labelIndex < numLabels)
  4681.             {
  4682.             Ptr    sourceStringPtr = (Ptr) *(((StringHandle*)(*mLabelStringHandles))[labelIndex]);
  4683.  
  4684.             ::BlockMoveData(sourceStringPtr, itsLabel, 1 + *sourceStringPtr);
  4685.             }
  4686.         }
  4687.     }
  4688.  
  4689. void AGASlider::SetLabelsStyle(const AGATextStyle& textStyle)
  4690.     {
  4691.     // Set the QuickDraw text style for the labels.
  4692.  
  4693.     mTextStyle = textStyle;
  4694.     }
  4695.  
  4696. void AGASlider::SetJustification(SInt32 justification)
  4697.     {
  4698.     // Set the justification of the slider. For vertical
  4699.     // sliders, default/left means the slider is on the
  4700.     // left and the labels are on the right; flush right
  4701.     // reverses this. For horizontal sliders, default/left
  4702.     // means the slider is above and the labels are below;
  4703.     // flush right reverses this.
  4704.     // In fact, for "teFlushDefault", the system script
  4705.     // direction is checked at runtime, so this is usually
  4706.     // what you should use. Use flush right or flush left
  4707.     // to force it one way or another.
  4708.  
  4709.     mJustification = justification;
  4710.     }
  4711.  
  4712. SInt32 AGASlider::TrackTestPart(Point mouseLocation)
  4713.     {
  4714.     // Return the indicator part value if the mouse location
  4715.     // would hit the indicator.
  4716.  
  4717.     Rect    indicatorRect;
  4718.     
  4719.     this->GetIndicatorBox(mValue, &indicatorRect);
  4720.     
  4721.     if (::PtInRect(mouseLocation, &indicatorRect))
  4722.         return kIndicatorPress;
  4723.     else
  4724.         return kNoTrackPress;
  4725.     }
  4726.  
  4727. Boolean AGASlider::IsValidIndicatorTrackMouse(Point mouseLocation)
  4728.     {
  4729.     // Return true if the mouse location is reasonably close
  4730.     // to the indicator track. This will depend on the
  4731.     // justification.
  4732.  
  4733.     Rect    okRect = mBounds;
  4734.     
  4735.     if (mIsHorizontal)
  4736.         {
  4737.         if (RuntimeJustify(mJustification) == teFlushLeft)
  4738.             okRect.bottom = okRect.top + kIndicatorWidth;
  4739.         else
  4740.             okRect.top = okRect.bottom - kIndicatorWidth;
  4741.         }
  4742.     else
  4743.         {
  4744.         if (RuntimeJustify(mJustification) == teFlushLeft)
  4745.             okRect.right = okRect.left + kIndicatorWidth;
  4746.         else
  4747.             okRect.left = okRect.right - kIndicatorWidth;
  4748.         }
  4749.     
  4750.     ::InsetRect(&okRect, -32, -32);    // slop for mouse tracking
  4751.  
  4752.     return ::PtInRect(mouseLocation, &okRect);
  4753.     }
  4754.  
  4755. SInt32 AGASlider::GetValueFromMouseDelta(SInt32 originalValue, Point originalMouseLocation, Point newMouseLocation)
  4756.     {
  4757.     // Return the new potential indicator value based on the mouse
  4758.     // delta from the original click location and the original value.
  4759.  
  4760.     SInt32    dontCare;
  4761.     SInt32    valueRange = mMaximum - mMinimum;
  4762.     SInt32    pixelRange = this->GetIndicatorPixelRange(&dontCare);
  4763.     SInt32    pixelDelta;
  4764.     float    pixelFraction;
  4765.     
  4766.     if (mIsHorizontal)
  4767.         pixelDelta = newMouseLocation.h - originalMouseLocation.h;
  4768.     else
  4769.         pixelDelta = newMouseLocation.v - originalMouseLocation.v;
  4770.  
  4771.     pixelFraction = ((float) pixelDelta) / (float) pixelRange;
  4772.     
  4773.     float delta = pixelFraction * ((float) valueRange);
  4774.     delta += (float) 0.5;    // round to nearest integer, don't just truncate fraction
  4775.     
  4776.     return originalValue + delta;
  4777.     }
  4778.  
  4779. void AGASlider::DrawBackground()
  4780.     {
  4781.     AGADrawingEnvironment    env;
  4782.  
  4783.     // Paint the background and labels.
  4784.  
  4785.     GDIterator    iter;
  4786.     Boolean        deep;
  4787.  
  4788.     while (iter.More(deep))
  4789.         {
  4790.         if (deep)
  4791.             this->ApplyBackgroundColor();
  4792.         else
  4793.             ::RGBForeColor(&gAGARamp[rW]);
  4794.         }
  4795.  
  4796.     ::PaintRect(&mBounds);
  4797.     
  4798.     iter.Cleanup();    // Restore clipping since not yet destructed.
  4799.  
  4800.     this->DrawLabels();
  4801.     }
  4802.  
  4803. void AGASlider::DrawIndicatorTrack()
  4804.     {
  4805.     AGADrawingEnvironment    env;
  4806.  
  4807.     // Draw the empty slider track.
  4808.  
  4809.     GDIterator    iter;
  4810.     Boolean        deep;
  4811.  
  4812.     while (iter.More(deep))
  4813.         {
  4814.         if (deep)
  4815.             {
  4816.             Rect    trackFrame;
  4817.             
  4818.             this->GetTrackFrame(&trackFrame, kIncludeBackground);
  4819.  
  4820.             this->ApplyBackgroundColor();
  4821.             ::PaintRect(&trackFrame);
  4822.             
  4823.             this->GetTrackFrame(&trackFrame, kTrackOnly);
  4824.  
  4825.             if (mEnabled)
  4826.                 ::RGBForeColor(&gAGARamp[rB]);
  4827.             else
  4828.                 ::RGBForeColor(&gAGARamp[r8]);
  4829.             
  4830.             ::InsetRect(&trackFrame, 1, 1);
  4831.             ::MoveTo(trackFrame.left + 1, trackFrame.top);
  4832.             ::LineTo(trackFrame.right - 2, trackFrame.top);
  4833.             ::Move(1, 1);
  4834.             ::LineTo(trackFrame.right - 1, trackFrame.bottom - 2);
  4835.             ::Move(-1, 1);
  4836.             ::LineTo(trackFrame.left + 1, trackFrame.bottom - 1);
  4837.             ::Move(-1, -1);
  4838.             ::LineTo(trackFrame.left, trackFrame.top + 1);
  4839.  
  4840.             ::InsetRect(&trackFrame, 1, 1);
  4841.  
  4842.             if (mEnabled)
  4843.                 ::RGBForeColor(&gAGARamp[r5]);
  4844.             else
  4845.                 ::RGBForeColor(&gAGARamp[r4]);
  4846.             
  4847.             ::PaintRect(&trackFrame);
  4848.  
  4849.             if (mEnabled)
  4850.                 {
  4851.                 ::InsetRect(&trackFrame, -2, -2);
  4852.                 ::MoveTo(trackFrame.left, trackFrame.bottom - 3);
  4853.                 ::LineTo(trackFrame.left, trackFrame.top + 1);
  4854.                 ::Line(1, 0);
  4855.                 ::Line(0, -1);
  4856.                 ::LineTo(trackFrame.right - 3, trackFrame.top);
  4857.                 
  4858.                 if (mIsHorizontal)
  4859.                     {
  4860.                     ::Move(1, 1);
  4861.                     ::Line(0, 0);
  4862.                     }
  4863.                 
  4864.                 ::RGBForeColor(&gAGARamp[rW]);
  4865.                 ::MoveTo(trackFrame.left + 1, trackFrame.bottom - 2);
  4866.                 ::Line(0, 0);
  4867.                 ::Move(1, 1);
  4868.                 ::LineTo(trackFrame.right - 2, trackFrame.bottom - 1);
  4869.                 ::Line(0, -1);
  4870.                 ::Line(1, 0);
  4871.                 ::LineTo(trackFrame.right -  1, trackFrame.top + 2);
  4872.  
  4873.                 if (! mIsHorizontal)
  4874.                     {
  4875.                     ::Move(-1, -1);
  4876.                     ::Line(0, 0);
  4877.                     }
  4878.                 }
  4879.             }
  4880.         else    // 1 -bit
  4881.             {
  4882.             Rect    trackFrame;
  4883.             
  4884.             this->GetTrackFrame(&trackFrame, kIncludeBackground);
  4885.  
  4886.             ::RGBForeColor(&gAGARamp[rW]);
  4887.             ::PaintRect(&trackFrame);
  4888.             
  4889.             this->GetTrackFrame(&trackFrame, kTrackOnly);
  4890.  
  4891.             ::RGBForeColor(&gAGARamp[rB]);
  4892.             
  4893.             if (! mEnabled)
  4894.                 ::PenPat(&qd.gray);
  4895.             
  4896.             ::InsetRect(&trackFrame, 1, 1);
  4897.             
  4898.             ::MoveTo(trackFrame.left + 1, trackFrame.top);
  4899.             ::LineTo(trackFrame.right - 2, trackFrame.top);
  4900.             ::Move(1, 1);
  4901.             ::LineTo(trackFrame.right - 1, trackFrame.bottom - 2);
  4902.             ::Move(-1, 1);
  4903.             ::LineTo(trackFrame.left + 1, trackFrame.bottom - 1);
  4904.             ::Move(-1, -1);
  4905.             ::LineTo(trackFrame.left, trackFrame.top + 1);
  4906.             
  4907.             if (! mEnabled)
  4908.                 ::PenPat(&qd.black);
  4909.             }
  4910.         }
  4911.     }
  4912.  
  4913. void AGASlider::DrawIndicator()
  4914.     {
  4915.     AGADrawingEnvironment    env;
  4916.  
  4917.     // Draw the slider indicator.
  4918.  
  4919.     Rect    indicatorRect;
  4920.     
  4921.     this->GetIndicatorBox(mValue, &indicatorRect);
  4922.  
  4923.     if (mSliderKind == kRectSlider)
  4924.         this->DrawRectIndicator(&indicatorRect, kNormalIndicator);
  4925.     else
  4926.         this->DrawPointerIndicator(&indicatorRect, kNormalIndicator);
  4927.     }
  4928.  
  4929. void AGASlider::DrawGhost()
  4930.     {
  4931.     AGADrawingEnvironment    env;
  4932.  
  4933.     // Draw the ghost slider indicator.
  4934.  
  4935.     Rect    indicatorRect;
  4936.     
  4937.     this->GetIndicatorBox(mGhostValue, &indicatorRect);
  4938.  
  4939.     if (mSliderKind == kRectSlider)
  4940.         this->DrawRectIndicator(&indicatorRect, kGhostIndicator);
  4941.     else
  4942.         this->DrawPointerIndicator(&indicatorRect, kGhostIndicator);
  4943.     }
  4944.  
  4945. void AGASlider::DrawLabels()
  4946.     {
  4947.     AGADrawingEnvironment    env;
  4948.  
  4949.     // Draw the slider labels and ticks.
  4950.  
  4951.     UInt32    numHandles = 0;
  4952.  
  4953.     if (mLabelStringHandles != NULL)
  4954.         numHandles = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
  4955.  
  4956.     if (numHandles < 2)    // Gotta at least label the ends, man!
  4957.         return;
  4958.     
  4959.     SInt16        tickRange;
  4960.     Point        tickOrigin;
  4961.     Point        drawDirection;
  4962.     Point        moveDirection;
  4963.     Rect        trackFrame;
  4964.     Boolean        flushLeft = (RuntimeJustify(mJustification) == teFlushLeft);
  4965.     FontInfo    fontInfo;
  4966.  
  4967.     mTextStyle.PrepareForDrawing();
  4968.     ::GetFontInfo(&fontInfo);
  4969.     
  4970.     this->GetTrackFrame(&trackFrame, kTrackOnly);
  4971.  
  4972.     if (mIsHorizontal)
  4973.         {
  4974.         tickRange = trackFrame.right - trackFrame.left - (2 * kLabelTickEndInset) - 1;
  4975.         drawDirection.h = 0;
  4976.         drawDirection.v = 1;
  4977.         moveDirection.h = 1;
  4978.         moveDirection.v = 0;
  4979.         tickOrigin.h = trackFrame.left + kLabelTickEndInset;
  4980.         
  4981.         if (flushLeft)
  4982.             tickOrigin.v = trackFrame.bottom + kLabelTickOffset;
  4983.         else
  4984.             tickOrigin.v = trackFrame.top - kLabelTickOffset - 2 - kLabelTickLength;
  4985.         }
  4986.     else
  4987.         {
  4988.         tickRange = trackFrame.bottom - trackFrame.top - (2 * kLabelTickEndInset) - 1;
  4989.         drawDirection.h = 1;
  4990.         drawDirection.v = 0;
  4991.         moveDirection.h = 0;
  4992.         moveDirection.v = 1;
  4993.         tickOrigin.v = trackFrame.top + kLabelTickEndInset;
  4994.         
  4995.         if (flushLeft)
  4996.             tickOrigin.h = trackFrame.right + kLabelTickOffset;
  4997.         else
  4998.             tickOrigin.h = trackFrame.left - kLabelTickOffset - 2 - kLabelTickLength;
  4999.         }
  5000.     
  5001.     GDIterator    iter;
  5002.     Boolean        deep;
  5003.  
  5004.     while (iter.More(deep))
  5005.         {
  5006.         for (UInt32 i = 0; i < numHandles; i++)
  5007.             {
  5008.             Point    tickLocation;
  5009.             float    fraction = ((float) i) / ((float) (numHandles - 1));
  5010.             
  5011.             tickLocation.h = tickOrigin.h + (moveDirection.h * tickRange * fraction);
  5012.             tickLocation.v = tickOrigin.v + (moveDirection.v * tickRange * fraction);
  5013.  
  5014.             ::MoveTo(tickLocation.h, tickLocation.v);
  5015.             
  5016.             ::RGBForeColor(&gAGARamp[rB]);
  5017.             
  5018.             if (! mEnabled)
  5019.                 {
  5020.                 if (deep)
  5021.                     ::RGBForeColor(&gAGARamp[r7]);
  5022.                 else
  5023.                     ::PenPat(&qd.gray);
  5024.                 }
  5025.  
  5026.             ::Line(drawDirection.h * (kLabelTickLength + 1), drawDirection.v * (kLabelTickLength + 1));
  5027.  
  5028.             ::PenNormal();
  5029.  
  5030.             if (deep)
  5031.                 {
  5032.                 // If disabled, we still draw in order to erase the 7/W
  5033.                 // shading pixels from prior enabled drawing.
  5034.  
  5035.                 if (mEnabled)
  5036.                     ::RGBForeColor(&gAGARamp[r7]);
  5037.                 else
  5038.                     this->ApplyBackgroundColor();
  5039.  
  5040.                 ::Line(moveDirection.h, moveDirection.v);
  5041.                 ::Line( - (kLabelTickLength * drawDirection.h), - (kLabelTickLength * drawDirection.v));
  5042.                 
  5043.                 if (mEnabled)
  5044.                     ::RGBForeColor(&gAGARamp[rW]);
  5045.                 
  5046.                 ::Move(-1, -1);
  5047.                 ::Line(-moveDirection.h, -moveDirection.v);
  5048.                 ::Line(drawDirection.h * kLabelTickLength, drawDirection.v * kLabelTickLength);
  5049.                 }
  5050.  
  5051.             Str255    aLabel;
  5052.             Rect    labelBox;
  5053.             SInt16    labelHeight = fontInfo.ascent + fontInfo.descent;
  5054.             SInt16    labelWidth;
  5055.             SInt32    textJustification;
  5056.  
  5057.             this->GetLabel(i, aLabel);
  5058.             labelWidth = ::StringWidth(aLabel);
  5059.             
  5060.             if (mIsHorizontal)
  5061.                 {
  5062.                 textJustification = teCenter;
  5063.                 labelBox.left = tickLocation.h - (labelWidth / 2);
  5064.                 labelBox.right = labelBox.left + labelWidth;
  5065.  
  5066.                 if (flushLeft)
  5067.                     {
  5068.                     labelBox.top = tickLocation.v + 9;
  5069.                     labelBox.bottom = labelBox.top + labelHeight;
  5070.                     }
  5071.                 else
  5072.                     {
  5073.                     labelBox.bottom = tickLocation.v - 2;
  5074.                     labelBox.top = labelBox.bottom - labelHeight;
  5075.                     }
  5076.                 }
  5077.             else
  5078.                 {
  5079.                 textJustification = mJustification;
  5080.                 labelBox.top = tickLocation.v - (labelHeight / 2);
  5081.                 labelBox.bottom = labelBox.top + labelHeight;
  5082.  
  5083.                 if (flushLeft)
  5084.                     {
  5085.                     labelBox.left = tickLocation.h + 11;
  5086.                     labelBox.right = labelBox.left + labelWidth;
  5087.                     }
  5088.                 else
  5089.                     {
  5090.                     labelBox.right = tickLocation.h - 2;
  5091.                     labelBox.left = labelBox.right - labelWidth;
  5092.                     }
  5093.                 }
  5094.  
  5095.             //
  5096.             // To make view layout simpler, we assume that the labels may
  5097.             // extend outside the mBounds. So if this happens
  5098.             // we need to make sure we aren't being clipped out, but also
  5099.             // make sure we don't extend the unclipped area out to other
  5100.             // screens during device iteration.
  5101.             //
  5102.             
  5103.             RgnHandle    savedRegion = NULL;
  5104.  
  5105.             if ((labelBox.left < mBounds.left) ||
  5106.                 (labelBox.right > mBounds.right))
  5107.                 {
  5108.                 savedRegion = ::NewRgn();
  5109.                 ::GetClip(savedRegion);
  5110.                 ::InsetRect(&labelBox, -1, -1);
  5111.                 ::ClipRect(&labelBox);
  5112.                 ::InsetRect(&labelBox, 1, 1);
  5113.                 
  5114.                 iter.ClipFurtherToCurrentDevice();
  5115.                 }
  5116.  
  5117.             AGAStringOut(aLabel, &labelBox, kNoTruncation, textJustification, mEnabled ? kNormalOutput : kDisabledOutput, deep, mTextStyle);
  5118.  
  5119.             if (savedRegion != NULL)
  5120.                 {
  5121.                 ::SetClip(savedRegion);
  5122.                 ::DisposeRgn(savedRegion);
  5123.                 }
  5124.             }
  5125.         }
  5126.     }
  5127.  
  5128. void AGASlider::DrawRectIndicator(Rect* indicatorRect, Boolean isGhost)
  5129.     {
  5130.     AGADrawingEnvironment    env;
  5131.  
  5132.     // Draw the rectangular slider indicator at the
  5133.     // specified location. The location will be sized
  5134.     // to account for a proportional indicator.
  5135.  
  5136.     enum { Frame, Fill, Corner, Light, TL, BR, Dark, Grip, BG, kNumIndicatorColors };
  5137.  
  5138.     UInt8    colorIndexes[kNumIndicatorColors];
  5139.     Rect    r = *indicatorRect;
  5140.     Point    drawDirection;
  5141.     Point    moveDirection;
  5142.     SInt16    lineLength;
  5143.  
  5144.     GDIterator    iter;
  5145.     Boolean        deep;
  5146.  
  5147.     while (iter.More(deep))
  5148.         {
  5149.         if (deep)
  5150.             {
  5151.             colorIndexes[BG] = r2;
  5152.  
  5153.             if (isGhost)
  5154.                 {
  5155.                 colorIndexes[Frame] = r7;
  5156.                 colorIndexes[Fill] = r2;
  5157.                 colorIndexes[Corner] = r1;
  5158.                 colorIndexes[Light] = rW;
  5159.                 colorIndexes[TL] = rW;
  5160.                 colorIndexes[BR] = r4;
  5161.                 colorIndexes[Dark] = r5;
  5162.                 colorIndexes[Grip] = rW;
  5163.                 }
  5164.             else if (! mEnabled)
  5165.                 {
  5166.                 colorIndexes[Frame] = r8;
  5167.                 colorIndexes[Fill] = r2;
  5168.                 colorIndexes[Corner] = r2;
  5169.                 colorIndexes[Light] = r2;
  5170.                 colorIndexes[TL] = r2;
  5171.                 colorIndexes[BR] = r2;
  5172.                 // n/a colorIndexes[Dark] = r9;
  5173.                 colorIndexes[Grip] = r2;
  5174.                 }
  5175.             else if (mIsPressed)
  5176.                 {
  5177.                 colorIndexes[Frame] = rB;
  5178.                 colorIndexes[Fill] = r8;
  5179.                 colorIndexes[Corner] = r3;
  5180.                 colorIndexes[Light] = r3;
  5181.                 colorIndexes[TL] = r5;
  5182.                 colorIndexes[BR] = r10;
  5183.                 colorIndexes[Dark] = r12;
  5184.                 colorIndexes[Grip] = r5;
  5185.                 }
  5186.             else // normal
  5187.                 {
  5188.                 colorIndexes[Frame] = rB;
  5189.                 colorIndexes[Fill] = r5;
  5190.                 colorIndexes[Corner] = r1;
  5191.                 colorIndexes[Light] = r1;
  5192.                 colorIndexes[TL] = r3;
  5193.                 colorIndexes[BR] = r8;
  5194.                 colorIndexes[Dark] = r10;
  5195.                 colorIndexes[Grip] = r3;
  5196.                 }
  5197.             }
  5198.         else    // 1-bit
  5199.             {
  5200.             colorIndexes[BG] = rW;
  5201.  
  5202.             if (isGhost)
  5203.                 {
  5204.                 colorIndexes[Frame] = rB;
  5205.                 colorIndexes[Fill] = rW;
  5206.                 colorIndexes[Corner] = rW;
  5207.                 colorIndexes[Light] = rW;
  5208.                 colorIndexes[TL] = rW;
  5209.                 colorIndexes[BR] = rW;
  5210.                 colorIndexes[Dark] = rW;
  5211.                 colorIndexes[Grip] = rB;
  5212.                 }
  5213.             else if (! mEnabled)
  5214.                 {
  5215.                 colorIndexes[Frame] = rB;
  5216.                 colorIndexes[Fill] = rW;
  5217.                 colorIndexes[Corner] = rW;
  5218.                 colorIndexes[Light] = rW;
  5219.                 colorIndexes[TL] = rW;
  5220.                 colorIndexes[BR] = rW;
  5221.                 colorIndexes[Dark] = rW;
  5222.                 colorIndexes[Grip] = rW;
  5223.                 }
  5224.             else if (mIsPressed)
  5225.                 {
  5226.                 colorIndexes[Frame] = rB;
  5227.                 colorIndexes[Fill] = rB;
  5228.                 colorIndexes[Corner] = rB;
  5229.                 colorIndexes[Light] = rB;
  5230.                 colorIndexes[TL] = rB;
  5231.                 colorIndexes[BR] = rB;
  5232.                 colorIndexes[Dark] = rB;
  5233.                 colorIndexes[Grip] = rW;
  5234.                 }
  5235.             else    // normal
  5236.                 {
  5237.                 colorIndexes[Frame] = rB;
  5238.                 colorIndexes[Fill] = rW;
  5239.                 colorIndexes[Corner] = rW;
  5240.                 colorIndexes[Light] = rW;
  5241.                 colorIndexes[TL] = rW;
  5242.                 colorIndexes[BR] = rW;
  5243.                 colorIndexes[Dark] = rW;
  5244.                 colorIndexes[Grip] = rB;
  5245.                 }
  5246.             }
  5247.         
  5248.         ::RGBForeColor(&gAGARamp[colorIndexes[Frame]]);
  5249.         ::FrameRect(&r);
  5250.         ::RGBForeColor(&gAGARamp[colorIndexes[BG]]);
  5251.         ::MoveTo(r.left, r.top);
  5252.         ::Line(0, 0);
  5253.         ::MoveTo(r.right - 1, r.top);
  5254.         ::Line(0, 0);
  5255.         ::MoveTo(r.right - 1, r.bottom - 1);
  5256.         ::Line(0, 0);
  5257.         ::MoveTo(r.left, r.bottom - 1);
  5258.         ::Line(0, 0);
  5259.         
  5260.         ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  5261.         ::InsetRect(&r, 1, 1);
  5262.         ::PaintRect(&r);
  5263.         ::InsetRect(&r, -1, -1);
  5264.         
  5265.         ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
  5266.         ::MoveTo(r.left + 1, r.top + 1);
  5267.         ::Line(0, 0);
  5268.         
  5269.         ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  5270.         ::MoveTo(r.left + 1, r.bottom - 3);
  5271.         ::LineTo(r.left + 1, r.top + 2);
  5272.         ::Move(1, -1);
  5273.         ::LineTo(r.right - 3, r.top + 1);
  5274.         
  5275.         ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  5276.         ::Move(1, 1);
  5277.         ::LineTo(r.right - 2, r.bottom - 2);
  5278.         ::LineTo(r.left + 2, r.bottom - 2);
  5279.  
  5280.         if (mIsHorizontal)
  5281.             {
  5282.             ::SetPt(&drawDirection, 0, 1);
  5283.             ::SetPt(&moveDirection, 1, 0);
  5284.             lineLength = r.bottom - r.top - 10;
  5285.             }
  5286.         else
  5287.             {
  5288.             ::SetPt(&drawDirection, 1, 0);
  5289.             ::SetPt(&moveDirection, 0, 1);
  5290.             lineLength = r.right - r.left - 10;
  5291.             }
  5292.  
  5293.         if (mEnabled)
  5294.             {
  5295.             ::MoveTo(r.left + 3 + drawDirection.h + (moveDirection.h * (((r.right - r.left) / 2) - 6)),
  5296.                     r.top + 3 + drawDirection.v + (moveDirection.v * (((r.bottom - r.top) / 2) - 6)));
  5297.  
  5298.             if (! deep)
  5299.                 ::Move(moveDirection.h, moveDirection.v);
  5300.  
  5301.             for (SInt32 i = 0; i < 3; i++)
  5302.                 {
  5303.                 ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
  5304.                 ::Line(drawDirection.h, drawDirection.v);
  5305.                 
  5306.                 ::RGBForeColor(&gAGARamp[colorIndexes[Grip]]);
  5307.                 ::Line(drawDirection.h * (lineLength-1), drawDirection.v * (lineLength-1));
  5308.                 
  5309.                 ::Move(moveDirection.h, moveDirection.v);
  5310.                 ::Move(drawDirection.h, drawDirection.v);
  5311.                 ::RGBForeColor(&gAGARamp[colorIndexes[Dark]]);
  5312.                 ::Line(- (drawDirection.h * lineLength), - (drawDirection.v * lineLength));
  5313.  
  5314.                 ::Move(moveDirection.h, moveDirection.v);
  5315.                 ::Move(- drawDirection.h, - drawDirection.v);
  5316.                 }
  5317.             }
  5318.         
  5319.         if (isGhost && deep)
  5320.             {
  5321.             // Draw the little see-thru track slides.
  5322.             // They run inverse draw direction from the grip lines.
  5323.             // To handle proportional indicators, we need to vary
  5324.             // the length of the track slides on the flat part.
  5325.             SInt32    wholeFlatLength;
  5326.             SInt32    firstFlatLength;
  5327.             SInt32    remainingFlatLength;
  5328.             
  5329.             if (mIsHorizontal)
  5330.                 wholeFlatLength = r.right - r.left - 10;
  5331.             else
  5332.                 wholeFlatLength = r.bottom - r.top - 10;
  5333.  
  5334.             firstFlatLength = wholeFlatLength / 2;
  5335.             remainingFlatLength = wholeFlatLength - firstFlatLength; // don't round down twice
  5336.  
  5337.             ::RGBForeColor(&gAGARamp[r11]);
  5338.             ::MoveTo(r.left + (drawDirection.h * 5), r.top + (drawDirection.v * 5));
  5339.             
  5340.             for (UInt32 i = 0; i < 2; i++)
  5341.                 {
  5342.                 ::Line(moveDirection.h, moveDirection.v);
  5343.                 ::RGBForeColor(&gAGARamp[r2]);
  5344.                 ::Line(moveDirection.h, moveDirection.v);
  5345.                 ::RGBForeColor(&gAGARamp[r5]);
  5346.                 ::Line(moveDirection.h * firstFlatLength, moveDirection.v * firstFlatLength);
  5347.                 ::RGBForeColor(&gAGARamp[r2]);
  5348.                 ::Line(moveDirection.h, moveDirection.v);
  5349.                 ::RGBForeColor(&gAGARamp[r9]);
  5350.                 ::Line(moveDirection.h, moveDirection.v);
  5351.                 ::RGBForeColor(&gAGARamp[r2]);
  5352.                 ::Line(moveDirection.h, moveDirection.v);
  5353.                 ::RGBForeColor(&gAGARamp[r9]);
  5354.                 ::Line(moveDirection.h, moveDirection.v);
  5355.                 ::RGBForeColor(&gAGARamp[r2]);
  5356.                 ::Line(moveDirection.h, moveDirection.v);
  5357.                 ::RGBForeColor(&gAGARamp[r9]);
  5358.                 ::Line(moveDirection.h, moveDirection.v);
  5359.                 ::RGBForeColor(&gAGARamp[r5]);
  5360.                 ::Line(moveDirection.h * remainingFlatLength, moveDirection.v * remainingFlatLength);
  5361.                 ::RGBForeColor(&gAGARamp[r7]);
  5362.                 ::Line(moveDirection.h, moveDirection.v);
  5363.                 ::RGBForeColor(&gAGARamp[r11]);
  5364.                 ::Line(0, 0);
  5365.                 
  5366.                 ::MoveTo(r.left + (drawDirection.h * 9), r.top + (drawDirection.v * 9));
  5367.                 }
  5368.             }
  5369.         }
  5370.     }
  5371.  
  5372. void AGASlider::DrawPointerIndicator(Rect* indicatorRect, Boolean isGhost)
  5373.     {
  5374.     AGADrawingEnvironment    env;
  5375.  
  5376.     // Draw the pointy slider indicator at the
  5377.     // specified location. The location will be sized
  5378.     // to account for a proportional indicator.
  5379.  
  5380.     enum { Frame, Fill, Corner, Light, TL, Grip, BR, Dark, kNumIndicatorColors };
  5381.  
  5382.     UInt8    colorIndexes[kNumIndicatorColors];
  5383.     Rect    r = *indicatorRect;
  5384.     Point    drawDirection;
  5385.     Point    moveDirection;
  5386.     SInt16    lineLength;
  5387.     SInt16    propExtra;    // extra pixels due to proportional indicator shape
  5388.  
  5389.     GDIterator    iter;
  5390.     Boolean        deep;
  5391.  
  5392.     while (iter.More(deep))
  5393.         {
  5394.         if (deep)
  5395.             {
  5396.             if (isGhost)
  5397.                 {
  5398.                 colorIndexes[Frame] = r7;
  5399.                 colorIndexes[Fill] = r2;
  5400.                 colorIndexes[Corner] = r1;
  5401.                 colorIndexes[Light] = rW;
  5402.                 colorIndexes[TL] = rW;
  5403.                 colorIndexes[Grip] = rW;
  5404.                 colorIndexes[BR] = r4;
  5405.                 colorIndexes[Dark] = r5;
  5406.                 }
  5407.             else if (! mEnabled)
  5408.                 {
  5409.                 colorIndexes[Frame] = r8;
  5410.                 colorIndexes[Fill] = r2;
  5411.                 colorIndexes[Corner] = r2;
  5412.                 colorIndexes[Light] = r2;
  5413.                 colorIndexes[TL] = r2;
  5414.                 colorIndexes[Grip] = r2;
  5415.                 colorIndexes[BR] = r2;
  5416.                 // n/a colorIndexes[Dark] = r9;
  5417.                 }
  5418.             else if (mIsPressed)
  5419.                 {
  5420.                 colorIndexes[Frame] = rB;
  5421.                 colorIndexes[Fill] = r8;
  5422.                 colorIndexes[Corner] = r3;
  5423.                 colorIndexes[Light] = r3;
  5424.                 colorIndexes[TL] = r5;
  5425.                 colorIndexes[Grip] = r5;
  5426.                 colorIndexes[BR] = r10;
  5427.                 colorIndexes[Dark] = r12;
  5428.                 }
  5429.             else // normal
  5430.                 {
  5431.                 colorIndexes[Frame] = rB;
  5432.                 colorIndexes[Fill] = r5;
  5433.                 colorIndexes[Corner] = r1;
  5434.                 colorIndexes[Light] = r1;
  5435.                 colorIndexes[TL] = r3;
  5436.                 colorIndexes[Grip] = r3;
  5437.                 colorIndexes[BR] = r8;
  5438.                 colorIndexes[Dark] = r10;
  5439.                 }
  5440.             }
  5441.         else    // 1-bit
  5442.             {
  5443.             if (isGhost)
  5444.                 {
  5445.                 colorIndexes[Frame] = rB;
  5446.                 colorIndexes[Fill] = rW;
  5447.                 colorIndexes[Corner] = rW;
  5448.                 colorIndexes[Light] = rW;
  5449.                 colorIndexes[TL] = rW;
  5450.                 colorIndexes[Grip] = rW;
  5451.                 colorIndexes[BR] = rW;
  5452.                 colorIndexes[Dark] = rW;
  5453.                 }
  5454.             else if (! mEnabled)
  5455.                 {
  5456.                 colorIndexes[Frame] = rB;
  5457.                 colorIndexes[Fill] = rW;
  5458.                 colorIndexes[Corner] = rW;
  5459.                 colorIndexes[Light] = rW;
  5460.                 colorIndexes[TL] = rW;
  5461.                 colorIndexes[Grip] = rW;
  5462.                 colorIndexes[BR] = rW;
  5463.                 colorIndexes[Dark] = rW;
  5464.                 }
  5465.             else if (mIsPressed)
  5466.                 {
  5467.                 colorIndexes[Frame] = rB;
  5468.                 colorIndexes[Fill] = rB;
  5469.                 colorIndexes[Corner] = rB;
  5470.                 colorIndexes[Light] = rB;
  5471.                 colorIndexes[TL] = rB;
  5472.                 colorIndexes[Grip] = rW;
  5473.                 colorIndexes[BR] = rB;
  5474.                 colorIndexes[Dark] = rB;
  5475.                 }
  5476.             else // normal
  5477.                 {
  5478.                 colorIndexes[Frame] = rB;
  5479.                 colorIndexes[Fill] = rW;
  5480.                 colorIndexes[Corner] = rW;
  5481.                 colorIndexes[Light] = rW;
  5482.                 colorIndexes[TL] = rW;
  5483.                 colorIndexes[Grip] = rB;
  5484.                 colorIndexes[BR] = rW;
  5485.                 colorIndexes[Dark] = rW;
  5486.                 }
  5487.             }
  5488.  
  5489.         if (mIsHorizontal)
  5490.             {
  5491.             ::SetPt(&drawDirection, 0, 1);
  5492.             ::SetPt(&moveDirection, 1, 0);
  5493.             lineLength = r.bottom - r.top - 11;
  5494.             propExtra = MaxSInt16(0, r.right - r.left - 15);
  5495.             }
  5496.         else
  5497.             {
  5498.             ::SetPt(&drawDirection, 1, 0);
  5499.             ::SetPt(&moveDirection, 0, 1);
  5500.             lineLength = r.right - r.left - 11;
  5501.             propExtra = MaxSInt16(0, r.bottom - r.top - 15);
  5502.             }
  5503.         
  5504.         PolyHandle    pointerPoly = ::OpenPoly();
  5505.         
  5506.         this->BuildPointerIndicator(indicatorRect);
  5507.         
  5508.         ::ClosePoly();
  5509.         
  5510.         ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  5511.         ::PaintPoly(pointerPoly);
  5512.         ::RGBForeColor(&gAGARamp[colorIndexes[Frame]]);
  5513.         ::FramePoly(pointerPoly);
  5514.         
  5515.         ::KillPoly(pointerPoly);
  5516.  
  5517.         if (mIsHorizontal)
  5518.             {
  5519.             if (RuntimeJustify(mJustification) == teFlushLeft)
  5520.                 {
  5521.                 ::MoveTo(r.left + 1, r.top + 1);
  5522.                 ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
  5523.                 ::Line(0, 0);
  5524.                 ::MoveTo(r.right - 2, r.top + 2);
  5525.                 ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  5526.                 ::LineTo(r.right - 2, r.top + 9);
  5527.                 ::Line(-5, 5);
  5528.                 ::Line(-2 - propExtra, 0);
  5529.                 ::Line(-5, -5);
  5530.                 ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  5531.                 ::LineTo(r.left + 1, r.top + 2);
  5532.                 ::Line(1, -1);
  5533.                 ::LineTo(r.right - 3, r.top + 1);
  5534.                 }
  5535.             else
  5536.                 {
  5537.                 ::MoveTo(r.right - 6, r.top + 2);
  5538.                 ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  5539.                 ::Line(4, 4);
  5540.                 ::LineTo(r.right - 2, r.bottom - 2);
  5541.                 ::LineTo(r.left + 2, r.bottom - 2);
  5542.                 ::Move(-1, -1);
  5543.                 ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  5544.                 ::Line(0, -7);
  5545.                 ::Line(5, -5);
  5546.                 ::Line(1 + propExtra, 0);
  5547.                 ::MoveTo(r.left + 6, r.top + 1);
  5548.                 ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
  5549.                 ::Line(0, 0);
  5550.                 ::Move(-5, 5);
  5551.                 ::Line(0, 0);
  5552.                 }
  5553.             }
  5554.         else
  5555.             {
  5556.             if (RuntimeJustify(mJustification) == teFlushLeft)
  5557.                 {
  5558.                 ::MoveTo(r.left + 1, r.top + 1);
  5559.                 ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
  5560.                 ::Line(0, 0);
  5561.                 ::MoveTo(r.left + 1, r.bottom - 3);
  5562.                 ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  5563.                 ::LineTo(r.left + 1, r.top + 2);
  5564.                 ::Line(1, -1);
  5565.                 ::Line(7, 0);
  5566.                 ::Move(1, 1);
  5567.                 ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  5568.                 ::Line(4, 4);
  5569.                 ::Line(0, 2 + propExtra);
  5570.                 ::Line(-5, 5);
  5571.                 ::Line(-7, 0);
  5572.                 }
  5573.             else
  5574.                 {
  5575.                 ::MoveTo(r.left + 2, r.top + 9 + propExtra);
  5576.                 ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  5577.                 ::Line(4, 4);
  5578.                 ::LineTo(r.right - 2, r.bottom - 2);
  5579.                 ::LineTo(r.right - 2, r.top + 2);
  5580.                 ::Move(-1, -1);
  5581.                 ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  5582.                 ::Line(-7, 0);
  5583.                 ::Line(-5, 5);
  5584.                 ::Line(0, 1 + propExtra);
  5585.                 ::Move(0, - (1 + propExtra));
  5586.                 ::RGBForeColor(&gAGARamp[colorIndexes[Corner]]);
  5587.                 ::Line(0, 0);
  5588.                 ::Move(5, -5);
  5589.                 ::Line(0, 0);
  5590.                 }
  5591.             }
  5592.         
  5593.         if (mEnabled)
  5594.             {
  5595.             ::MoveTo(r.left + 3 + (moveDirection.h * (((r.right - r.left) / 2) - 6)),
  5596.                     r.top + 3 + (moveDirection.v * (((r.bottom - r.top) / 2) - 6)));
  5597.  
  5598.             if (RuntimeJustify(mJustification) == teFlushRight)
  5599.                 ::Move(2 * drawDirection.h, 2 * drawDirection.v);
  5600.  
  5601.             if (! deep)
  5602.                 ::Move(moveDirection.h, moveDirection.v);
  5603.  
  5604.             for (SInt32 i = 0; i < 3; i++)
  5605.                 {
  5606.                 ::RGBForeColor(&gAGARamp[colorIndexes[Light]]);
  5607.                 ::Line(drawDirection.h, drawDirection.v);
  5608.                 
  5609.                 ::RGBForeColor(&gAGARamp[colorIndexes[Grip]]);
  5610.                 ::Line(drawDirection.h * (lineLength-1), drawDirection.v * (lineLength-1));
  5611.                 
  5612.                 ::Move(moveDirection.h, moveDirection.v);
  5613.                 ::Move(drawDirection.h, drawDirection.v);
  5614.                 ::RGBForeColor(&gAGARamp[colorIndexes[Dark]]);
  5615.                 ::Line(- (drawDirection.h * lineLength), - (drawDirection.v * lineLength));
  5616.  
  5617.                 ::Move(moveDirection.h, moveDirection.v);
  5618.                 ::Move(- drawDirection.h, - drawDirection.v);
  5619.                 }
  5620.             }
  5621.         
  5622.         if (isGhost && deep)
  5623.             {
  5624.             // Draw the little see-thru track slides.
  5625.             // They run inverse draw direction from the grip lines.
  5626.             // To handle proportional indicators, we need to vary
  5627.             // the length of the track slides on the flat part.
  5628.             SInt32    wholeFlatLength;
  5629.             SInt32    firstFlatLength;
  5630.             SInt32    remainingFlatLength;
  5631.             
  5632.             if (mIsHorizontal)
  5633.                 wholeFlatLength = r.right - r.left - 10;
  5634.             else
  5635.                 wholeFlatLength = r.bottom - r.top - 10;
  5636.  
  5637.             firstFlatLength = wholeFlatLength / 2;
  5638.             remainingFlatLength = wholeFlatLength - firstFlatLength; // don't round down twice
  5639.  
  5640.             ::RGBForeColor(&gAGARamp[r11]);
  5641.             ::MoveTo(r.left + (drawDirection.h * 4), r.top + (drawDirection.v * 4));
  5642.             
  5643.             for (UInt32 i = 0; i < 2; i++)
  5644.                 {
  5645.                 if (RuntimeJustify(mJustification) == teFlushRight)
  5646.                     ::Move(3 * drawDirection.h, 3 * drawDirection.v);
  5647.  
  5648.                 ::Line(moveDirection.h, moveDirection.v);
  5649.                 ::RGBForeColor(&gAGARamp[r2]);
  5650.                 ::Line(moveDirection.h, moveDirection.v);
  5651.                 ::RGBForeColor(&gAGARamp[r5]);
  5652.                 ::Line(moveDirection.h * firstFlatLength, moveDirection.v * firstFlatLength);
  5653.                 ::RGBForeColor(&gAGARamp[r2]);
  5654.                 ::Line(moveDirection.h, moveDirection.v);
  5655.                 ::RGBForeColor(&gAGARamp[r9]);
  5656.                 ::Line(moveDirection.h, moveDirection.v);
  5657.                 ::RGBForeColor(&gAGARamp[r2]);
  5658.                 ::Line(moveDirection.h, moveDirection.v);
  5659.                 ::RGBForeColor(&gAGARamp[r9]);
  5660.                 ::Line(moveDirection.h, moveDirection.v);
  5661.                 ::RGBForeColor(&gAGARamp[r2]);
  5662.                 ::Line(moveDirection.h, moveDirection.v);
  5663.                 ::RGBForeColor(&gAGARamp[r9]);
  5664.                 ::Line(moveDirection.h, moveDirection.v);
  5665.                 ::RGBForeColor(&gAGARamp[r5]);
  5666.                 ::Line(moveDirection.h * remainingFlatLength, moveDirection.v * remainingFlatLength);
  5667.                 ::RGBForeColor(&gAGARamp[r7]);
  5668.                 ::Line(moveDirection.h, moveDirection.v);
  5669.                 ::RGBForeColor(&gAGARamp[r11]);
  5670.                 ::Line(0, 0);
  5671.                 
  5672.                 ::MoveTo(r.left + (drawDirection.h * 8), r.top + (drawDirection.v * 8));
  5673.                 }
  5674.             }
  5675.         }
  5676.     }
  5677.  
  5678. void AGASlider::BuildPointerIndicator(Rect* indicatorRect)
  5679.     {
  5680.     // Perform the QuickDraw framing commands to build the
  5681.     // pointy indicator. This function is called while wrapped
  5682.     // in polygon or region building calls. The caller will
  5683.     // use the resulting polygon or region to frame, fill,
  5684.     // or clip.
  5685.  
  5686.     Rect    r = *indicatorRect;
  5687.     SInt16    propExtra;
  5688.  
  5689.     if (mIsHorizontal)
  5690.         {
  5691.         propExtra = MaxSInt16(0, r.right - r.left - 15);
  5692.  
  5693.         if (RuntimeJustify(mJustification) == teFlushLeft)
  5694.             {
  5695.             ::MoveTo(r.right - 1, r.top + 1);
  5696.             ::LineTo(r.right - 1, r.bottom - 7);
  5697.             ::Line(-6, 6);
  5698.             ::Line(-2 - propExtra, 0);
  5699.             ::Line(-6, -6);
  5700.             ::LineTo(r.left, r.top + 1);
  5701.             ::Line(1, -1);
  5702.             ::LineTo(r.right - 2, r.top);
  5703.             ::Line(1, 1);
  5704.             }
  5705.         else
  5706.             {
  5707.             ::MoveTo(r.left, r.bottom - 2);
  5708.             ::LineTo(r.left, r.top + 6);
  5709.             ::Line(6, -6);
  5710.             ::Line(2 + propExtra, 0);
  5711.             ::Line(6, 6);
  5712.             ::LineTo(r.right - 1, r.bottom - 2);
  5713.             ::Line(-1, 1);
  5714.             ::LineTo(r.left + 1, r.bottom - 1);
  5715.             ::Line(-1, -1);
  5716.             }
  5717.         }
  5718.     else
  5719.         {
  5720.         propExtra = MaxSInt16(0, r.bottom - r.top - 15);
  5721.  
  5722.         if (RuntimeJustify(mJustification) == teFlushLeft)
  5723.             {
  5724.             ::MoveTo(r.left + 1, r.top);
  5725.             ::LineTo(r.right - 7, r.top);
  5726.             ::Line(6, 6);
  5727.             ::Line(0, 2 + propExtra);
  5728.             ::Line(-6, 6);
  5729.             ::LineTo(r.left + 1, r.bottom - 1);
  5730.             ::Line(-1, -1);
  5731.             ::LineTo(r.left, r.top + 1);
  5732.             ::Line(1, -1);
  5733.             }
  5734.         else
  5735.             {
  5736.             ::MoveTo(r.right - 2, r.bottom - 1);
  5737.             ::LineTo(r.left + 6, r.bottom - 1);
  5738.             ::Line(-6, -6);
  5739.             ::Line(0, -2 - propExtra);
  5740.             ::Line(6, -6);
  5741.             ::LineTo(r.right - 2, r.top);
  5742.             ::Line(1, 1);
  5743.             ::LineTo(r.right - 1, r.bottom - 2);
  5744.             ::Line(-1, 1);
  5745.             }
  5746.         }
  5747.     }
  5748.  
  5749. void AGASlider::RemoveIndicator(SInt32 newValue)
  5750.     {
  5751.     // Draw the background to remove the indicator
  5752.     // at the specified value.
  5753.  
  5754.     //
  5755.     // Set clipping so we only draw the track to
  5756.     // wipe out the old indicator, but not where
  5757.     // the new indicator will get drawn anyway.
  5758.     // This reduces flicker. Polygon geometry makes
  5759.     // tweaking necessary and still imperfect.
  5760.     //
  5761.  
  5762.     ::GetClip(mgSavedIndicatorClip);
  5763.  
  5764.     if (newValue != mValue)
  5765.         {
  5766.         Rect    oldIndicatorBox;
  5767.         Rect    newIndicatorBox;
  5768.  
  5769.         this->GetIndicatorBox(mValue, &oldIndicatorBox);
  5770.         this->GetIndicatorBox(newValue, &newIndicatorBox);
  5771.         
  5772.         if (mSliderKind == kRectSlider)
  5773.             {
  5774.             ::RectRgn(mgOldIndicatorClip, &oldIndicatorBox);
  5775.             ::RectRgn(mgNewIndicatorClip, &newIndicatorBox);
  5776.             }
  5777.         else
  5778.             {
  5779.             //
  5780.             // For optimal clipping, because of polygon and
  5781.             // region geometry, we have to tweak the regions
  5782.             // a little bit.
  5783.             //
  5784.             
  5785.             RgnHandle    tempRegion = ::NewRgn();
  5786.  
  5787.             ::OpenRgn();
  5788.             this->BuildPointerIndicator(&oldIndicatorBox);
  5789.             ::CloseRgn(mgOldIndicatorClip);
  5790.             ::CopyRgn(mgOldIndicatorClip, tempRegion);
  5791.             ::OffsetRgn(tempRegion, 1, 1);
  5792.             ::InsetRgn(tempRegion, -1, -1);
  5793.             ::UnionRgn(mgOldIndicatorClip, tempRegion, mgOldIndicatorClip);
  5794.  
  5795.             ::OpenRgn();
  5796.             this->BuildPointerIndicator(&newIndicatorBox);
  5797.             ::CloseRgn(mgNewIndicatorClip);
  5798.             ::CopyRgn(mgNewIndicatorClip, tempRegion);
  5799.             ::UnionRgn(mgNewIndicatorClip, tempRegion, mgNewIndicatorClip);
  5800.             
  5801.             ::DisposeRgn(tempRegion);
  5802.             }
  5803.  
  5804.         ::DiffRgn(mgOldIndicatorClip, mgNewIndicatorClip, mgOldIndicatorClip);
  5805.  
  5806.         ::SetClip(mgOldIndicatorClip);
  5807.         }
  5808.  
  5809.     this->DrawIndicatorTrack();
  5810.  
  5811.     ::SetClip(mgSavedIndicatorClip);
  5812.     }
  5813.  
  5814. void AGASlider::RemoveGhost(SInt32 /*newValue*/)
  5815.     {
  5816.     // Draw the background necessary to remove the
  5817.     // ghost indicator while not removing the solid
  5818.     // value indicator.
  5819.  
  5820.     Rect    r;
  5821.     RgnHandle    savedClip = ::NewRgn();
  5822.     
  5823.     ::GetClip(savedClip);
  5824.  
  5825.     this->GetIndicatorBox(mGhostValue, &r);
  5826.     ::ClipRect(&r);
  5827.     this->DrawIndicatorTrack();
  5828.     this->DrawIndicator();
  5829.     
  5830.     ::SetClip(savedClip);
  5831.     ::DisposeRgn(savedClip);
  5832.     }
  5833.  
  5834. void AGASlider::GetTrackFrame(Rect* trackFrame, Boolean includeBackground)
  5835.     {
  5836.     // Return the rectangle that bounds just the indicator
  5837.     // track, including shading pixels but not the area covered
  5838.     // by the indicator itself.
  5839.  
  5840.     Boolean    leftJustify = (RuntimeJustify(mJustification) == teFlushLeft);
  5841.  
  5842.     *trackFrame = mBounds;
  5843.     
  5844.     if (mIsHorizontal)
  5845.         {
  5846.         if (leftJustify)
  5847.             {
  5848.             trackFrame->top += 4;
  5849.             trackFrame->bottom = trackFrame->top + 7;
  5850.             }
  5851.         else
  5852.             {
  5853.             trackFrame->bottom -= 4;
  5854.             trackFrame->top = trackFrame->bottom - 7;
  5855.             }
  5856.         
  5857.         if (includeBackground)
  5858.             {
  5859.             trackFrame->top -= leftJustify ? 4 : 6;
  5860.             trackFrame->bottom += leftJustify ? 6 : 4;
  5861.             }
  5862.         }
  5863.     else
  5864.         {
  5865.         if (leftJustify)
  5866.             {
  5867.             trackFrame->left += 4;
  5868.             trackFrame->right = trackFrame->left + 7;
  5869.             }
  5870.         else
  5871.             {
  5872.             trackFrame->right -= 4;
  5873.             trackFrame->left = trackFrame->right - 7;
  5874.             }
  5875.         
  5876.         if (includeBackground)
  5877.             {
  5878.             trackFrame->left -= leftJustify ? 4 : 6;
  5879.             trackFrame->right += leftJustify ? 6 : 4;
  5880.             }
  5881.         }
  5882.     }
  5883.  
  5884. void AGASlider::GetIndicatorBox(SInt32 indicatorValue, Rect* indicatorBox)
  5885.     {
  5886.     // Return the box that defines the indicator's location
  5887.     // given the specified indicator value.
  5888.  
  5889.     Rect    r = mBounds;
  5890.     SInt32    startPt;
  5891.     SInt32    valuePt;
  5892.     SInt32    stopPt;
  5893.  
  5894.     this->GetIndicatorSpan(indicatorValue, &startPt, &valuePt, &stopPt);
  5895.     
  5896.     if (mIsHorizontal)
  5897.         {
  5898.         r.left = startPt;
  5899.         r.right = stopPt;
  5900.  
  5901.         if (RuntimeJustify(mJustification) == teFlushLeft)
  5902.             {
  5903.             if (mSliderKind == kPointerSlider)
  5904.                 r.top++;
  5905.  
  5906.             r.bottom = r.top + kIndicatorWidth;
  5907.             }
  5908.         else
  5909.             {
  5910.             if (mSliderKind == kPointerSlider)
  5911.                 r.bottom--;
  5912.  
  5913.             r.top = r.bottom - kIndicatorWidth;
  5914.             }
  5915.         }
  5916.     else
  5917.         {
  5918.         r.top = startPt;
  5919.         r.bottom = stopPt;
  5920.  
  5921.         if (RuntimeJustify(mJustification) == teFlushLeft)
  5922.             {
  5923.             if (mSliderKind == kPointerSlider)
  5924.                 r.left++;
  5925.  
  5926.             r.right = r.left + kIndicatorWidth;
  5927.             }
  5928.         else
  5929.             {
  5930.             if (mSliderKind == kPointerSlider)
  5931.                 r.right--;
  5932.  
  5933.             r.left = r.right - kIndicatorWidth;
  5934.             }
  5935.         }
  5936.     
  5937.     *indicatorBox = r;
  5938.     }
  5939.  
  5940. SInt32 AGASlider::GetIndicatorPixelRange(SInt32* proportionalIndicatorPixels)
  5941.     {
  5942.     // Return the pixel range that the center point of the indicator
  5943.     // can travel along the track, and also return the amount of
  5944.     // range reduction that is caused by proportional indicator growth.
  5945.     // Non-proportional indicators use the full track range, minus
  5946.     // the size of the indicator itself.
  5947.  
  5948.     SInt32    range;
  5949.     SInt32    indicatorInset = (mSliderKind == kRectSlider) ? kRectIndicatorPixelInset : kPointerIndicatorPixelInset;
  5950.     
  5951.     *proportionalIndicatorPixels = 0;
  5952.  
  5953.     if (mIsHorizontal)
  5954.         range = mBounds.right - mBounds.left - (2 * (kEndGapSize + indicatorInset)) + 1;
  5955.     else
  5956.         range = mBounds.bottom - mBounds.top - (2 * (kEndGapSize + indicatorInset)) + 1;
  5957.  
  5958.     if (mIsProportional)
  5959.         {
  5960.         SInt32    pagePixels;
  5961.         
  5962.         pagePixels =
  5963.             (range * (((float) mPageSize) / ((float) (mMaximum - mMinimum))));
  5964.         
  5965.         if (pagePixels > 0)
  5966.             {
  5967.             range -= pagePixels;
  5968.             *proportionalIndicatorPixels = pagePixels;
  5969.             }
  5970.         }
  5971.     
  5972.     return range;
  5973.     }
  5974.  
  5975. void AGASlider::GetIndicatorPixelEnds(SInt32* startPt, SInt32* stopPt)
  5976.     {
  5977.     // Return the start and end pixel locations of the indicator
  5978.     // track traveled by the center point of the indicator.
  5979.  
  5980.     SInt32    dontCare;
  5981.     SInt32    range = this->GetIndicatorPixelRange(&dontCare);
  5982.  
  5983.     if (mIsHorizontal)
  5984.         *startPt = ((mBounds.left + mBounds.right) / 2) - (range / 2) - 1;
  5985.     else
  5986.         *startPt = ((mBounds.top + mBounds.bottom) / 2) - (range / 2) - 1;
  5987.  
  5988.     *stopPt = *startPt + range;    // avoid rounding of 1/2 pixel twice
  5989.     }
  5990.  
  5991. void AGASlider::GetIndicatorSpan(SInt32 value, SInt32* startPt, SInt32* valuePt, SInt32* stopPt)
  5992.     {
  5993.     // Return the pixel locations of the indicator's ends and value.
  5994.  
  5995.     SInt32    proportionalIndicatorPixels;
  5996.     SInt32    trackStart;
  5997.     SInt32    trackStop;
  5998.     SInt32    trackRange = this->GetIndicatorPixelRange(&proportionalIndicatorPixels);
  5999.     SInt32    indicatorInset = (mSliderKind == kRectSlider) ? kRectIndicatorPixelInset : kPointerIndicatorPixelInset;
  6000.     
  6001.     this->GetIndicatorPixelEnds(&trackStart, &trackStop);
  6002.     
  6003.     *valuePt = trackStart +
  6004.         (trackRange * (((float) (value - mMinimum)) / ((float) (mMaximum - mMinimum))));
  6005.  
  6006.     *startPt = *valuePt - indicatorInset - (proportionalIndicatorPixels / 2);
  6007.     *stopPt = *startPt + (2 * indicatorInset) + proportionalIndicatorPixels + 1;
  6008.     }
  6009.  
  6010. void AGASlider::DisposeLabels()
  6011.     {
  6012.     // Release the memory allocated for slider labels.
  6013.  
  6014.     if (mLabelStringHandles != NULL)
  6015.         {
  6016.         UInt32    numHandles = ::GetHandleSize(mLabelStringHandles) / sizeof(StringHandle);
  6017.         
  6018.         for (UInt32 i = 0; i < numHandles; i++)
  6019.             ::DisposeHandle((Handle) ((StringHandle*)(*mLabelStringHandles))[i]);
  6020.  
  6021.         ::DisposeHandle(mLabelStringHandles);
  6022.         }
  6023.     }
  6024.  
  6025. //
  6026. // AGAPopupMenu ---------------------------------------------------------------
  6027. //
  6028. // This class implements a standard popup menu look, and handles the
  6029. // mouse by calling PopUpMenuSelect such that the visible menu is
  6030. // located where the AGA says it should.
  6031. //
  6032.  
  6033. AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment)
  6034. : AGAObject(bounds)
  6035.     {
  6036.     // Construct without a menu installed.
  6037.  
  6038.     mMenuID = 0;
  6039.     mMenuRef = NULL;
  6040.     mMenuRefDisposalKind = kDontDispose;
  6041.     mCurrentItemNo = 1;
  6042.     mWidthAdjust = adjustment;
  6043.     mTitleStyle = titleStyle;
  6044.     mTextStyle = textStyle;
  6045.     AGA_PLstrcpy(mTitle, title);
  6046.     mTitleOffset = titleOffset;
  6047.     mTitleJustification = titleJustification;
  6048.     }
  6049.  
  6050. AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment, MenuRef itsMenuRef, DisposalKind menuRefDisposalKind)
  6051. : AGAObject(bounds)
  6052.     {
  6053.     // Construct with specified MenuRef.
  6054.  
  6055.     if (itsMenuRef == NULL)
  6056.         mMenuID = 0;
  6057.     else
  6058.         mMenuID = (**itsMenuRef).menuID;
  6059.  
  6060.     mMenuRef = itsMenuRef;
  6061.     mMenuRefDisposalKind = menuRefDisposalKind;
  6062.  
  6063.     mCurrentItemNo = 1;
  6064.     mWidthAdjust = adjustment;
  6065.     mTitleStyle = titleStyle;
  6066.     mTextStyle = textStyle;
  6067.     AGA_PLstrcpy(mTitle, title);
  6068.     mTitleOffset = titleOffset;
  6069.     mTitleJustification = titleJustification;
  6070.     }
  6071.  
  6072. AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment, SInt16 itemsStringListID, SInt16 newMenuID)
  6073. : AGAObject(bounds)
  6074.     {
  6075.     // Construct with menu built from strings in a 'STR#' resource.
  6076.  
  6077.     mMenuID = newMenuID;
  6078.     mMenuRef = ::NewMenu(newMenuID, "\pAGA");
  6079.     mMenuRefDisposalKind = kDispose;
  6080.     mCurrentItemNo = 1;
  6081.     mWidthAdjust = adjustment;
  6082.     mTitleStyle = titleStyle;
  6083.     mTextStyle = textStyle;
  6084.     AGA_PLstrcpy(mTitle, title);
  6085.     mTitleOffset = titleOffset;
  6086.     mTitleJustification = titleJustification;
  6087.     
  6088.     Handle    stringListHandle = ::GetResource('STR#', itemsStringListID);
  6089.     if (stringListHandle != NULL)
  6090.         {
  6091.         SInt16    numStrings = **((SInt16 **) stringListHandle);
  6092.         
  6093.         for (SInt16 stringIndex = 1; stringIndex <= numStrings; stringIndex++)
  6094.             {
  6095.             Str255    aString;
  6096.             
  6097.             ::GetIndString(aString, itemsStringListID, stringIndex);
  6098.             
  6099.             // Use SetMenuItemText to avoid metacharacter interpretation.
  6100.             ::AppendMenu(mMenuRef, "\pXXX");
  6101.             ::SetMenuItemText(mMenuRef, stringIndex, aString);
  6102.             }
  6103.         }
  6104.     }
  6105.  
  6106. AGAPopupMenu::AGAPopupMenu(Rect* bounds, SInt16 titleOffset, StringPtr title, SInt32 titleJustification, const AGATextStyle& titleStyle, const AGATextStyle& textStyle, WidthAdjust adjustment, ResType appendResourceType, SInt16 newMenuID)
  6107. : AGAObject(bounds)
  6108.     {
  6109.     // Construct with menu built from specified appended resource type.
  6110.     // Typical use is for a Fonts menu, using resource type 'FOND'.
  6111.  
  6112.     mMenuID = newMenuID;
  6113.     mMenuRef = ::NewMenu(newMenuID, "\pAGA");
  6114.     mMenuRefDisposalKind = kDispose;
  6115.     mCurrentItemNo = 1;
  6116.     mWidthAdjust = adjustment;
  6117.     mTitleStyle = titleStyle;
  6118.     mTextStyle = textStyle;
  6119.     AGA_PLstrcpy(mTitle, title);
  6120.     mTitleOffset = titleOffset;
  6121.     mTitleJustification = titleJustification;
  6122.     
  6123.     ::AppendResMenu(mMenuRef, appendResourceType);
  6124.     }
  6125.  
  6126. AGAPopupMenu::~AGAPopupMenu()
  6127.     {
  6128.     // Destruct by cleaning up the menu data.
  6129.     // This depends on how the menu was created.
  6130.  
  6131.     this->DisposeExistingMenuRef();
  6132.     }
  6133.  
  6134. void AGAPopupMenu::DisposeExistingMenuRef()
  6135.     {
  6136.     // Clean up the menu data based on how it was created
  6137.     // or how the client code specified.
  6138.  
  6139.     if (mMenuRef != NULL)
  6140.         {
  6141.         if (mMenuRefDisposalKind == kDispose)
  6142.             ::DisposeMenu(mMenuRef);
  6143.         else if (mMenuRefDisposalKind == kRelease)
  6144.             ::ReleaseResource((Handle) mMenuRef);
  6145.         }
  6146.  
  6147.     mMenuRefDisposalKind = kDontDispose;
  6148.     }
  6149.  
  6150. void AGAPopupMenu::SetMenuRef(MenuRef itsMenuRef, DisposalKind menuRefDisposalKind)
  6151.     {
  6152.     // Install the specified MenuRef.
  6153.  
  6154.     this->DisposeExistingMenuRef();
  6155.  
  6156.     if (itsMenuRef == NULL)
  6157.         mMenuID = 0;
  6158.     else
  6159.         mMenuID = (**itsMenuRef).menuID;
  6160.  
  6161.     mMenuRef = itsMenuRef;
  6162.     mMenuRefDisposalKind = menuRefDisposalKind;
  6163.  
  6164.     mCurrentItemNo = 1;
  6165.     }
  6166.  
  6167. void AGAPopupMenu::SetWidthAdjustment(WidthAdjust adjustment)
  6168.     {
  6169.     // Set the width adjustment, which determines how wide
  6170.     // the closed menu appears.
  6171.  
  6172.     mWidthAdjust = adjustment;
  6173.     }
  6174.  
  6175. void AGAPopupMenu::DrawObject()
  6176.     {
  6177.     // Draw the unpressed popup menu "button".
  6178.  
  6179.     this->DrawButton(kNotPressed);
  6180.     }
  6181.  
  6182. Boolean AGAPopupMenu::TrackMouse(Point /*mouseLocation*/)
  6183.     {
  6184.     if (! mEnabled)
  6185.         return false;
  6186.  
  6187.     // Track the mouse in the popup, and return true
  6188.     // if it caused the current popup selection to change.
  6189.  
  6190.     Boolean    selectionChanged;
  6191.     SInt32    menuResult;
  6192.     Point    globalOrigin;
  6193.     
  6194.     this->DrawButton(kPressed);
  6195.     
  6196.     ::SetPt(&globalOrigin, mBounds.left + mTitleOffset, mBounds.bottom);
  6197.     ::LocalToGlobal(&globalOrigin);
  6198.  
  6199.     ::InsertMenu(mMenuRef, -1);            // put it in the hierarchical list
  6200.     
  6201.     if ((mTextStyle.mFontNum != 0) || ((mTextStyle.mFontSize != 0) && (mTextStyle.mFontSize != 12)))//sizer.mIsCustom)
  6202.         ::SetItemMark(mMenuRef, mCurrentItemNo, '•');
  6203.     else
  6204.         ::CheckItem(mMenuRef, mCurrentItemNo, true);
  6205.  
  6206.     {    // create scope so AGACustomPopupMenuSizer is destructed right away
  6207.     AGACustomPopupMenuSizer    sizer(mTextStyle.mFontNum, mTextStyle.mFontSize);
  6208.     
  6209.     menuResult = ::PopUpMenuSelect(mMenuRef, globalOrigin.v, globalOrigin.h + 1, 1);
  6210.     }
  6211.  
  6212.     ::CheckItem(mMenuRef, mCurrentItemNo, false);
  6213.  
  6214.     ::DeleteMenu((**mMenuRef).menuID);    // get it out of the hierarchical list
  6215.  
  6216.     selectionChanged = (menuResult != 0);
  6217.  
  6218.     if (selectionChanged)
  6219.         this->SetCurrentItemNo(menuResult & 0x0000FFFF, kDontRedraw);
  6220.     
  6221.     this->DrawButton(kNotPressed);
  6222.  
  6223.     return selectionChanged;
  6224.     }
  6225.  
  6226. SInt16 AGAPopupMenu::GetCurrentItemNo()
  6227.     {
  6228.     // Return the currently selected item index (1-based).
  6229.  
  6230.     return mCurrentItemNo;
  6231.     }
  6232.  
  6233. void AGAPopupMenu::SetCurrentItemNo(SInt16 newItemNo, Boolean redraw)
  6234.     {
  6235.     // Set the current item index (1-based), optionally redraw.
  6236.  
  6237.     mCurrentItemNo = newItemNo;
  6238.     
  6239.     if (redraw)
  6240.         this->DrawButton(kNotPressed);
  6241.     }
  6242.  
  6243. void AGAPopupMenu::GetCurrentItemText(StringPtr itemText)
  6244.     {
  6245.     // Return the menu item text of the currently selected item.
  6246.  
  6247.     itemText[0] = 0;
  6248.     
  6249.     if (mMenuRef != NULL)
  6250.         ::GetMenuItemText(mMenuRef, this->GetCurrentItemNo(), itemText);
  6251.     }
  6252.  
  6253. Boolean AGAPopupMenu::SetCurrentItemText(StringPtr itemTextToMatch, Boolean redraw)
  6254.     {
  6255.     // Set the current item index to the item whose text
  6256.     // matches the specified string. Optionally redraw.
  6257.  
  6258.     Boolean    wasMatchFound = false;
  6259.     SInt16    numItems = 0;
  6260.  
  6261.     if (mMenuRef != NULL)
  6262.         numItems = ::CountMenuItems(mMenuRef);
  6263.  
  6264.     for (SInt16 itemIndex = 1; itemIndex <= numItems; itemIndex++)
  6265.         {
  6266.         Str255    itemText;
  6267.  
  6268.         ::GetMenuItemText(mMenuRef, itemIndex, itemText);
  6269.  
  6270.         if (::EqualString(itemText, itemTextToMatch, true, true))
  6271.             {
  6272.             wasMatchFound = true;
  6273.             this->SetCurrentItemNo(itemIndex, redraw);
  6274.             break;
  6275.             }
  6276.         }
  6277.  
  6278.     return wasMatchFound;
  6279.     }
  6280.  
  6281. void AGAPopupMenu::SetTitle(StringPtr newTitle, Boolean redraw)
  6282.     {
  6283.     // Install the new title. Optionally redraw.
  6284.  
  6285.     AGA_PLstrcpy(mTitle, newTitle);
  6286.     
  6287.     if (redraw)
  6288.         this->DrawButton(kNotPressed);
  6289.     }
  6290.  
  6291. void AGAPopupMenu::DrawButton(Boolean pressed)
  6292.     {
  6293.     // Draw the popup button in the specified state.
  6294.  
  6295.     GDIterator    iter;
  6296.     Boolean        deep;
  6297.  
  6298.     while (iter.More(deep))
  6299.         {
  6300.         if (! mEnabled)
  6301.             this->DrawButtonDisabled(deep);
  6302.         else if (pressed)
  6303.             this->DrawButtonPressed(deep);
  6304.         else
  6305.             this->DrawButtonNormal(deep);
  6306.         }
  6307.     }
  6308.  
  6309. void AGAPopupMenu::DrawButtonNormal(Boolean deep)
  6310.     {
  6311.     AGADrawingEnvironment    env;
  6312.  
  6313.     // Draw the popup button in enabled/unpressed state.
  6314.  
  6315.     Rect    r;
  6316.     Str255    currentItemText;
  6317.     
  6318.     this->GetCurrentItemText(currentItemText);
  6319.     this->GetButtonBounds(&r);
  6320.     
  6321.     ::PenSize(1, 1);
  6322.  
  6323.     if (deep)
  6324.         {
  6325.         // Fill the interior.
  6326.         ::InsetRect(&r, 1, 1);
  6327.         ::RGBForeColor(&gAGARamp[r2]);
  6328.         ::PaintRect(&r);
  6329.         ::InsetRect(&r, -1, -1);
  6330.         
  6331.         // Draw the frame.
  6332.         ::MoveTo(r.left + 1, r.top + 1);
  6333.         ::RGBForeColor(&gAGARamp[rB]);
  6334.         ::Line(0, 0);
  6335.         ::Move(1, -1);
  6336.         ::RGBForeColor(&gAGARamp[r12]);
  6337.         ::Line(0, 0);
  6338.         ::Move(1, 0);
  6339.         ::RGBForeColor(&gAGARamp[rB]);
  6340.         ::Line(r.right - r.left - 6, 0);
  6341.         ::RGBForeColor(&gAGARamp[r12]);
  6342.         ::Line(0, 0);
  6343.         ::Move(1, 1);
  6344.         ::RGBForeColor(&gAGARamp[rB]);
  6345.         ::Line(0, 0);
  6346.         ::Move(1, 1);
  6347.         ::RGBForeColor(&gAGARamp[r12]);
  6348.         ::Line(0, 0);
  6349.         ::Move(0, 1);
  6350.         ::RGBForeColor(&gAGARamp[rB]);
  6351.         ::Line(0, r.bottom - r.top - 6);
  6352.         ::RGBForeColor(&gAGARamp[r12]);
  6353.         ::Line(0, 0);
  6354.         ::Move(-1, 1);
  6355.         ::RGBForeColor(&gAGARamp[rB]);
  6356.         ::Line(0, 0);
  6357.         ::Move(-1, 1);
  6358.         ::RGBForeColor(&gAGARamp[r12]);
  6359.         ::Line(0, 0);
  6360.         ::Move(-1, 0);
  6361.         ::RGBForeColor(&gAGARamp[rB]);
  6362.         ::Line(- (r.right - r.left - 6), 0);
  6363.         ::RGBForeColor(&gAGARamp[r12]);
  6364.         ::Line(0, 0);
  6365.         ::Move(-1, -1);
  6366.         ::RGBForeColor(&gAGARamp[rB]);
  6367.         ::Line(0, 0);
  6368.         ::Move(-1, -1);
  6369.         ::RGBForeColor(&gAGARamp[r12]);
  6370.         ::Line(0, 0);
  6371.         ::Move(0, -1);
  6372.         ::RGBForeColor(&gAGARamp[rB]);
  6373.         ::Line(0, -(r.bottom - r.top - 6));
  6374.         ::RGBForeColor(&gAGARamp[r12]);
  6375.         ::Line(0, 0);
  6376.         
  6377.         if (r.right - r.left > kPopupArrowSectionWidth)
  6378.             {
  6379.             // Add flat section inner pixels.
  6380.             ::RGBForeColor(&gAGARamp[rW]);
  6381.             ::MoveTo(r.left + 1, r.bottom - 3);
  6382.             ::LineTo(r.left + 1, r.top + 2);
  6383.             ::Move(1, -1);
  6384.             ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 1);
  6385.             ::RGBForeColor(&gAGARamp[r1]);
  6386.             ::Line(0, 0);
  6387.             ::RGBForeColor(&gAGARamp[r5]);
  6388.             ::MoveTo(r.left + 2, r.bottom - 2);
  6389.             ::LineTo(r.right - kPopupArrowSectionWidth, r.bottom - 2);
  6390.             ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 2);
  6391.             
  6392.             // Add arrow section left corners
  6393.             ::RGBForeColor(&gAGARamp[r4]);
  6394.             ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.bottom - 2);
  6395.             ::Line(0, 0);
  6396.             ::RGBForeColor(&gAGARamp[r2]);
  6397.             ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.top + 1);
  6398.             ::Line(0, 0);
  6399.             }
  6400.  
  6401.         // Add arrow section shading.
  6402.         ::RGBForeColor(&gAGARamp[r8]);
  6403.         ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 2);
  6404.         ::LineTo(r.right - 3, r.bottom - 2);
  6405.         ::Line(0, -1);
  6406.         ::Line(1, 0);
  6407.         ::LineTo(r.right - 2, r.top + 3);
  6408.         ::Move(-1, -2);
  6409.         ::RGBForeColor(&gAGARamp[r4]);
  6410.         ::Line(1, 1);
  6411.         ::RGBForeColor(&gAGARamp[r5]);
  6412.         ::Line(-1, 1);
  6413.         ::LineTo(r.right - 3, r.bottom - 4);
  6414.         ::Move(-1, 1);
  6415.         ::LineTo(r.right - kPopupArrowSectionWidth + 3, r.bottom - 3);
  6416.         ::RGBForeColor(&gAGARamp[rW]);
  6417.         ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 4);
  6418.         ::LineTo(r.right - kPopupArrowSectionWidth + 2, r.top + 2);
  6419.         ::LineTo(r.right - 4, r.top + 2);
  6420.         }
  6421.     else    // 1-bit
  6422.         {
  6423.         ::RGBForeColor(&gAGARamp[rW]);
  6424.         ::PaintRoundRect(&r, 7, 7);
  6425.         ::RGBForeColor(&gAGARamp[rB]);
  6426.         ::FrameRoundRect(&r, 7, 7);
  6427.         }
  6428.     
  6429.     // Add arrow.
  6430.     ::RGBForeColor(&gAGARamp[rB]);
  6431.     ::MoveTo(r.right - kPopupArrowSectionWidth + 6, r.top + ((r.bottom - r.top) / 2) - 2);
  6432.     ::Line(8, 0);
  6433.     ::Move(-1, 1);
  6434.     ::Line(-6, 0);
  6435.     ::Move(1, 1);
  6436.     ::Line(4, 0);
  6437.     ::Move(-1, 1);
  6438.     ::Line(-2, 0);
  6439.     ::Line(1, 1);
  6440.  
  6441.     if (r.right - r.left > kPopupArrowSectionWidth)
  6442.         {
  6443.         // Draw the current item text.
  6444.         r.left += 7;
  6445.         r.right -= kPopupArrowSectionWidth;
  6446.         AGAStringOut(currentItemText, &r, truncEnd, teFlushDefault, kNormalOutput, deep, mTextStyle);
  6447.         }
  6448.  
  6449.     // If the popup has a title, draw it next to the button.    
  6450.     if (mTitle[0] != 0)
  6451.         {
  6452.         this->GetTitleBounds(&r);
  6453.         AGAStringOut(mTitle, &r, truncEnd, mTitleJustification, kNormalOutput, deep, mTitleStyle);
  6454.         }
  6455.     }
  6456.  
  6457. void AGAPopupMenu::DrawButtonPressed(Boolean deep)
  6458.     {
  6459.     AGADrawingEnvironment    env;
  6460.  
  6461.     // Draw the popup button in enabled/pressed state.
  6462.  
  6463.     Rect    r;
  6464.     Str255    currentItemText;
  6465.     
  6466.     this->GetCurrentItemText(currentItemText);
  6467.     this->GetButtonBounds(&r);
  6468.     
  6469.     ::PenSize(1, 1);
  6470.  
  6471.     if (deep)
  6472.         {
  6473.         // Fill the interior.
  6474.         ::InsetRect(&r, 1, 1);
  6475.         ::RGBForeColor(&gAGARamp[r9]);
  6476.         ::PaintRect(&r);
  6477.         ::InsetRect(&r, -1, -1);
  6478.         
  6479.         // Draw the frame.
  6480.         ::MoveTo(r.left + 1, r.top + 1);
  6481.         ::RGBForeColor(&gAGARamp[rB]);
  6482.         ::Line(0, 0);
  6483.         ::Move(1, -1);
  6484.         ::RGBForeColor(&gAGARamp[r12]);
  6485.         ::Line(0, 0);
  6486.         ::Move(1, 0);
  6487.         ::RGBForeColor(&gAGARamp[rB]);
  6488.         ::Line(r.right - r.left - 6, 0);
  6489.         ::RGBForeColor(&gAGARamp[r12]);
  6490.         ::Line(0, 0);
  6491.         ::Move(1, 1);
  6492.         ::RGBForeColor(&gAGARamp[rB]);
  6493.         ::Line(0, 0);
  6494.         ::Move(1, 1);
  6495.         ::RGBForeColor(&gAGARamp[r12]);
  6496.         ::Line(0, 0);
  6497.         ::Move(0, 1);
  6498.         ::RGBForeColor(&gAGARamp[rB]);
  6499.         ::Line(0, r.bottom - r.top - 6);
  6500.         ::RGBForeColor(&gAGARamp[r12]);
  6501.         ::Line(0, 0);
  6502.         ::Move(-1, 1);
  6503.         ::RGBForeColor(&gAGARamp[rB]);
  6504.         ::Line(0, 0);
  6505.         ::Move(-1, 1);
  6506.         ::RGBForeColor(&gAGARamp[r12]);
  6507.         ::Line(0, 0);
  6508.         ::Move(-1, 0);
  6509.         ::RGBForeColor(&gAGARamp[rB]);
  6510.         ::Line(- (r.right - r.left - 6), 0);
  6511.         ::RGBForeColor(&gAGARamp[r12]);
  6512.         ::Line(0, 0);
  6513.         ::Move(-1, -1);
  6514.         ::RGBForeColor(&gAGARamp[rB]);
  6515.         ::Line(0, 0);
  6516.         ::Move(-1, -1);
  6517.         ::RGBForeColor(&gAGARamp[r12]);
  6518.         ::Line(0, 0);
  6519.         ::Move(0, -1);
  6520.         ::RGBForeColor(&gAGARamp[rB]);
  6521.         ::Line(0, -(r.bottom - r.top - 6));
  6522.         ::RGBForeColor(&gAGARamp[r12]);
  6523.         ::Line(0, 0);
  6524.         
  6525.         if (r.right - r.left > kPopupArrowSectionWidth)
  6526.             {
  6527.             // Add flat section inner pixels.
  6528.             ::RGBForeColor(&gAGARamp[r10]);
  6529.             ::MoveTo(r.left + 1, r.bottom - 3);
  6530.             ::LineTo(r.left + 1, r.top + 2);
  6531.             ::Line(1, 0);
  6532.             ::Line(0, -1);
  6533.             ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 1);
  6534.             ::RGBForeColor(&gAGARamp[r8]);
  6535.             ::MoveTo(r.left + 2, r.bottom - 2);
  6536.             ::LineTo(r.right - kPopupArrowSectionWidth, r.bottom - 2);
  6537.             ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 2);
  6538.             
  6539.             // Add arrow section left corners
  6540.             ::RGBForeColor(&gAGARamp[r11]);
  6541.             ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.bottom - 2);
  6542.             ::Line(0, 0);
  6543.             ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.top + 1);
  6544.             ::Line(0, 0);
  6545.             }
  6546.  
  6547.         // Add arrow section shading.
  6548.         ::RGBForeColor(&gAGARamp[r7]);
  6549.         ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 2);
  6550.         ::LineTo(r.right - 3, r.bottom - 2);
  6551.         ::Line(0, -1);
  6552.         ::Line(1, 0);
  6553.         ::LineTo(r.right - 2, r.top + 2);
  6554.         ::Move(-1, 1);
  6555.         ::RGBForeColor(&gAGARamp[r8]);
  6556.         ::LineTo(r.right - 3, r.bottom - 4);
  6557.         ::Move(-1, 1);
  6558.         ::LineTo(r.right - kPopupArrowSectionWidth + 3, r.bottom - 3);
  6559.         ::RGBForeColor(&gAGARamp[r10]);
  6560.         ::MoveTo(r.right - kPopupArrowSectionWidth + 2, r.bottom - 4);
  6561.         ::LineTo(r.right - kPopupArrowSectionWidth + 2, r.top + 2);
  6562.         ::LineTo(r.right - 4, r.top + 2);
  6563.         ::RGBForeColor(&gAGARamp[r11]);
  6564.         ::MoveTo(r.right - kPopupArrowSectionWidth + 1, r.bottom - 3);
  6565.         ::LineTo(r.right - kPopupArrowSectionWidth + 1, r.top + 2);
  6566.         ::Move(1, -1);
  6567.         ::LineTo(r.right - 3, r.top + 1);
  6568.         }
  6569.     else    // 1-bit
  6570.         {
  6571.         ::RGBForeColor(&gAGARamp[rB]);
  6572.         ::PaintRoundRect(&r, 7, 7);
  6573.         }
  6574.  
  6575.     // Add arrow.
  6576.     
  6577.     ::RGBForeColor(&gAGARamp[rW]);
  6578.     ::MoveTo(r.right - kPopupArrowSectionWidth + 6, r.top + ((r.bottom - r.top) / 2) - 2);
  6579.     ::Line(8, 0);
  6580.     ::Move(-1, 1);
  6581.     ::Line(-6, 0);
  6582.     ::Move(1, 1);
  6583.     ::Line(4, 0);
  6584.     ::Move(-1, 1);
  6585.     ::Line(-2, 0);
  6586.     ::Line(1, 1);
  6587.  
  6588.     if (r.right - r.left > kPopupArrowSectionWidth)
  6589.         {
  6590.         // Draw the current item text.
  6591.         r.left += 7;
  6592.         r.right -= kPopupArrowSectionWidth;
  6593.         AGAStringOut(currentItemText, &r, truncEnd, teFlushDefault, kInverseOutput, deep, mTextStyle);
  6594.         }
  6595.  
  6596.     // (No need to draw the title, since it does not change
  6597.     //  upon pressing the button.)
  6598.     }
  6599.  
  6600. void AGAPopupMenu::DrawButtonDisabled(Boolean deep)
  6601.     {
  6602.     AGADrawingEnvironment    env;
  6603.  
  6604.     // Draw the popup button in disabled/unpressed state.
  6605.  
  6606.     Rect    r;
  6607.     Str255    currentItemText;
  6608.     
  6609.     this->GetCurrentItemText(currentItemText);
  6610.     this->GetButtonBounds(&r);
  6611.     
  6612.     ::PenSize(1, 1);
  6613.  
  6614.     if (deep)
  6615.         {
  6616.         // Fill the interior.
  6617.         ::InsetRect(&r, 1, 1);
  6618.         ::RGBForeColor(&gAGARamp[r2]);
  6619.         ::PaintRect(&r);
  6620.         ::InsetRect(&r, -1, -1);
  6621.         
  6622.         // Draw the frame.
  6623.         ::MoveTo(r.left + 1, r.top + 1);
  6624.         ::RGBForeColor(&gAGARamp[r7]);
  6625.         ::Line(0, 0);
  6626.         ::Move(1, -1);
  6627.         ::Line(0, 0);
  6628.         ::Move(1, 0);
  6629.         ::Line(r.right - r.left - 6, 0);
  6630.         ::Line(0, 0);
  6631.         ::Move(1, 1);
  6632.         ::Line(0, 0);
  6633.         ::Move(1, 1);
  6634.         ::Line(0, 0);
  6635.         ::Move(0, 1);
  6636.         ::Line(0, r.bottom - r.top - 6);
  6637.         ::Line(0, 0);
  6638.         ::Move(-1, 1);
  6639.         ::Line(0, 0);
  6640.         ::Move(-1, 1);
  6641.         ::Line(0, 0);
  6642.         ::Move(-1, 0);
  6643.         ::Line(- (r.right - r.left - 6), 0);
  6644.         ::Line(0, 0);
  6645.         ::Move(-1, -1);
  6646.         ::Line(0, 0);
  6647.         ::Move(-1, -1);
  6648.         ::Line(0, 0);
  6649.         ::Move(0, -1);
  6650.         ::Line(0, -(r.bottom - r.top - 6));
  6651.         ::Line(0, 0);
  6652.  
  6653.         if (r.right - r.left > kPopupArrowSectionWidth)
  6654.             {
  6655.             ::RGBForeColor(&gAGARamp[r5]);
  6656.             ::MoveTo(r.right - kPopupArrowSectionWidth, r.bottom - 2);
  6657.             ::LineTo(r.right - kPopupArrowSectionWidth, r.top + 2);
  6658.             }
  6659.         }
  6660.     else    // 1-bit
  6661.         {
  6662.         ::RGBForeColor(&gAGARamp[rW]);
  6663.         ::PaintRoundRect(&r, 7, 7);
  6664.         ::RGBForeColor(&gAGARamp[rB]);
  6665.         ::FrameRoundRect(&r, 7, 7);
  6666.         }
  6667.  
  6668.     // Add arrow.
  6669.     ::RGBForeColor(&gAGARamp[r7]);
  6670.     ::MoveTo(r.right - kPopupArrowSectionWidth + 6, r.top + ((r.bottom - r.top) / 2) - 2);
  6671.     ::Line(8, 0);
  6672.     ::Move(-1, 1);
  6673.     ::Line(-6, 0);
  6674.     ::Move(1, 1);
  6675.     ::Line(4, 0);
  6676.     ::Move(-1, 1);
  6677.     ::Line(-2, 0);
  6678.     ::Line(1, 1);
  6679.  
  6680.     if (r.right - r.left > kPopupArrowSectionWidth)
  6681.         {
  6682.         // Draw the current item text.
  6683.         r.left += 7;
  6684.         r.right -= kPopupArrowSectionWidth;
  6685.         AGAStringOut(currentItemText, &r, truncEnd, teFlushDefault, kDisabledOutput, deep, mTextStyle);
  6686.         }
  6687.     
  6688.     // If the popup has a title, draw it next to the button.    
  6689.     if (mTitle[0] != 0)
  6690.         {
  6691.         this->GetTitleBounds(&r);
  6692.         AGAStringOut(mTitle, &r, truncEnd, mTitleJustification, kDisabledOutput, deep, mTitleStyle);
  6693.         }
  6694.     
  6695.     if (! deep)
  6696.         {
  6697.         ::RGBForeColor(&gAGARamp[rB]);
  6698.         ::PenPat(&qd.gray);
  6699.         ::PenMode(patBic);
  6700.         ::PaintRect(&mBounds);
  6701.  
  6702.         ::PenNormal();
  6703.         }
  6704.     }
  6705.  
  6706. void AGAPopupMenu::GetButtonBounds(Rect* buttonBounds)
  6707.     {
  6708.     // Return the bounds of the popup button. We may need
  6709.     // to check the actual menu's width, depending on the
  6710.     // width adjustment specifier.
  6711.  
  6712.     *buttonBounds = mBounds;
  6713.     buttonBounds->left += mTitleOffset;
  6714.     
  6715.     if ((mMenuRef != NULL) && (mWidthAdjust != kFixedWidth))
  6716.         {
  6717.         AGACustomPopupMenuSizer    sizer(mTextStyle.mFontNum, mTextStyle.mFontSize);
  6718.  
  6719.         ::CalcMenuSize(mMenuRef);
  6720.         buttonBounds->right = MinSInt16(mBounds.right, buttonBounds->left + 3 + (**mMenuRef).menuWidth + mWidthAdjust);
  6721.         }
  6722.     }
  6723.  
  6724. void AGAPopupMenu::GetTitleBounds(Rect* titleBounds)
  6725.     {
  6726.     // Return the bounds of the title area.
  6727.  
  6728.     *titleBounds = mBounds;
  6729.     
  6730.     titleBounds->right = titleBounds->left + mTitleOffset - 3;
  6731.     }
  6732.  
  6733. //
  6734. // AGACustomPopupMenuSizer ---------------------------------------------------------------
  6735. //
  6736. // Stack-based object to hack in a custom popup menu font/size
  6737. // around a call to PopUpMenuSelect or CalcMenuSize.
  6738. //
  6739.  
  6740. AGACustomPopupMenuSizer::AGACustomPopupMenuSizer(SInt16 fontNum, SInt16 fontSize)
  6741.     {
  6742.     mCustomFontNum = fontNum;
  6743.     mCustomFontSize = fontSize;
  6744.     mIsCustom = (fontNum != 0) || ((fontSize != 0) && (fontSize != 12));
  6745.  
  6746.     this->SaveEnvironment();
  6747.     this->InstallCustomEnvironment();
  6748.     }
  6749.  
  6750. AGACustomPopupMenuSizer::~AGACustomPopupMenuSizer()
  6751.     {
  6752.     this->RestoreEnvironment();
  6753.     }
  6754.  
  6755. void AGACustomPopupMenuSizer::SaveEnvironment()
  6756.     {
  6757.     if (mIsCustom)
  6758.         {
  6759.         mSavedFontNum = ::LMGetSysFontFam();
  6760.         mSavedFontSize = ::LMGetSysFontSize();
  6761.         }
  6762.     }
  6763.  
  6764. void AGACustomPopupMenuSizer::RestoreEnvironment()
  6765.     {
  6766.     if (mIsCustom)
  6767.         {
  6768.         ::LMSetSysFontFam(mSavedFontNum);
  6769.         ::LMSetSysFontSize(mSavedFontSize);
  6770.         ::LMSetLastSPExtra(-1);
  6771.         }
  6772.     }
  6773.  
  6774. void AGACustomPopupMenuSizer::InstallCustomEnvironment()
  6775.     {
  6776.     if (mIsCustom)
  6777.         {
  6778.         ::LMSetSysFontFam(mCustomFontNum);
  6779.         ::LMSetSysFontSize(mCustomFontSize);
  6780.         ::LMSetLastSPExtra(-1);
  6781.         }
  6782.     }
  6783.  
  6784. //
  6785. // AGALittleArrows ---------------------------------------------------------------
  6786. //
  6787. // This class implements a little arrows control.
  6788. //
  6789.  
  6790. AGALittleArrows::AGALittleArrows(Rect* bounds)
  6791. : AGAObject(bounds)
  6792.     {
  6793.     mNotificationRoutine = NULL;
  6794.     mUserData = 0;
  6795.     }
  6796.  
  6797. AGALittleArrows::~AGALittleArrows()
  6798.     {
  6799.     }
  6800.  
  6801. void AGALittleArrows::InstallNotificationRoutine(AGALittleArrowsNotifyPtr notificationRoutine, void* userData)
  6802.     {
  6803.     // Install the supplied function pointer and user data to
  6804.     // be called during notification.
  6805.  
  6806.     mNotificationRoutine = notificationRoutine;
  6807.     mUserData = userData;
  6808.     }
  6809.  
  6810. void AGALittleArrows::DrawObject()
  6811.     {
  6812.     // Draw the arrows in normal unpressed state.
  6813.  
  6814.     this->DrawButton(kNoArrowPressed);
  6815.     }
  6816.  
  6817. Boolean AGALittleArrows::TrackMouse(Point mouseLocation)
  6818.     {
  6819.     if (! mEnabled)
  6820.         return false;
  6821.  
  6822.     // Track the mouse in the appropriate arrow. Little arrows
  6823.     // always return true because the tracking is always successful.
  6824.  
  6825.     return this->TrackPart(mouseLocation, this->TrackTestPart(mouseLocation));
  6826.     }
  6827.  
  6828. void AGALittleArrows::DrawButton(SInt32 pressedPart)
  6829.     {
  6830.     AGADrawingEnvironment    env;
  6831.  
  6832.     // Draw the arrows in the specified press state. The
  6833.     // state may indicate that either or no arrow is pressed.
  6834.  
  6835.     enum { Frame, Fill, TL, BR, Arrow, kNumArrowColors };
  6836.  
  6837.     UInt8    colorIndexes[kNumArrowColors];
  6838.     
  6839.     GDIterator    iter;
  6840.     Boolean        deep;
  6841.  
  6842.     while (iter.More(deep))
  6843.         {
  6844.         Rect    r = mBounds;
  6845.         
  6846.         r.right = r.left + kLittleArrowWidth;
  6847.         r.bottom = r.top + kLittleArrowHeight;
  6848.         
  6849.         for (UInt32 i = 0; i < 2; i++)
  6850.             {
  6851.             if (deep)
  6852.                 {
  6853.                 if (mEnabled)
  6854.                     {
  6855.                     if (((pressedPart == kUpArrowPressed) && (i == 0)) ||
  6856.                         ((pressedPart == kDownArrowPressed) && (i == 1)))
  6857.                         {
  6858.                         colorIndexes[Frame] = rB;
  6859.                         colorIndexes[Fill] = r8;
  6860.                         colorIndexes[TL] = r10;
  6861.                         colorIndexes[BR] = r6;
  6862.                         colorIndexes[Arrow] = rW;
  6863.                         }
  6864.                     else if (((pressedPart != kUpArrowPressed) && (i == 0)) ||
  6865.                         ((pressedPart != kDownArrowPressed) && (i == 1)))
  6866.                         {
  6867.                         colorIndexes[Frame] = rB;
  6868.                         colorIndexes[Fill] = r2;
  6869.                         colorIndexes[TL] = rW;
  6870.                         colorIndexes[BR] = r5;
  6871.                         colorIndexes[Arrow] = rB;
  6872.                         }
  6873.                     }
  6874.                 else    // disabled
  6875.                     {
  6876.                     colorIndexes[Frame] = r7;
  6877.                     colorIndexes[Fill] = r2;
  6878.                     colorIndexes[TL] = r2;
  6879.                     colorIndexes[BR] = r2;
  6880.                     colorIndexes[Arrow] = r7;
  6881.                     }
  6882.                 
  6883.                 // These (1-i) and i uses here are to round off the top corners
  6884.                 // of the top frame (i=0) and round off the bottom corners of
  6885.                 // the bottom frame (i=1).
  6886.                 ::RGBForeColor(&gAGARamp[colorIndexes[Frame]]);
  6887.                 ::MoveTo(r.left + (1-i), r.top);
  6888.                 ::LineTo(r.right - 1 - (1-i), r.top);
  6889.                 ::Move(1-i, 1-i);
  6890.                 ::LineTo(r.right -1, r.bottom - 1 - i);
  6891.                 ::Move(-i, i);
  6892.                 ::LineTo(r.left + i, r.bottom - 1);
  6893.                 ::Move(-i, -i);
  6894.                 ::LineTo(r.left, r.top + (1-i));
  6895.                 
  6896.                 ::InsetRect(&r, 1, 1);
  6897.                 ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  6898.                 ::PaintRect(&r);
  6899.                 ::InsetRect(&r, -1, -1);
  6900.                 
  6901.                 ::RGBForeColor(&gAGARamp[colorIndexes[TL]]);
  6902.                 ::MoveTo(r.left + 1, r.bottom - 3);
  6903.                 ::LineTo(r.left + 1, r.top + 1);
  6904.                 ::LineTo(r.right - 3, r.top + 1);
  6905.                 
  6906.                 ::RGBForeColor(&gAGARamp[colorIndexes[BR]]);
  6907.                 ::MoveTo(r.left + 2, r.bottom - 2);
  6908.                 ::LineTo(r.right - 2, r.bottom - 2);
  6909.                 ::LineTo(r.right - 2, r.top + 2);
  6910.                 
  6911.                 ::RGBForeColor(&gAGARamp[colorIndexes[Arrow]]);
  6912.                 }
  6913.             else    // 1-bit
  6914.                 {
  6915.                 if (((pressedPart == kUpArrowPressed) && (i == 0)) ||
  6916.                     ((pressedPart == kDownArrowPressed) && (i == 1)))
  6917.                     {
  6918.                     ::RGBForeColor(&gAGARamp[rB]);
  6919.                     ::InsetRect(&r, 1, 1);
  6920.                     ::PaintRect(&r);
  6921.                     ::InsetRect(&r, -1, -1);
  6922.                     ::RGBForeColor(&gAGARamp[rW]);
  6923.                     }
  6924.                 else
  6925.                     {
  6926.                     ::RGBForeColor(&gAGARamp[rW]);
  6927.                     ::PaintRect(&r);
  6928.                     ::RGBForeColor(&gAGARamp[rB]);
  6929.  
  6930.                     ::MoveTo(r.left + (1-i), r.top);
  6931.                     ::LineTo(r.right - 1 - (1-i), r.top);
  6932.                     ::Move(1-i, 1-i);
  6933.                     ::LineTo(r.right -1, r.bottom - 1 - i);
  6934.                     ::Move(-i, i);
  6935.                     ::LineTo(r.left + i, r.bottom - 1);
  6936.                     ::Move(-i, -i);
  6937.                     ::LineTo(r.left, r.top + (1-i));
  6938.                     }
  6939.                 }
  6940.  
  6941.             ::MoveTo(r.left + 3, r.top + 7 - (i*3));
  6942.             ::Line(6, 0);
  6943.             ::Move(-1, -1 + (2*i));
  6944.             ::Line(-4, 0);
  6945.             ::Move(1, -1 + (2*i));
  6946.             ::Line(2, 0);
  6947.             ::Move(-1, -1 + (2*i));
  6948.             ::Line(0, 0);
  6949.             
  6950.             ::OffsetRect(&r, 0, kLittleArrowHeight - 1);
  6951.             }
  6952.  
  6953.         if ((! mEnabled) && ! deep)
  6954.             {
  6955.             ::RGBForeColor(&gAGARamp[rB]);
  6956.             ::PenPat(&qd.gray);
  6957.             ::PenMode(patBic);
  6958.             ::PaintRect(&mBounds);
  6959.  
  6960.             ::PenNormal();
  6961.             }
  6962.         }
  6963.     }
  6964.  
  6965. Boolean AGALittleArrows::TrackPart(Point /*mouseLocation*/, SInt32 partHit)
  6966.     {
  6967.     // Track the mouse in the specified arrow. Little arrows always
  6968.     // return true because the tracking is always successful.
  6969.  
  6970.     Boolean    wasIn = false;
  6971.     Boolean    isIn = true;
  6972.     Boolean    isButtonDown = true;    // ensure at least one time through
  6973.     Point    newMouseLocation;
  6974.     UInt32    accelerationDelay = 18;    // will divide by 2 each time
  6975.     
  6976.     while (isButtonDown)
  6977.         {
  6978.         if (isIn)
  6979.             this->NotifyDelta(partHit);
  6980.  
  6981.         ::GetMouse(&newMouseLocation);    // gives local coordinates
  6982.         
  6983.         isIn = (this->TrackTestPart(newMouseLocation) == partHit);
  6984.         
  6985.         if (isIn != wasIn)
  6986.             this->DrawButton(isIn ? partHit : kNoArrowPressed);
  6987.         
  6988.         wasIn = isIn;
  6989.         
  6990.         if (isButtonDown && (accelerationDelay != 0))
  6991.             {
  6992.             DelayFutureWhileStillDown(accelerationDelay);
  6993.             accelerationDelay = accelerationDelay >> 1;    // divide by 2
  6994.             }
  6995.  
  6996.         isButtonDown = ::StillDown();
  6997.         }
  6998.     
  6999.     if (isIn)    // if finished IN, restore normal appearance
  7000.         this->DrawButton(kNoArrowPressed);
  7001.     
  7002.     return true;
  7003.     }
  7004.  
  7005. SInt32 AGALittleArrows::TrackTestPart(Point mouseLocation)
  7006.     {
  7007.     // Return the part value where the mouse would hit.
  7008.  
  7009.     if ((mouseLocation.h >= mBounds.left + kLittleArrowWidth) ||
  7010.         (mouseLocation.h < mBounds.left) ||
  7011.         (mouseLocation.v >= mBounds.top + kLittleArrowTotalHeight) ||
  7012.         (mouseLocation.v < mBounds.top))
  7013.         return kNoArrowPressed;
  7014.     else if (mouseLocation.v < mBounds.top + kLittleArrowHeight)
  7015.         return kUpArrowPressed;
  7016.     else
  7017.         return kDownArrowPressed;
  7018.     }
  7019.  
  7020. void AGALittleArrows::NotifyDelta(SInt32 partHit)
  7021.     {
  7022.     // Call the installed notification routine, if any, with
  7023.     // the installed user data and our part hit, which is the
  7024.     // value delta (-1 or 1).
  7025.  
  7026.     if (mNotificationRoutine != NULL)
  7027.         (*(mNotificationRoutine))(this, partHit, mUserData);
  7028.     }
  7029.  
  7030. //
  7031. // AGADisclosureTriangle ---------------------------------------------------------------
  7032. //
  7033. // This class implements a disclosure triangle.
  7034. //
  7035.  
  7036. AGADisclosureTriangle::AGADisclosureTriangle(Rect* bounds, Boolean automaticState)
  7037. : AGAObject(bounds)
  7038.     {
  7039.     // Construct as specified.
  7040.  
  7041.     mAutomaticState = automaticState;
  7042.     mIsDisclosed = kClosedState;
  7043.     }
  7044.  
  7045. AGADisclosureTriangle::~AGADisclosureTriangle()
  7046.     {
  7047.     }
  7048.  
  7049. void AGADisclosureTriangle::DrawObject()
  7050.     {
  7051.     // Draw the triangle in the current state.
  7052.  
  7053.     this->DrawTriangle(mIsDisclosed ? kDTDisclosed : kDTClosed);
  7054.     }
  7055.  
  7056. Boolean AGADisclosureTriangle::TrackMouse(Point mouseLocation)
  7057.     {
  7058.     // Let superclass handle tracking, and change our state
  7059.     // if we have automatic state change turned on.
  7060.  
  7061.     Boolean    wasItHit = AGAObject::TrackMouse(mouseLocation);
  7062.  
  7063.     if (wasItHit && mAutomaticState)
  7064.         this->SetStateAnimate(! mIsDisclosed);
  7065.  
  7066.     return wasItHit;
  7067.     }
  7068.  
  7069. Boolean AGADisclosureTriangle::GetState()
  7070.     {
  7071.     // Return the current state.
  7072.  
  7073.     return mIsDisclosed;
  7074.     }
  7075.  
  7076. void AGADisclosureTriangle::SetState(Boolean isDisclosed, Boolean redraw)
  7077.     {
  7078.     // Set the state and optionally redraw.
  7079.  
  7080.     if (isDisclosed != mIsDisclosed)
  7081.         {
  7082.         mIsDisclosed = isDisclosed;
  7083.         
  7084.         if (redraw)
  7085.             this->DrawTriangle(mIsDisclosed ? kDTDisclosed : kDTClosed);
  7086.         }
  7087.     }
  7088.  
  7089. void AGADisclosureTriangle::SetStateAnimate(Boolean isDisclosed)
  7090.     {
  7091.     // Set the state, but animate the triangle as it changes
  7092.     // to the new state.
  7093.  
  7094.     const SInt32 kAnimationDelay = 4;
  7095.  
  7096.     if (isDisclosed)
  7097.         {
  7098.         this->DrawTriangle(kDTPressedClosed);
  7099.         DelayFuture(kAnimationDelay);
  7100.  
  7101.         this->EraseBackground();
  7102.         this->DrawTriangle(kDTIntermediate);
  7103.         DelayFuture(kAnimationDelay);
  7104.  
  7105.         this->EraseBackground();
  7106.         this->DrawTriangle(kDTPressedDisclosed);
  7107.         DelayFuture(kAnimationDelay);
  7108.  
  7109.         this->EraseBackground();
  7110.         }
  7111.     else
  7112.         {
  7113.         this->DrawTriangle(kDTPressedDisclosed);
  7114.         DelayFuture(kAnimationDelay);
  7115.  
  7116.         this->EraseBackground();
  7117.         this->DrawTriangle(kDTIntermediate);
  7118.         DelayFuture(kAnimationDelay);
  7119.  
  7120.         this->EraseBackground();
  7121.         this->DrawTriangle(kDTPressedClosed);
  7122.         DelayFuture(kAnimationDelay);
  7123.  
  7124.         this->EraseBackground();
  7125.         }
  7126.     
  7127.     this->SetState(isDisclosed, kRedraw);
  7128.     }
  7129.  
  7130. void AGADisclosureTriangle::SetTrackingState(Boolean isIn)
  7131.     {
  7132.     // Draw the triangle pressed or unpressed as specified.
  7133.  
  7134.     DTAnimationState    state;
  7135.     
  7136.     if (isIn)
  7137.         state = mIsDisclosed ? kDTPressedDisclosed : kDTPressedClosed;
  7138.     else
  7139.         state = mIsDisclosed ? kDTDisclosed : kDTClosed;
  7140.  
  7141.     this->DrawTriangle(state);
  7142.     }
  7143.  
  7144. void AGADisclosureTriangle::DrawTriangle(DTAnimationState state)
  7145.     {
  7146.     AGADrawingEnvironment    env;
  7147.  
  7148.     // Draw the triangle at the specified animation frame.
  7149.  
  7150.     Point        fulcrum;
  7151.     Point        corners[3];
  7152.     
  7153.     ::SetPt(&fulcrum, mBounds.left + 5, mBounds.top + 5);
  7154.  
  7155.     switch (state)
  7156.         {
  7157.         case kDTClosed:
  7158.         case kDTPressedClosed:
  7159.             ::SetPt(&corners[0], fulcrum.h - 2, fulcrum.v - 5);
  7160.             ::SetPt(&corners[1], fulcrum.h + 3, fulcrum.v);
  7161.             ::SetPt(&corners[2], fulcrum.h - 2, fulcrum.v + 5);
  7162.             break;
  7163.         case kDTIntermediate:
  7164.             ::SetPt(&corners[0], fulcrum.h + 3, fulcrum.v - 5);
  7165.             ::SetPt(&corners[1], fulcrum.h + 3, fulcrum.v + 3);
  7166.             ::SetPt(&corners[2], fulcrum.h - 5, fulcrum.v + 3);
  7167.             break;
  7168.         case kDTPressedDisclosed:
  7169.         case kDTDisclosed:
  7170.             ::SetPt(&corners[0], fulcrum.h + 5, fulcrum.v - 2);
  7171.             ::SetPt(&corners[1], fulcrum.h, fulcrum.v + 3);
  7172.             ::SetPt(&corners[2], fulcrum.h - 5, fulcrum.v - 2);
  7173.             break;
  7174.         }
  7175.     
  7176.     // Little trick: tweak state so that disabled state (gray
  7177.     // fill) is handled by pressed case code below. We already set
  7178.     // the color so they only set pressed fill color if enabled.
  7179.     DTAnimationState    deepState = state;
  7180.     
  7181.     if (! mEnabled)
  7182.         {
  7183.         if (deepState == kDTClosed)
  7184.             deepState = kDTPressedClosed;
  7185.         else
  7186.             deepState = kDTPressedDisclosed;
  7187.         }
  7188.             
  7189.     GDIterator    iter;
  7190.     Boolean        deep;
  7191.  
  7192.     while (iter.More(deep))
  7193.         {
  7194.         if (deep)
  7195.             {
  7196.             if (mEnabled)
  7197.                 ::RGBForeColor(&gAGARamp[rB]);
  7198.             else
  7199.                 ::RGBForeColor(&gAGARamp[r5]);
  7200.  
  7201.             ::MoveTo(corners[0].h, corners[0].v);
  7202.             ::LineTo(corners[1].h, corners[1].v);
  7203.             ::LineTo(corners[2].h, corners[2].v);
  7204.             ::LineTo(corners[0].h, corners[0].v);
  7205.             
  7206.             switch (deepState)
  7207.                 {
  7208.                 case kDTClosed:
  7209.                     ::RGBForeColor(&gAGARamp[rP1]);
  7210.                     ::MoveTo(corners[0].h + 1, corners[0].v + 2);
  7211.                     ::Line(0, 6);
  7212.                     ::RGBForeColor(&gAGARamp[rP2]);
  7213.                     ::Line(1, -1);
  7214.                     ::Line(0, -4);
  7215.                     ::Line(1, 1);
  7216.                     ::Line(0, 1);
  7217.                     ::Move(1, 0);
  7218.                     ::RGBForeColor(&gAGARamp[rP3]);
  7219.                     ::Line(-2, 2);
  7220.  
  7221.                     ::RGBForeColor(&gAGARamp[r7]);
  7222.                     ::MoveTo(corners[2].h + 1, corners[2].v);
  7223.                     ::Line(4, -4);
  7224.                     ::RGBForeColor(&gAGARamp[r4]);
  7225.                     ::Move(1, 0);
  7226.                     ::Line(-5, 5);
  7227.                     break;
  7228.                 case kDTPressedClosed:
  7229.                     if (mEnabled)
  7230.                         ::RGBForeColor(&gAGARamp[rP4]);
  7231.  
  7232.                     ::MoveTo(corners[0].h + 1, corners[0].v + 2);
  7233.                     ::Line(0, 6);
  7234.                     ::Move(1, -1);
  7235.                     ::Line(0, -4);
  7236.                     ::Move(1, 1);
  7237.                     ::Line(0, 2);
  7238.                     ::Line(1, -1);
  7239.  
  7240.                     ::RGBForeColor(&gAGARamp[r2]);
  7241.                     ::MoveTo(corners[2].h + 1, corners[2].v);
  7242.                     ::Line(4, -4);
  7243.                     ::Move(1, 0);
  7244.                     ::Line(-5, 5);
  7245.                     break;
  7246.                 case kDTIntermediate:
  7247.                     ::RGBForeColor(&gAGARamp[rP4]);
  7248.                     ::MoveTo(corners[0].h - 1, corners[0].v + 2);
  7249.                     ::Line(-5, 5);
  7250.                     ::Move(1, 0);
  7251.                     ::Line(4, -4);
  7252.                     ::Move(0, 1);
  7253.                     ::Line(-3, 3);
  7254.                     ::Move(1, 0);
  7255.                     ::Line(2, -2);
  7256.                     ::Move(0, 1);
  7257.                     ::Line(-1, 1);
  7258.                     ::Line(1, 0);
  7259.                     break;
  7260.                 case kDTPressedDisclosed:
  7261.                     if (mEnabled)
  7262.                         ::RGBForeColor(&gAGARamp[rP4]);
  7263.  
  7264.                     ::MoveTo(corners[2].h + 2, corners[2].v + 1);
  7265.                     ::Line(6, 0);
  7266.                     ::Move(-1, 1);
  7267.                     ::Line(-4, 0);
  7268.                     ::Move(1, 1);
  7269.                     ::Line(2, 0);
  7270.                     ::Line(-1, 1);
  7271.  
  7272.                     ::RGBForeColor(&gAGARamp[r2]);
  7273.                     ::MoveTo(corners[0].h, corners[0].v + 1);
  7274.                     ::Line(-4, 4);
  7275.                     ::Move(0, 1);
  7276.                     ::Line(5, -5);
  7277.                     break;
  7278.                 case kDTDisclosed:
  7279.                     ::RGBForeColor(&gAGARamp[rP1]);
  7280.                     ::MoveTo(corners[2].h + 2, corners[2].v + 1);
  7281.                     ::Line(6, 0);
  7282.                     ::RGBForeColor(&gAGARamp[rP2]);
  7283.                     ::Line(-1, 1);
  7284.                     ::Line(-4, 0);
  7285.                     ::Line(1, 1);
  7286.                     ::Line(1, 0);
  7287.                     ::Move(0, 1);
  7288.                     ::RGBForeColor(&gAGARamp[rP3]);
  7289.                     ::Line(2, -2);
  7290.  
  7291.                     ::RGBForeColor(&gAGARamp[r7]);
  7292.                     ::MoveTo(corners[0].h, corners[0].v + 1);
  7293.                     ::Line(-4, 4);
  7294.                     ::RGBForeColor(&gAGARamp[r4]);
  7295.                     ::Move(0, 1);
  7296.                     ::Line(5, -5);
  7297.                     break;
  7298.                 }
  7299.             }
  7300.         else    // 1-bit
  7301.             {
  7302.             PolyHandle    theTriangle = ::OpenPoly();
  7303.  
  7304.             ::MoveTo(corners[0].h, corners[0].v);
  7305.             ::LineTo(corners[1].h, corners[1].v);
  7306.             ::LineTo(corners[2].h, corners[2].v);
  7307.             ::LineTo(corners[0].h, corners[0].v);
  7308.             
  7309.             ::ClosePoly();
  7310.             
  7311.             switch (state)
  7312.                 {
  7313.                 case kDTClosed:
  7314.                 case kDTDisclosed:
  7315.                     ::RGBForeColor(&gAGARamp[rW]);
  7316.                     ::PaintPoly(theTriangle);
  7317.                     ::RGBForeColor(&gAGARamp[rB]);
  7318.                     ::FramePoly(theTriangle);
  7319.  
  7320.                     if (! mEnabled)
  7321.                         {
  7322.                         ::PenPat(&qd.gray);
  7323.                         ::PenMode(patBic);
  7324.                         ::PaintRect(&mBounds);
  7325.  
  7326.                         ::PenNormal();
  7327.                         }
  7328.                     break;
  7329.                 case kDTPressedClosed:
  7330.                 case kDTIntermediate:
  7331.                 case kDTPressedDisclosed:
  7332.                     ::RGBForeColor(&gAGARamp[rB]);
  7333.                     ::PaintPoly(theTriangle);
  7334.                     break;
  7335.                 }
  7336.             
  7337.             ::KillPoly(theTriangle);
  7338.             ::PenNormal();
  7339.             }
  7340.         }
  7341.     }
  7342.  
  7343. void AGADisclosureTriangle::EraseBackground()
  7344.     {
  7345.     AGADrawingEnvironment    env;
  7346.  
  7347.     GDIterator    iter;
  7348.     Boolean        deep;
  7349.  
  7350.     while (iter.More(deep))
  7351.         {
  7352.         if (deep)
  7353.             this->ApplyBackgroundColor();
  7354.         else
  7355.             ::RGBForeColor(&gAGARamp[rW]);
  7356.  
  7357.         ::PaintRect(&mBounds);
  7358.         }
  7359.     }
  7360.  
  7361. //
  7362. // AGAProgressIndicator ---------------------------------------------------------------
  7363. //
  7364. // This class implements a progress indicator that can be either
  7365. // determinate or indeterminate, and also can have a moving start
  7366. // value.
  7367. //
  7368.  
  7369. // We use an offscreen image for the indeterminate progress pattern.
  7370. AGAOffscreenImage*    AGAProgressIndicator::mgOffscreenIndeterminateProgressImage[kNumProgressPatterns];
  7371.  
  7372. // These are the color ramp indexes that are used to build the offscreen image.
  7373. SInt8                AGAProgressIndicator::kIndeterminateProgressImage[kNumProgressPatterns]
  7374.                                                                 [kProgressImageHeight]
  7375.                                                                     [kProgressImageWidth] =
  7376.         {
  7377.         {    // k1BitPattern
  7378.             {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  7379.             {  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  7380.             {  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  7381.             {  rW,  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW,  rW,  rW,  rW,  rW },
  7382.             {  rW,  rW,  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW,  rW,  rW,  rW },
  7383.             {  rW,  rW,  rW,  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW,  rW,  rW },
  7384.             {  rW,  rW,  rW,  rW,  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW,  rW },
  7385.             {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rW },
  7386.             {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  7387.             {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  7388.         },
  7389.         {    // kDeepPattern
  7390.             { r11, r11, r11, r11, r11, r11, r11, r11, r10, r10, r10, r10, r10, r10, r10, r10 },
  7391.             {  r8, r10, r10, r10, r10, r10, r10, r10, r10,  r8,  r8,  r8,  r8,  r8,  r8,  r8 },
  7392.             {  r5,  r5,  r8,  r8,  r8,  r8,  r8,  r8,  r8,  r8,  r5,  r5,  r5,  r5,  r5,  r5 },
  7393.             {  r2,  r2,  r2,  r5,  r5,  r5,  r5,  r5,  r5,  r5,  r5,  r2,  r2,  r2,  r2,  r2 },
  7394.             {  rW,  rW,  rW,  rW,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  rW,  rW,  rW,  rW },
  7395.             {  r2,  r2,  r2,  r2,  r2,  r5,  r5,  r5,  r5,  r5,  r5,  r5,  r5,  r2,  r2,  r2 },
  7396.             {  r4,  r4,  r4,  r4,  r4,  r4,  r8,  r8,  r8,  r8,  r8,  r8,  r8,  r8,  r4,  r4 },
  7397.             {  r6,  r6,  r6,  r6,  r6,  r6,  r6, r10, r10, r10, r10, r10, r10, r10, r10,  r6 },
  7398.             {  r8,  r8,  r8,  r8,  r8,  r8,  r8,  r8, r11, r11, r11, r11, r11, r11, r11, r11 },
  7399.             { r12, r10, r10, r10, r10, r10, r10, r10, r10, r12, r12, r12, r12, r12, r12, r12 },
  7400.         },
  7401.     };
  7402.  
  7403. OSErr AGAProgressIndicator::AllocateProgressImages()
  7404.     {
  7405.     // Allocate the offscreen image for each radio button state.
  7406.  
  7407.     OSErr    result = noErr;
  7408.     Point    imageSize;
  7409.     
  7410.     imageSize.h = kProgressImageWidth;
  7411.     imageSize.v = kProgressImageHeight;
  7412.     
  7413.     for (UInt32 imageIndex = 0; imageIndex < kNumProgressPatterns; imageIndex++)
  7414.         {
  7415.         if (result == noErr)
  7416.             {
  7417.             mgOffscreenIndeterminateProgressImage[imageIndex] = new AGAOffscreenImage;
  7418.             
  7419.             result = mgOffscreenIndeterminateProgressImage[imageIndex]->CreateImageData(
  7420.                         imageSize,
  7421.                         &kIndeterminateProgressImage[imageIndex][0][0],
  7422.                         NULL, 
  7423.                         &gAGARamp[rB]);
  7424.             }
  7425.         }
  7426.         
  7427.     return result;
  7428.     }
  7429.  
  7430. void AGAProgressIndicator::DisposeProgressImages()
  7431.     {
  7432.     for (UInt32 imageIndex = 0; imageIndex < kNumProgressPatterns; imageIndex++)
  7433.         if (mgOffscreenIndeterminateProgressImage[imageIndex] != NULL)
  7434.             delete mgOffscreenIndeterminateProgressImage[imageIndex];
  7435.     }
  7436.  
  7437. AGAProgressIndicator::AGAProgressIndicator(Rect* bounds, SInt32 minimum, SInt32 maximum)
  7438. : AGAObject(bounds)
  7439.     {
  7440.     // Construct with default options.
  7441.     // (minimum == maximum) means indeterminate indicator.
  7442.  
  7443.     mMinimum = minimum;
  7444.     mMaximum = maximum;
  7445.     mValue = minimum;
  7446.     mOriginValue = minimum;
  7447.     mAnimationIndex = 0;
  7448.     mLastAnimationTime = 0;
  7449.     }
  7450.  
  7451. AGAProgressIndicator::~AGAProgressIndicator()
  7452.     {
  7453.     }
  7454.  
  7455. void AGAProgressIndicator::DrawObject()
  7456.     {
  7457.     // Draw at current gauge value or next animation step.
  7458.  
  7459.     this->DrawFrame();
  7460.     
  7461.     if (mMinimum == mMaximum)
  7462.         this->DrawAnimationStep();
  7463.     else
  7464.         this->DrawGauge();
  7465.     }
  7466.  
  7467. SInt32 AGAProgressIndicator::GetValue()
  7468.     {
  7469.     // Return current value.
  7470.  
  7471.     return mValue;
  7472.     }
  7473.  
  7474. void AGAProgressIndicator::SetValue(SInt32 newValue, Boolean redraw)
  7475.     {
  7476.     // Set gauge value, optionally redraw.
  7477.  
  7478.     // Constrain: mMinimum <= mValue <= mMaximum
  7479.     newValue = MaxSInt32(mMinimum, MinSInt32(newValue, mMaximum));
  7480.     
  7481.     if (newValue != mValue)
  7482.         {
  7483.         mValue = newValue;
  7484.         
  7485.         if (redraw)
  7486.             this->DrawGauge();
  7487.         }
  7488.     }
  7489.  
  7490. void AGAProgressIndicator::Increment(SInt32 delta, Boolean redraw)
  7491.     {
  7492.     // Increment gauge value, optionally redraw.
  7493.  
  7494.     this->SetValue(delta + this->GetValue(), redraw);
  7495.     }
  7496.  
  7497. void AGAProgressIndicator::Animate()
  7498.     {
  7499.     // Draw the next animation step.
  7500.  
  7501.     mAnimationIndex = (mAnimationIndex + 1) % kNumProgressAnimationSteps;
  7502.     
  7503.     this->DrawAnimationStep();
  7504.     }
  7505.  
  7506. void AGAProgressIndicator::QuantizedAnimate()
  7507.     {
  7508.     // Draw the next animation step if enough time has elapsed since the
  7509.     // last animation step.
  7510.     
  7511.     if (mMinimum == mMaximum)
  7512.         {
  7513.         SInt32    now = ::TickCount();
  7514.         
  7515.         if (now > mLastAnimationTime + kAnimationDelay)
  7516.             {
  7517.             mLastAnimationTime = now;
  7518.             this->Animate();
  7519.             }
  7520.         }
  7521.     }
  7522.  
  7523. void AGAProgressIndicator::GetRange(SInt32* minimum, SInt32* maximum)
  7524.     {
  7525.     // Return the gauge value range.
  7526.  
  7527.     *minimum = mMinimum;
  7528.     *maximum = mMaximum;
  7529.     }
  7530.  
  7531. void AGAProgressIndicator::SetRange(SInt32 newMinimum, SInt32 newMaximum, Boolean redraw)
  7532.     {
  7533.     // Set the gauge value range, optionally redraw.
  7534.     // (minimum == maximum) means indeterminate indicator.
  7535.  
  7536.     if (mOriginValue == mMinimum)
  7537.         mOriginValue = newMinimum;
  7538.  
  7539.     mMinimum = newMinimum;
  7540.     mMaximum = MaxSInt32(newMinimum, newMaximum);
  7541.     
  7542.     if (redraw)
  7543.         this->DrawObject();
  7544.     }
  7545.  
  7546. SInt32 AGAProgressIndicator::GetOriginValue()
  7547.     {
  7548.     // Return the optional gauge origin value.
  7549.  
  7550.     return mOriginValue;
  7551.     }
  7552.  
  7553. void AGAProgressIndicator::SetOriginValue(SInt32 newValue, Boolean redraw)
  7554.     {
  7555.     // Set the optional gauge origin value.
  7556.  
  7557.     // Constrain: mMinimum <= mOriginValue <= mValue
  7558.     newValue = MaxSInt32(mMinimum, MinSInt32(newValue, mValue));
  7559.  
  7560.     if (newValue != mOriginValue)
  7561.         {
  7562.         mOriginValue = newValue;
  7563.         
  7564.         if (redraw)
  7565.             this->DrawObject();
  7566.         }
  7567.     }
  7568.  
  7569. void AGAProgressIndicator::DrawFrame()
  7570.     {
  7571.     AGADrawingEnvironment    env;
  7572.  
  7573.     // Draw the constant frame around the indicator.
  7574.     Rect    r = mBounds;
  7575.     
  7576.     r.bottom = r.top + kProgressHeight;
  7577.     
  7578.  
  7579.     GDIterator    iter;
  7580.     Boolean        deep;
  7581.  
  7582.     while (iter.More(deep))
  7583.         {
  7584.         if (deep)
  7585.             {
  7586.             ::RGBForeColor(&gAGARamp[r5]);
  7587.             ::MoveTo(r.left, r.bottom - 2);
  7588.             ::LineTo(r.left, r.top);
  7589.             ::LineTo(r.right - 2, r.top);
  7590.             
  7591.             ::RGBForeColor(&gAGARamp[rW]);
  7592.             ::MoveTo(r.left + 1, r.bottom - 1);
  7593.             ::LineTo(r.right - 1, r.bottom - 1);
  7594.             ::LineTo(r.right - 1, r.top + 1);
  7595.             }
  7596.         
  7597.         ::InsetRect(&r, 1, 1);
  7598.         ::RGBForeColor(&gAGARamp[rB]);
  7599.         ::FrameRect(&r);
  7600.         ::InsetRect(&r, -1, -1);
  7601.         }
  7602.     }
  7603.  
  7604. void AGAProgressIndicator::DrawAnimationStep()
  7605.     {
  7606.     AGADrawingEnvironment    env;
  7607.  
  7608.     // Draw the indeterminate progress indicator at the
  7609.     // current animation step.
  7610.  
  7611.     const UInt32 kNumRows = 10;
  7612.  
  7613.     Rect    r = mBounds;
  7614.     SInt16    patternHOrigin;
  7615.     
  7616.     r.bottom = r.top + kProgressHeight;
  7617.     ::InsetRect(&r, 2, 2);
  7618.     
  7619.     //
  7620.     // Move the pen leftward so the pattern is offset for
  7621.     // the current animation step. This will mean we need
  7622.     // to explicitly clip to our gauge area, since our pattern
  7623.     // origin is outside it.
  7624.     //
  7625.  
  7626.     patternHOrigin = r.left - 32 + ((16 / kNumProgressAnimationSteps) * mAnimationIndex);
  7627.     
  7628.     RgnHandle    savedClip = ::NewRgn();
  7629.     ::GetClip(savedClip);
  7630.     
  7631.     AGAClipFurther(&r);
  7632.     
  7633.     r.left = patternHOrigin;
  7634.  
  7635.     {
  7636.     GDIterator    iter;
  7637.     Boolean        deep;
  7638.  
  7639.     while (iter.More(deep))
  7640.         {
  7641.         if (deep)
  7642.             mgOffscreenIndeterminateProgressImage[kDeepPattern]->DrawPattern(&r);
  7643.         else
  7644.             mgOffscreenIndeterminateProgressImage[k1BitPattern]->DrawPattern(&r);
  7645.         }
  7646.     }    // force GDIterator clip to clean up now, not after we set savedClip!
  7647.  
  7648.     ::SetClip(savedClip);
  7649.     ::DisposeRgn(savedClip);
  7650.     }
  7651.  
  7652. void AGAProgressIndicator::DrawGauge()
  7653.     {
  7654.     // Draw the determinate progress indicator.
  7655.  
  7656.     if (mOriginValue != mMinimum)
  7657.         this->DrawOriginArea();
  7658.     
  7659.     this->DrawProgressArea();
  7660.     this->DrawRemainderArea();
  7661.     }
  7662.  
  7663. void AGAProgressIndicator::DrawOriginArea()
  7664.     {
  7665.     // Draw the empty track between the minimum value
  7666.     // and the origin value.
  7667.  
  7668.     Rect    frame;
  7669.     
  7670.     if (this->GetOriginFrame(&frame))
  7671.         {
  7672.         GDIterator    iter;
  7673.         Boolean        deep;
  7674.  
  7675.         while (iter.More(deep))
  7676.             {
  7677.             Rect    r = frame;
  7678.  
  7679.             if (deep)
  7680.                 {
  7681.                 SInt16    width = r.right - r.left;
  7682.                 
  7683.                 if (width >= 0)
  7684.                     {
  7685.                     ::RGBForeColor(&gAGARamp[rB]);
  7686.                     ::MoveTo(r.right, r.top);
  7687.                     ::LineTo(r.right, r.bottom - 1);
  7688.                     }
  7689.  
  7690.                 if (width > 0)
  7691.                     {
  7692.                     ::RGBForeColor(&gAGARamp[r10]);
  7693.                     ::MoveTo(r.left, r.top);
  7694.                     ::LineTo(r.left, r.bottom - 1);
  7695.                     }
  7696.                 
  7697.                 if (width > 1)
  7698.                     {
  7699.                     ::RGBForeColor(&gAGARamp[r4]);
  7700.                     ::MoveTo(r.right - 1, r.top);
  7701.                     ::Line(0, 1);
  7702.                     ::RGBForeColor(&gAGARamp[r2]);
  7703.                     ::LineTo(r.right - 1, r.bottom - 1);
  7704.                     }
  7705.                 
  7706.                 if (width > 2)
  7707.                     {
  7708.                     ::RGBForeColor(&gAGARamp[r7]);
  7709.                     ::MoveTo(r.left + 1, r.top);
  7710.                     ::LineTo(r.left + 1, r.bottom - 1);
  7711.                     }
  7712.                 
  7713.                 if (width > 3)
  7714.                     {
  7715.                     ::RGBForeColor(&gAGARamp[r2]);
  7716.                     ::MoveTo(r.left + 2, r.bottom - 1);
  7717.                     ::LineTo(r.right - 1, r.bottom - 1);
  7718.  
  7719.                     ::RGBForeColor(&gAGARamp[r7]);
  7720.                     ::MoveTo(r.left + 2, r.top);
  7721.                     ::LineTo(r.right - 2, r.top);
  7722.  
  7723.                     ::RGBForeColor(&gAGARamp[r4]);
  7724.                     r.left += 2;
  7725.                     r.top++;
  7726.                     r.bottom--;
  7727.                     r.right--;
  7728.                     ::PaintRect(&r);
  7729.                     }
  7730.                 }
  7731.             else    // 1-bit
  7732.                 {
  7733.                 ::RGBForeColor(&gAGARamp[rW]);
  7734.                 ::PaintRect(&r);
  7735.                 }
  7736.             }
  7737.         }
  7738.     }
  7739.  
  7740. void AGAProgressIndicator::DrawProgressArea()
  7741.     {
  7742.     AGADrawingEnvironment    env;
  7743.  
  7744.     // Draw the filled progress gauge area between
  7745.     // the origin and the current value.
  7746.  
  7747.     Rect    frame;
  7748.     
  7749.     if (this->GetProgressFrame(&frame))
  7750.         {
  7751.         GDIterator    iter;
  7752.         Boolean        deep;
  7753.  
  7754.         while (iter.More(deep))
  7755.             {
  7756.             Rect    r = frame;
  7757.  
  7758.             if (deep)
  7759.                 {
  7760.                 SInt16    width = r.right - r.left;
  7761.  
  7762.                 //
  7763.                 // Because the endcaps of the gauge are shaded,
  7764.                 // we need to carefully draw the ends horizontal
  7765.                 // pixel by pixel, bailing out if there is not
  7766.                 // enough width to accomodate the endcaps and the
  7767.                 // midsection.
  7768.                 //
  7769.  
  7770.                 if (width > 0)
  7771.                     {
  7772.                     ::RGBForeColor(&gAGARamp[rB]);
  7773.                     ::MoveTo(r.right - 1, r.top);
  7774.                     ::LineTo(r.right - 1, r.bottom - 1);
  7775.                     }
  7776.  
  7777.                 if (width > 1)
  7778.                     {
  7779.                     ::RGBForeColor(&gAGARamp[r8]);
  7780.                     ::MoveTo(r.left, r.top);
  7781.                     ::LineTo(r.left, r.bottom - 1);
  7782.                     }
  7783.  
  7784.                 if (width > 2)
  7785.                     {
  7786.                     ::RGBForeColor(&gAGARamp[r10]);
  7787.                     ::MoveTo(r.right - 2, r.top);
  7788.                     ::Line(0, 1);
  7789.                     ::RGBForeColor(&gAGARamp[r12]);
  7790.                     ::LineTo(r.right - 2, r.bottom - 1);
  7791.                     }
  7792.  
  7793.                 if (width > 3)
  7794.                     {
  7795.                     ::RGBForeColor(&gAGARamp[r8]);
  7796.                     ::MoveTo(r.left + 1, r.top);
  7797.                     ::Line(0, 1);
  7798.                     ::RGBForeColor(&gAGARamp[r5]);
  7799.                     ::Line(0, 1);
  7800.                     ::RGBForeColor(&gAGARamp[r3]);
  7801.                     ::Line(0, 1);
  7802.                     ::RGBForeColor(&gAGARamp[r1]);
  7803.                     ::Line(0, 3);
  7804.                     ::RGBForeColor(&gAGARamp[r3]);
  7805.                     ::Line(0, 1);
  7806.                     ::RGBForeColor(&gAGARamp[r5]);
  7807.                     ::Line(0, 1);
  7808.                     ::RGBForeColor(&gAGARamp[r8]);
  7809.                     ::Line(0, 1);
  7810.                     ::RGBForeColor(&gAGARamp[r10]);
  7811.                     ::Line(0, 0);
  7812.                     }
  7813.  
  7814.                 if (width > 4)
  7815.                     {
  7816.                     ::RGBForeColor(&gAGARamp[r10]);
  7817.                     ::MoveTo(r.right - 3, r.top);
  7818.                     ::Line(0, 1);
  7819.                     ::RGBForeColor(&gAGARamp[r8]);
  7820.                     ::Line(0, 1);
  7821.                     ::RGBForeColor(&gAGARamp[r10]);
  7822.                     ::LineTo(r.right - 3, r.bottom - 1);
  7823.                     ::RGBForeColor(&gAGARamp[r12]);
  7824.                     ::Line(0, 0);
  7825.                     }
  7826.  
  7827.                 if (width > 5)
  7828.                     {
  7829.                     ::RGBForeColor(&gAGARamp[r10]);
  7830.                     ::MoveTo(r.right - 4, r.top);
  7831.                     ::Line(0, 1);
  7832.                     ::RGBForeColor(&gAGARamp[r8]);
  7833.                     ::Line(0, 1);
  7834.                     ::RGBForeColor(&gAGARamp[r5]);
  7835.                     ::Line(0, 1);
  7836.                     ::RGBForeColor(&gAGARamp[r3]);
  7837.                     ::Line(0, 3);
  7838.                     ::RGBForeColor(&gAGARamp[r5]);
  7839.                     ::Line(0, 1);
  7840.                     ::RGBForeColor(&gAGARamp[r8]);
  7841.                     ::Line(0, 1);
  7842.                     ::RGBForeColor(&gAGARamp[r10]);
  7843.                     ::Line(0, 1);
  7844.                     ::RGBForeColor(&gAGARamp[r12]);
  7845.                     ::Line(0, 0);
  7846.                     }
  7847.  
  7848.                 if (width > 6)
  7849.                     {
  7850.                     SInt16    distance = width - 7;
  7851.                     
  7852.                     ::RGBForeColor(&gAGARamp[r10]);
  7853.                     ::MoveTo(r.left + 2, r.top);
  7854.                     ::Line(distance, 0);
  7855.                     ::RGBForeColor(&gAGARamp[r8]);
  7856.                     ::MoveTo(r.left + 2, r.top + 1);
  7857.                     ::Line(distance, 0);
  7858.                     ::RGBForeColor(&gAGARamp[r5]);
  7859.                     ::MoveTo(r.left + 2, r.top + 2);
  7860.                     ::Line(distance, 0);
  7861.                     ::RGBForeColor(&gAGARamp[r3]);
  7862.                     ::MoveTo(r.left + 2, r.top + 3);
  7863.                     ::Line(distance, 0);
  7864.                     ::RGBForeColor(&gAGARamp[r1]);
  7865.                     ::MoveTo(r.left + 2, r.top + 4);
  7866.                     ::Line(distance, 0);
  7867.                     ::RGBForeColor(&gAGARamp[r3]);
  7868.                     ::MoveTo(r.left + 2, r.top + 5);
  7869.                     ::Line(distance, 0);
  7870.                     ::RGBForeColor(&gAGARamp[r5]);
  7871.                     ::MoveTo(r.left + 2, r.top + 6);
  7872.                     ::Line(distance, 0);
  7873.                     ::RGBForeColor(&gAGARamp[r8]);
  7874.                     ::MoveTo(r.left + 2, r.top + 7);
  7875.                     ::Line(distance, 0);
  7876.                     ::RGBForeColor(&gAGARamp[r10]);
  7877.                     ::MoveTo(r.left + 2, r.top + 8);
  7878.                     ::Line(distance, 0);
  7879.                     ::RGBForeColor(&gAGARamp[r12]);
  7880.                     ::MoveTo(r.left + 2, r.top + 9);
  7881.                     ::Line(distance, 0);
  7882.                     }
  7883.                 }
  7884.             else    // 1-bit
  7885.                 {
  7886.                 ::RGBForeColor(&gAGARamp[rB]);
  7887.                 ::PaintRect(&r);
  7888.                 }
  7889.             }
  7890.         }
  7891.     }
  7892.  
  7893. void AGAProgressIndicator::DrawRemainderArea()
  7894.     {
  7895.     AGADrawingEnvironment    env;
  7896.  
  7897.     // Draw the empty track area between the current
  7898.     // gauge value and the maximum.
  7899.  
  7900.     Rect    frame;
  7901.     
  7902.     if (this->GetRemainderFrame(&frame))
  7903.         {
  7904.         GDIterator    iter;
  7905.         Boolean        deep;
  7906.  
  7907.         while (iter.More(deep))
  7908.             {
  7909.             Rect    r = frame;
  7910.  
  7911.             if (deep)
  7912.                 {
  7913.                 SInt16    width = r.right - r.left;
  7914.                 
  7915.                 if (width > 0)
  7916.                     {
  7917.                     ::RGBForeColor(&gAGARamp[r10]);
  7918.                     ::MoveTo(r.left, r.top);
  7919.                     ::LineTo(r.left, r.bottom - 1);
  7920.                     }
  7921.                 
  7922.                 if (width > 1)
  7923.                     {
  7924.                     ::RGBForeColor(&gAGARamp[r4]);
  7925.                     ::MoveTo(r.right - 1, r.top);
  7926.                     ::Line(0, 1);
  7927.                     ::RGBForeColor(&gAGARamp[r2]);
  7928.                     ::LineTo(r.right - 1, r.bottom - 1);
  7929.                     }
  7930.                 
  7931.                 if (width > 2)
  7932.                     {
  7933.                     ::RGBForeColor(&gAGARamp[r7]);
  7934.                     ::MoveTo(r.left + 1, r.top);
  7935.                     ::LineTo(r.left + 1, r.bottom - 1);
  7936.                     }
  7937.                 
  7938.                 if (width > 3)
  7939.                     {
  7940.                     ::RGBForeColor(&gAGARamp[r2]);
  7941.                     ::MoveTo(r.left + 2, r.bottom - 1);
  7942.                     ::LineTo(r.right - 1, r.bottom - 1);
  7943.  
  7944.                     ::RGBForeColor(&gAGARamp[r7]);
  7945.                     ::MoveTo(r.left + 2, r.top);
  7946.                     ::LineTo(r.right - 2, r.top);
  7947.  
  7948.                     ::RGBForeColor(&gAGARamp[r4]);
  7949.                     r.left += 2;
  7950.                     r.top++;
  7951.                     r.bottom--;
  7952.                     r.right--;
  7953.                     ::PaintRect(&r);
  7954.                     }
  7955.                 }
  7956.             else    // 1-bit
  7957.                 {
  7958.                 ::RGBForeColor(&gAGARamp[rW]);
  7959.                 ::PaintRect(&r);
  7960.                 }
  7961.             }
  7962.         }
  7963.     }
  7964.  
  7965. Boolean AGAProgressIndicator::GetOriginFrame(Rect* originFrame)
  7966.     {
  7967.     // Return true (and the area) if there is an area
  7968.     // to be drawn for the empty origin part of the track.
  7969.  
  7970.     Boolean    isNeeded = false;
  7971.     
  7972.     if (mOriginValue != mMinimum)
  7973.         {
  7974.         isNeeded = true;
  7975.  
  7976.         this->GetRangeFrame(mMinimum, mOriginValue, originFrame);
  7977.         
  7978.         if (mOriginValue != mMaximum)
  7979.             originFrame->right--;
  7980.         }
  7981.  
  7982.     return isNeeded;
  7983.     }
  7984.  
  7985. Boolean AGAProgressIndicator::GetProgressFrame(Rect* progressFrame)
  7986.     {
  7987.     // Return true (and the area) if there is an area
  7988.     // to be drawn for the progress section of the gauge.
  7989.  
  7990.     Boolean    isNeeded = false;
  7991.     
  7992.     if (mValue != mOriginValue)
  7993.         {
  7994.         isNeeded = true;
  7995.  
  7996.         this->GetRangeFrame(mOriginValue, mValue, progressFrame);
  7997.         
  7998.         if (mValue == mMaximum)
  7999.             progressFrame->right++;
  8000.         }
  8001.  
  8002.     return isNeeded;
  8003.     }
  8004.  
  8005. Boolean AGAProgressIndicator::GetRemainderFrame(Rect* remainderFrame)
  8006.     {
  8007.     // Return true (and the area) if there is an area
  8008.     // to be drawn for the uncompleted gauge remainder area.
  8009.  
  8010.     Boolean    isNeeded = false;
  8011.     
  8012.     if (mMaximum != mValue)
  8013.         {
  8014.         isNeeded = true;
  8015.  
  8016.         this->GetRangeFrame(mValue, mMaximum, remainderFrame);
  8017.         }
  8018.  
  8019.     return isNeeded;
  8020.     }
  8021.  
  8022. void AGAProgressIndicator::GetRangeFrame(SInt32 startValue, SInt32 endValue, Rect* rangeFrame)
  8023.     {
  8024.     // Return the rectangle that the indicator draws in,
  8025.     // which does not include the constant border frame area.
  8026.  
  8027.     *rangeFrame = mBounds;
  8028.     rangeFrame->bottom = rangeFrame->top + kProgressHeight;
  8029.     
  8030.     ::InsetRect(rangeFrame, 2, 2);
  8031.  
  8032.     SInt32    divisor = mMaximum - mMinimum;
  8033.     
  8034.     if (divisor != 0)    // avoid divide by zero
  8035.         {
  8036.         SInt32    totalWidth = rangeFrame->right - rangeFrame->left;
  8037.         float    startFraction = ((float) (startValue - mMinimum)) / divisor;
  8038.         float    endFraction = ((float) (endValue - mMinimum)) / divisor;
  8039.  
  8040.         rangeFrame->right = rangeFrame->left + (endFraction * totalWidth);
  8041.         rangeFrame->left = rangeFrame->left + (startFraction * totalWidth);
  8042.         }
  8043.     }
  8044.  
  8045. //
  8046. // AGASeparator ---------------------------------------------------------------
  8047. //
  8048. // This class draws a separator line. It knowns whether it's horizontal or
  8049. // vertical based on the larger dimension.
  8050. //
  8051.  
  8052. AGASeparator::AGASeparator(Rect* bounds)
  8053. : AGAObject(bounds)
  8054.     {
  8055.     // Call superclass constructor.
  8056.     }
  8057.  
  8058. AGASeparator::~AGASeparator()
  8059.     {
  8060.     }
  8061.  
  8062. void AGASeparator::DrawObject()
  8063.     {
  8064.     AGADrawingEnvironment    env;
  8065.  
  8066.     // Draw the separator along the leading edge in
  8067.     // its longest dimension.
  8068.  
  8069.     Boolean    isHorizontal = ((mBounds.right - mBounds.left) > (mBounds.bottom - mBounds.top));
  8070.  
  8071.     GDIterator    iter;
  8072.     Boolean        deep;
  8073.  
  8074.     while (iter.More(deep))
  8075.         {
  8076.         if (deep)
  8077.             ::RGBForeColor(&gAGARamp[r7]);
  8078.         else
  8079.             {
  8080.             ::RGBForeColor(&gAGARamp[rB]);
  8081.             ::PenPat(&qd.gray);
  8082.             }
  8083.  
  8084.         ::MoveTo(mBounds.left, mBounds.top);
  8085.         
  8086.         if (isHorizontal)
  8087.             ::LineTo(mBounds.right - 2, mBounds.top);
  8088.         else
  8089.             ::LineTo(mBounds.left, mBounds.bottom - 2);
  8090.  
  8091.         if (deep)
  8092.             {
  8093.             ::RGBForeColor(&gAGARamp[rW]);
  8094.             ::MoveTo(mBounds.left + 1, mBounds.top + 1);
  8095.             
  8096.             if (isHorizontal)
  8097.                 ::LineTo(mBounds.right - 1, mBounds.top + 1);
  8098.             else
  8099.                 ::LineTo(mBounds.left + 1, mBounds.bottom - 1);
  8100.             }
  8101.         else
  8102.             ::PenPat(&qd.black);
  8103.         }
  8104.     }
  8105.  
  8106. //
  8107. // AGAGroupBox ---------------------------------------------------------------
  8108. //
  8109. // This class draws primary and secondary group boxes, with optional
  8110. // title label or title gap for a separate control.
  8111. //
  8112.  
  8113. AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType)
  8114. : AGAObject(bounds)
  8115.     {
  8116.     // Construct without a title or gap.
  8117.  
  8118.     mIsPrimaryBox = groupBoxType;
  8119.     mTitleGap = 0;
  8120.     mTitle[0] = 0;
  8121.     mTextStyle = textStyle;
  8122.     }
  8123.  
  8124. AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, SInt16 titleGap)
  8125. : AGAObject(bounds)
  8126.     {
  8127.     // Construct with specified gap.
  8128.  
  8129.     mIsPrimaryBox = groupBoxType;
  8130.     mTitleGap = titleGap;
  8131.     mTitle[0] = 0;
  8132.     mTextStyle = textStyle;
  8133.     }
  8134.  
  8135. AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, StringPtr titleString)
  8136. : AGAObject(bounds)
  8137.     {
  8138.     // Construct with specified title.
  8139.  
  8140.     mIsPrimaryBox = groupBoxType;
  8141.     mTitleGap = 0;
  8142.     AGA_PLstrcpy(mTitle, titleString);
  8143.     mTextStyle = textStyle;
  8144.     }
  8145.  
  8146. AGAGroupBox::AGAGroupBox(Rect* bounds, const AGATextStyle& textStyle, Boolean groupBoxType, SInt16 titleStringListResourceID, SInt16 titleStringIndex)
  8147. : AGAObject(bounds)
  8148.     {
  8149.     // Construct by getting title from specified resource.
  8150.  
  8151.     mIsPrimaryBox = groupBoxType;
  8152.     mTitleGap = 0;
  8153.     ::GetIndString(mTitle, titleStringListResourceID, titleStringIndex);
  8154.     mTextStyle = textStyle;
  8155.     }
  8156.  
  8157. AGAGroupBox::~AGAGroupBox()
  8158.     {
  8159.     }
  8160.  
  8161. void AGAGroupBox::SetTitleGap(SInt16 titleGap)
  8162.     {
  8163.     // Set the width of the title gap that will be left blank.
  8164.  
  8165.     mTitleGap = titleGap;
  8166.     }
  8167.  
  8168. void AGAGroupBox::SetTitle(StringPtr newTitle, Boolean redraw)
  8169.     {
  8170.     // Set the title, optionally redraw.
  8171.  
  8172.     AGA_PLstrcpy(mTitle, newTitle);
  8173.  
  8174.     if (redraw)
  8175.         this->DrawObject();
  8176.     }
  8177.  
  8178. void AGAGroupBox::DrawObject()
  8179.     {
  8180.     AGADrawingEnvironment    env;
  8181.  
  8182.     // Draw the group box.
  8183.  
  8184.     Rect        r = mBounds;
  8185.     SInt16        titleGap = 0;
  8186.     SInt16        topIndent = 0;
  8187.     FontInfo    fontInfo;
  8188.  
  8189.     if (mTitle[0] != 0)
  8190.         {
  8191.         mTextStyle.PrepareForDrawing();    // calculate gap for title's text style
  8192.         ::GetFontInfo(&fontInfo);
  8193.         
  8194.         topIndent = fontInfo.ascent;    // text baseline should be at frame top
  8195.         
  8196.         titleGap = 5 + ::StringWidth(mTitle);
  8197.         }
  8198.     else
  8199.         titleGap = mTitleGap;
  8200.  
  8201.     if (mIsPrimaryBox)
  8202.         this->DrawPrimaryFrame(topIndent, titleGap);
  8203.     else
  8204.         this->DrawSecondaryFrame(topIndent, titleGap);
  8205.  
  8206.     if (mTitle[0] != 0)
  8207.         {
  8208.         Rect    titleRect;
  8209.         
  8210.         titleRect.left = r.left + 14;
  8211.         titleRect.top = r.top + 2;
  8212.         titleRect.right = titleRect.left + titleGap;
  8213.         titleRect.bottom = titleRect.top + fontInfo.ascent + fontInfo.descent;
  8214.  
  8215.         GDIterator    iter;
  8216.         Boolean        deep;
  8217.  
  8218.         while (iter.More(deep))
  8219.             AGAStringOut(mTitle, &titleRect, kNoTruncation, teFlushDefault, mEnabled ? kNormalOutput : kDisabledOutput, deep, mTextStyle);
  8220.         }
  8221.     }
  8222.  
  8223. void AGAGroupBox::DrawPrimaryFrame(SInt16 topIndent, SInt16 gapSize)
  8224.     {
  8225.     // Draw the group box as a primary group.
  8226.  
  8227.     Rect    r = mBounds;
  8228.     
  8229.     r.top += topIndent;
  8230.  
  8231.     GDIterator    iter;
  8232.     Boolean        deep;
  8233.  
  8234.     while (iter.More(deep))
  8235.         {
  8236.         if (deep)
  8237.             {
  8238.             if (mEnabled)
  8239.                 ::RGBForeColor(&gAGARamp[r7]);
  8240.             else
  8241.                 ::RGBForeColor(&gAGARamp[r4]);
  8242.             }
  8243.         else
  8244.             {
  8245.             ::RGBForeColor(&gAGARamp[rB]);
  8246.             
  8247.             if (! mEnabled)
  8248.                 ::PenPat(&qd.gray);
  8249.             }
  8250.  
  8251.         ::MoveTo(r.right - 2, r.top);
  8252.         ::LineTo(r.right - 2, r.bottom - 2);
  8253.         ::LineTo(r.left, r.bottom - 2);
  8254.         ::LineTo(r.left, r.top);
  8255.         ::Line(10, 0);
  8256.         ::Move(gapSize, 0);
  8257.         ::LineTo(r.right - 2, r.top);
  8258.         
  8259.         if (deep)
  8260.             {
  8261.             if (mEnabled)
  8262.                 ::RGBForeColor(&gAGARamp[rW]);
  8263.             else
  8264.                 this->ApplyBackgroundColor();
  8265.  
  8266.             ::MoveTo(r.right - 1, r.top);
  8267.             ::LineTo(r.right - 1, r.bottom - 1);
  8268.             ::LineTo(r.left, r.bottom - 1);
  8269.             ::MoveTo(r.left + 1, r.bottom - 3);
  8270.             ::LineTo(r.left + 1, r.top + 1);
  8271.             ::Line(9, 0);
  8272.             ::Move(gapSize, 0);
  8273.             ::LineTo(r.right - 3, r.top + 1);
  8274.             }
  8275.         else
  8276.             ::PenPat(&qd.black);
  8277.         }
  8278.     }
  8279.  
  8280. void AGAGroupBox::DrawSecondaryFrame(SInt16 topIndent, SInt16 gapSize)
  8281.     {
  8282.     // Draw the group box as a secondary group.
  8283.  
  8284.     Rect    r = mBounds;
  8285.     
  8286.     r.top += topIndent;
  8287.  
  8288.     GDIterator    iter;
  8289.     Boolean        deep;
  8290.  
  8291.     while (iter.More(deep))
  8292.         {
  8293.         if (deep)
  8294.             {
  8295.             ::MoveTo(r.right - 1, r.top);
  8296.  
  8297.             if (mEnabled)
  8298.                 {
  8299.                 ::RGBForeColor(&gAGARamp[rW]);
  8300.                 ::Move(0, 1);
  8301.                 }
  8302.             else
  8303.                 ::RGBForeColor(&gAGARamp[r4]);
  8304.  
  8305.             ::LineTo(r.right - 1, r.bottom - 1);
  8306.             ::LineTo(r.left + 1, r.bottom - 1);
  8307.  
  8308.             if (mEnabled)
  8309.                 {
  8310.                 ::Move(-1, -1);
  8311.                 ::RGBForeColor(&gAGARamp[r7]);
  8312.                 }
  8313.             else
  8314.                 ::Line(-1, 0);
  8315.  
  8316.             ::LineTo(r.left, r.top);
  8317.             ::Line(10, 0);
  8318.             ::Move(gapSize, 0);
  8319.             ::LineTo(r.right - 2, r.top);
  8320.             }
  8321.         else
  8322.             {
  8323.             ::RGBForeColor(&gAGARamp[rB]);
  8324.             
  8325.             if (! mEnabled)
  8326.                 ::PenPat(&qd.gray);
  8327.  
  8328.             ::MoveTo(r.right - 2, r.top);
  8329.             ::LineTo(r.right - 2, r.bottom - 2);
  8330.             ::LineTo(r.left, r.bottom - 2);
  8331.             ::LineTo(r.left, r.top);
  8332.             ::Line(10, 0);
  8333.             ::Move(gapSize, 0);
  8334.             ::LineTo(r.right - 2, r.top);
  8335.             
  8336.             if (! mEnabled)
  8337.                 ::PenPat(&qd.black);
  8338.             }
  8339.         }
  8340.     }
  8341.  
  8342. //
  8343. // AGATabPanel ---------------------------------------------------------------
  8344. //
  8345. // AGATabPanel implements a folder tabs box, often referred to as a "tabbed
  8346. // dialog" interface.
  8347. //
  8348.  
  8349. AGATabPanel::AGATabPanel(Rect* bounds, SInt32 initialTabIndex, const AGATextStyle& textStyle, SInt16 labelsID)
  8350.     : AGAObject(bounds)
  8351.     {
  8352.     // Construct with default options.
  8353.     
  8354.     mNumTabs = 0;
  8355.     mCurrentTabIndex = initialTabIndex;
  8356.     mTabInfo = NULL;
  8357.     mTabsLocation = kTopTabs;
  8358.     mTabWidthKind = kVariableTabWidth;
  8359.     mDrawFrame = true;
  8360.     mTextStyle = textStyle;
  8361.     
  8362.     mTabSize = ((textStyle.mFontSize > 10) || (textStyle.mFontSize == 0)) ? kLargeTabs : kSmallTabs;
  8363.  
  8364.     this->CalculateTabSizeInfo();
  8365.     
  8366.     this->SetLabelsFromResource(labelsID);
  8367.     }
  8368.  
  8369. AGATabPanel::AGATabPanel(Rect* bounds, SInt32 initialTabIndex, const AGATextStyle& textStyle, SInt16 labelsID, TabWidthKind widthKind, TabsLocation location, Boolean drawFrame)
  8370.     : AGAObject(bounds)
  8371.     {
  8372.     // Construct with specified options.
  8373.  
  8374.     mNumTabs = 0;
  8375.     mCurrentTabIndex = initialTabIndex;
  8376.     mTabInfo = NULL;
  8377.     mTabsLocation = location;
  8378.     mTabWidthKind = widthKind;
  8379.     mDrawFrame = drawFrame;
  8380.     mTextStyle = textStyle;
  8381.  
  8382.     mTabSize = ((textStyle.mFontSize > 10) || (textStyle.mFontSize == 0)) ? kLargeTabs : kSmallTabs;
  8383.  
  8384.     this->CalculateTabSizeInfo();
  8385.  
  8386.     this->SetLabelsFromResource(labelsID);
  8387.     }
  8388.  
  8389. AGATabPanel::~AGATabPanel()
  8390.     {
  8391.     // Destruct by releasing memory allocated for labels.
  8392.  
  8393.     this->DisposeTabInfo();
  8394.     }
  8395.  
  8396. void AGATabPanel::DrawObject()
  8397.     {
  8398.     this->DrawBackground();
  8399.     this->DrawFrame();
  8400.     this->DrawTabs();
  8401.     }
  8402.  
  8403. Boolean AGATabPanel::TrackMouse(Point mouseLocation)
  8404.     {
  8405.     Boolean    wasItHit;
  8406.     Rect    tabRect;
  8407.  
  8408.     //
  8409.     // First we determine which tab, if any, was clicked.
  8410.     //
  8411.  
  8412.     mLastTabClicked = -1;
  8413.     
  8414.     for (SInt32 i = 0; i < mNumTabs; i++)
  8415.         {
  8416.         this->GetTabBounds(i, &tabRect);
  8417.         if (::PtInRect(mouseLocation, &tabRect) && this->IsTabEnabled(i))
  8418.             {
  8419.             mLastTabClicked = i;
  8420.             break;
  8421.             }
  8422.         }
  8423.     
  8424.     //
  8425.     // Now we let the standard in/out tracking occur.
  8426.     // Our hit test will compare with the mLastTabClicked
  8427.     // area.
  8428.     //
  8429.  
  8430.     wasItHit = AGAObject::TrackMouse(mouseLocation);
  8431.     
  8432.     if (! wasItHit)
  8433.         mLastTabClicked = -1;
  8434.         
  8435.     return wasItHit;
  8436.     }
  8437.  
  8438. void AGATabPanel::SetObjectBounds(Rect* bounds, Boolean redraw)
  8439.     {
  8440.     AGAObject::SetObjectBounds(bounds, redraw);
  8441.  
  8442.     this->CalculateTabWidths();
  8443.     this->CalculateTabSizeInfo();
  8444.     }
  8445.  
  8446. Boolean AGATabPanel::HitTest(Point mouseLocation)
  8447.     {
  8448.     Boolean    isIn;
  8449.  
  8450.     // Return true if the mouse is in the mLastTabClicked.
  8451.     
  8452.     if (mLastTabClicked == -1)
  8453.         isIn = false;
  8454.     else
  8455.         {
  8456.         Rect    tabRect;
  8457.  
  8458.         this->GetTabBounds(mLastTabClicked, &tabRect);
  8459.         
  8460.         isIn = ::PtInRect(mouseLocation, &tabRect);
  8461.         }
  8462.  
  8463.     return isIn;
  8464.     }
  8465.  
  8466. void AGATabPanel::SetTrackingState(Boolean isIn)
  8467.     {
  8468.     // Draw the mLastTabClicked pressed or unpressed as specified.
  8469.  
  8470.     if ((mLastTabClicked != -1) && (mLastTabClicked != mCurrentTabIndex))
  8471.         this->DrawOneTab(mLastTabClicked, isIn);
  8472.     }
  8473.  
  8474. SInt32 AGATabPanel::GetCurrentTab()
  8475.     {
  8476.     return mCurrentTabIndex;
  8477.     }
  8478.  
  8479. void AGATabPanel::SetCurrentTab(SInt32 tabIndex, Boolean redraw)
  8480.     {
  8481.     if (tabIndex != mCurrentTabIndex)
  8482.         {
  8483.         mCurrentTabIndex = tabIndex;
  8484.         
  8485.         if (redraw)
  8486.             this->DrawTabs();
  8487.         }
  8488.     }
  8489.  
  8490. SInt32 AGATabPanel::GetLastTabClicked()
  8491.     {
  8492.     return mLastTabClicked;
  8493.     }
  8494.  
  8495. void AGATabPanel::SetTabSize(TabSize size)
  8496.     {
  8497.     // Set the tabs size.
  8498.  
  8499.     mTabSize = size;
  8500.     this->CalculateTabSizeInfo();
  8501.     }
  8502.  
  8503. void AGATabPanel::SetTabsLocation(TabsLocation location)
  8504.     {
  8505.     // Set the tabs location.
  8506.  
  8507.     mTabsLocation = location;
  8508.     this->CalculateTabSizeInfo();
  8509.     }
  8510.  
  8511. void AGATabPanel::SetTabsWidth(TabWidthKind widthKind)
  8512.     {
  8513.     // Set the tabs width style.
  8514.  
  8515.     mTabWidthKind = widthKind;
  8516.     
  8517.     this->CalculateTabWidths();
  8518.     }
  8519.  
  8520. SInt16 AGATabPanel::GetTabHeight()
  8521.     {
  8522.     // Return the current tab image height (or width if oriented vertically).
  8523.  
  8524.     if ((mTabsLocation == kTopTabs) || (mTabsLocation == kBottomTabs))
  8525.         return mTabImageSize.v;
  8526.     else
  8527.         return mTabImageSize.h;
  8528.     }
  8529.  
  8530. Boolean AGATabPanel::HasFrame()
  8531.     {
  8532.     return mDrawFrame;
  8533.     }
  8534.  
  8535. void AGATabPanel::SetLabelsFromResource(SInt16 stringListResourceID)
  8536.     {
  8537.     // Build the tab labels from the specified 'STR#' resource.
  8538.     // A label slot is allocated for each string in the resource;
  8539.     // there will be a tab for each of these strings.
  8540.  
  8541.     this->DisposeTabInfo();
  8542.     
  8543.     if (stringListResourceID != 0)
  8544.         {
  8545.         SInt16**    stringListHandle = (SInt16**) ::GetResource('STR#', stringListResourceID);
  8546.         SInt32        numTabs = (stringListHandle == NULL) ? 0 : **stringListHandle;
  8547.         
  8548.         if (numTabs != 0)
  8549.             {
  8550.             this->AllocateTabInfo(numTabs, kShrinkToFit);
  8551.  
  8552.             for (SInt16 i = 0; i < mNumTabs; i++)
  8553.                 {
  8554.                 Str255    aLabel;
  8555.                 
  8556.                 ::GetIndString(aLabel, stringListResourceID, i+1);
  8557.                 this->SetTabLabel(i, aLabel);
  8558.                 }
  8559.             
  8560.             this->CalculateTabWidths();
  8561.             }
  8562.         }
  8563.     }
  8564.  
  8565. void AGATabPanel::SetNumTabs(SInt32 numTabs, Boolean shrinkToFit)
  8566.     {
  8567.     // Allocate slots for the specified number of labels.
  8568.     
  8569.     this->AllocateTabInfo(numTabs, shrinkToFit);
  8570.     
  8571.     // In case the caller never informs us when the labels have
  8572.     // all been set (i.e., never calls CalculateTabWidths), we
  8573.     // init the widths to fill the bounds.
  8574.     
  8575.     this->CalculateTabWidthsByKind(kVariableTabWidth);
  8576.     }
  8577.  
  8578. SInt32 AGATabPanel::GetNumTabs()
  8579.     {
  8580.     return mNumTabs;
  8581.     }
  8582.  
  8583. void AGATabPanel::AllocateTabInfo(SInt32 numTabs, Boolean shrinkToFit)
  8584.     {
  8585.     // Make sure the tab info handle is sized to fit the
  8586.     // specified number of tabs.
  8587.     
  8588.     if (mTabInfo == NULL)
  8589.         {
  8590.         mTabInfo = (TabInfoHandle) ::NewHandleClear(numTabs * sizeof(TabInfo));
  8591.         
  8592.         if (mTabInfo == NULL)
  8593.             mNumTabs = 0;
  8594.         else
  8595.             mNumTabs = numTabs;
  8596.         }
  8597.     else if ((mNumTabs < numTabs) || (shrinkToFit && (mNumTabs > numTabs)))
  8598.         {
  8599.         ::SetHandleSize((Handle) mTabInfo, numTabs * sizeof(TabInfo));
  8600.         
  8601.         if (::MemError() != noErr)
  8602.             return;
  8603.         
  8604.         // Make sure the new tab info elements are zeroed like NewHandleClear.
  8605.  
  8606.         for (SInt32 i = mNumTabs; i < numTabs; i++)
  8607.             {
  8608.             (*mTabInfo)[i].mLabel = NULL;
  8609.             (*mTabInfo)[i].mTabWidth = 0;
  8610.             (*mTabInfo)[i].mDisabled = false;
  8611.             (*mTabInfo)[i].mUserData = NULL;
  8612.             }
  8613.  
  8614.         mNumTabs = numTabs;
  8615.         }
  8616.     }
  8617.  
  8618. void AGATabPanel::SetTabLabel(SInt32 tabIndex, StringPtr itsLabel)
  8619.     {
  8620.     // Assign the specified string to the specified label slot.
  8621.  
  8622.     if (mTabInfo != NULL)
  8623.         {
  8624.         if (tabIndex < mNumTabs)
  8625.             (*mTabInfo)[tabIndex].mLabel = ::NewString(itsLabel);
  8626.         }
  8627.     }
  8628.  
  8629. void AGATabPanel::GetTabLabel(SInt32 tabIndex, StringPtr itsLabel)
  8630.     {
  8631.     // Return the label string of the specified label slot.
  8632.  
  8633.     itsLabel[0] = 0;
  8634.  
  8635.     if (mTabInfo != NULL)
  8636.         {
  8637.         if (tabIndex < mNumTabs)
  8638.             {
  8639.             StringHandle    labelStringHandle = (*mTabInfo)[tabIndex].mLabel;
  8640.             
  8641.             if (labelStringHandle != NULL)
  8642.                 {
  8643.                 Ptr    sourceStringPtr = (Ptr) *((*mTabInfo)[tabIndex].mLabel);
  8644.  
  8645.                 ::BlockMoveData(sourceStringPtr, itsLabel, 1 + *sourceStringPtr);
  8646.                 }
  8647.             }
  8648.         }
  8649.     }
  8650.  
  8651. void AGATabPanel::SetTabEnable(SInt32 tabIndex, Boolean enable)
  8652.     {
  8653.     // Enable or disable the specified tab.
  8654.  
  8655.     if (mTabInfo != NULL)
  8656.         {
  8657.         if (tabIndex < mNumTabs)
  8658.             (*mTabInfo)[tabIndex].mDisabled = ! enable;
  8659.         }
  8660.     }
  8661.  
  8662. Boolean AGATabPanel::IsTabEnabled(SInt32 tabIndex)
  8663.     {
  8664.     // Return the enable state of the specified tab.
  8665.     
  8666.     Boolean    isEnabled = true;
  8667.  
  8668.     if (mTabInfo != NULL)
  8669.         {
  8670.         if (tabIndex < mNumTabs)
  8671.             isEnabled = ! (*mTabInfo)[tabIndex].mDisabled;
  8672.         }
  8673.     
  8674.     return isEnabled;
  8675.     }
  8676.  
  8677. void AGATabPanel::SetTabUserData(SInt32 tabIndex, void* userData)
  8678.     {
  8679.     // Stash the userData in the specified tab's info.
  8680.  
  8681.     if (mTabInfo != NULL)
  8682.         {
  8683.         if (tabIndex < mNumTabs)
  8684.             (*mTabInfo)[tabIndex].mUserData = userData;
  8685.         }
  8686.     }
  8687.  
  8688. void* AGATabPanel::GetTabUserData(SInt32 tabIndex)
  8689.     {
  8690.     // Return the specified tab's mUserData.
  8691.     
  8692.     void*    userData = NULL;
  8693.  
  8694.     if (mTabInfo != NULL)
  8695.         {
  8696.         if (tabIndex < mNumTabs)
  8697.             userData = (*mTabInfo)[tabIndex].mUserData;
  8698.         }
  8699.     
  8700.     return userData;
  8701.     }
  8702.  
  8703. void AGATabPanel::SetLabelsStyle(const AGATextStyle& textStyle)
  8704.     {
  8705.     // Set the QuickDraw text style for the labels.
  8706.  
  8707.     mTextStyle = textStyle;
  8708.     
  8709.     this->CalculateTabWidths();
  8710.     this->CalculateTabSizeInfo();
  8711.     }
  8712.  
  8713. void AGATabPanel::CalculateTabWidths()
  8714.     {
  8715.     this->CalculateTabWidthsByKind(mTabWidthKind);
  8716.     }
  8717.  
  8718. void AGATabPanel::CalculateTabWidthsByKind(TabWidthKind widthKind)
  8719.     {
  8720.     SInt32        widthAvailable;
  8721.     Str255        aLabel;
  8722.     SInt32        tabWidth;
  8723.     SInt32        totalWidth;
  8724.     SInt32        overflow;
  8725.     SInt32        tabEndWidth;
  8726.     
  8727.     if ((mTabsLocation == kTopTabs) || (mTabsLocation == kBottomTabs))
  8728.         {
  8729.         widthAvailable = mBounds.right - mBounds.left - (2 * kPanelEndMargin);
  8730.         tabEndWidth = mTabImageSize.h;
  8731.         }
  8732.     else
  8733.         {
  8734.         widthAvailable = mBounds.bottom - mBounds.top - (2 * kPanelEndMargin);
  8735.         tabEndWidth = mTabImageSize.v;
  8736.         }
  8737.  
  8738.     mTextStyle.PrepareForDrawing();
  8739.     
  8740.     switch (widthKind)
  8741.         {
  8742.         case kVariableTabWidth:
  8743.         
  8744.             totalWidth = 0;
  8745.  
  8746.             for (SInt32 i = 0; i < mNumTabs; i++)
  8747.                 {
  8748.                 this->GetTabLabel(i, aLabel);
  8749.                 tabWidth = ::StringWidth(aLabel) + (2 * tabEndWidth);
  8750.  
  8751.                 totalWidth += tabWidth;
  8752.                 (*mTabInfo)[i].mTabWidth = tabWidth;
  8753.                 }
  8754.             
  8755.             // If we overflowed the available width, reduce the tab sizes.
  8756.  
  8757.             overflow = totalWidth - widthAvailable;
  8758.  
  8759.             if (overflow > 0)
  8760.                 for (SInt32 i = 0; i < mNumTabs; i++)
  8761.                     (*mTabInfo)[i].mTabWidth -= (1 + (overflow / mNumTabs));
  8762.             break;
  8763.  
  8764.         case kCommonTabWidth:
  8765.  
  8766.             tabWidth = 0;
  8767.  
  8768.             for (SInt32 i = 0; i < mNumTabs; i++)
  8769.                 {
  8770.                 this->GetTabLabel(i, aLabel);
  8771.                 tabWidth = MaxSInt32(tabWidth, ::StringWidth(aLabel));
  8772.                 }
  8773.             
  8774.             tabWidth += (2 * tabEndWidth);
  8775.  
  8776.             for (SInt32 i = 0; i < mNumTabs; i++)
  8777.                 (*mTabInfo)[i].mTabWidth = tabWidth;
  8778.  
  8779.             // If we overflowed the available width, reduce the tab sizes.
  8780.  
  8781.             overflow = (tabWidth * mNumTabs) - widthAvailable;
  8782.  
  8783.             if (overflow > 0)
  8784.                 for (SInt32 i = 0; i < mNumTabs; i++)
  8785.                     (*mTabInfo)[i].mTabWidth -= (1 + (overflow / mNumTabs));
  8786.  
  8787.             break;
  8788.         }
  8789.     }
  8790.  
  8791. void AGATabPanel::DrawBackground()
  8792.     {
  8793.     AGADrawingEnvironment    env;
  8794.  
  8795.     // Paint the background.
  8796.  
  8797.     GDIterator    iter;
  8798.     Boolean        deep;
  8799.  
  8800.     while (iter.More(deep))
  8801.         {
  8802.         if (deep)
  8803.             this->ApplyBackgroundColor();
  8804.         else
  8805.             ::RGBForeColor(&gAGARamp[rW]);
  8806.  
  8807.         ::PaintRect(&mBounds);
  8808.         }
  8809.     }
  8810.  
  8811. void AGATabPanel::DrawFrame()
  8812.     {
  8813.     // If we have a frame, draw it; otherwise, draw the line/shading
  8814.     // for just the tabs edge.
  8815.  
  8816.     if (mDrawFrame)
  8817.         this->DrawFrameBox();
  8818.     else
  8819.         this->DrawFrameTop();
  8820.     }
  8821.  
  8822. void AGATabPanel::DrawFrameTop()
  8823.     {
  8824.     // Draw the line and shading for the tabs without a frame.
  8825.  
  8826.     AGADrawingEnvironment    env;
  8827.  
  8828.     Rect    frameBounds = mBounds;
  8829.  
  8830.     frameBounds.top = frameBounds.bottom - 3;
  8831.     
  8832.     GDIterator    iter;
  8833.     Boolean        deep;
  8834.  
  8835.     while (iter.More(deep))
  8836.         {
  8837.         Rect    r = frameBounds;
  8838.         
  8839.         if (deep && !mEnabled)
  8840.             ::RGBForeColor(&gAGARamp[r10]);
  8841.         else
  8842.             ::RGBForeColor(&gAGARamp[rB]);
  8843.  
  8844.         ::MoveTo(r.left, r.top);
  8845.         ::LineTo(r.right - 1, r.top);
  8846.         
  8847.         if (deep)
  8848.             {
  8849.             if (mEnabled)
  8850.                 ::RGBForeColor(&gAGARamp[r3]);
  8851.             else
  8852.                 ::RGBForeColor(&gAGARamp[r2]);
  8853.  
  8854.             ::MoveTo(r.left + 1, r.top + 1);
  8855.             ::LineTo(r.right - 2, r.top + 1);
  8856.  
  8857.             if (mEnabled)
  8858.                 ::RGBForeColor(&gAGARamp[rW]);
  8859.             else
  8860.                 ::RGBForeColor(&gAGARamp[r2]);
  8861.  
  8862.             ::MoveTo(r.left + 2, r.top + 2);
  8863.             ::LineTo(r.right - 3, r.top + 2);
  8864.             }
  8865.         }
  8866.     }
  8867.  
  8868. void AGATabPanel::DrawFrameBox()
  8869.     {
  8870.     // Draw the tab panel frame box.
  8871.  
  8872.     AGADrawingEnvironment    env;
  8873.  
  8874.     enum { Frame, Fill, LightOuter, LightInner, DarkOuter, DarkInner, kNumFrameColors };
  8875.  
  8876.     UInt8    colorIndexes[kNumFrameColors];
  8877.     Rect    frameBounds = mBounds;
  8878.     
  8879.     if (mEnabled)
  8880.         {
  8881.         colorIndexes[Frame] = rB;
  8882.         colorIndexes[Fill] = r1;
  8883.         colorIndexes[LightOuter] = r3;
  8884.         colorIndexes[LightInner] = rW;
  8885.         colorIndexes[DarkOuter] = r6;
  8886.         colorIndexes[DarkInner] = r4;
  8887.         }
  8888.     else
  8889.         {
  8890.         colorIndexes[Frame] = r10;
  8891.         colorIndexes[Fill] = r2;
  8892.         colorIndexes[LightOuter] = r2;
  8893.         colorIndexes[LightInner] = r2;
  8894.         colorIndexes[DarkOuter] = r2;
  8895.         colorIndexes[DarkInner] = r2;
  8896.         }
  8897.  
  8898.     frameBounds.top += (mTabImageSize.v - 3);
  8899.     
  8900.     GDIterator    iter;
  8901.     Boolean        deep;
  8902.  
  8903.     while (iter.More(deep))
  8904.         {
  8905.         Rect    r = frameBounds;
  8906.         
  8907.         if (deep)
  8908.             ::RGBForeColor(&gAGARamp[colorIndexes[Frame]]);
  8909.         else
  8910.             {
  8911.             ::RGBForeColor(&gAGARamp[rB]);
  8912.             
  8913.             if (! mEnabled)
  8914.                 ::PenPat(&qd.gray);
  8915.             }
  8916.         
  8917.         ::FrameRect(&r);
  8918.         
  8919.         if (deep)
  8920.             ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  8921.         else
  8922.             {
  8923.             ::RGBForeColor(&gAGARamp[rW]);
  8924.             
  8925.             if (! mEnabled)    // put it back if we set to gray above
  8926.                 ::PenPat(&qd.black);
  8927.             }
  8928.             
  8929.         ::InsetRect(&r, 1, 1);
  8930.         ::PaintRect(&r);
  8931.         
  8932.         if (deep && mEnabled)    // disabled has no raised light/dark edges
  8933.             {
  8934.             ::RGBForeColor(&gAGARamp[colorIndexes[LightOuter]]);
  8935.             ::MoveTo(r.left, r.bottom - 2);
  8936.             ::LineTo(r.left, r.top);
  8937.             ::LineTo(r.right - 2, r.top);
  8938.  
  8939.             ::RGBForeColor(&gAGARamp[colorIndexes[DarkOuter]]);
  8940.             ::Move(1, 1);
  8941.             ::LineTo(r.right - 1, r.bottom - 1);
  8942.             ::LineTo(r.left + 1, r.bottom - 1);
  8943.  
  8944.             ::RGBForeColor(&gAGARamp[colorIndexes[LightInner]]);
  8945.             ::Move(0, -2);
  8946.             ::LineTo(r.left + 1, r.top + 1);
  8947.             ::LineTo(r.right - 3, r.top + 1);
  8948.  
  8949.             ::RGBForeColor(&gAGARamp[colorIndexes[DarkInner]]);
  8950.             ::Move(1, 1);
  8951.             ::LineTo(r.right - 2, r.bottom - 2);
  8952.             ::LineTo(r.left + 2, r.bottom - 2);
  8953.             
  8954.             ::RGBForeColor(&gAGARamp[r2]);
  8955.             ::MoveTo(r.left, r.bottom - 1);
  8956.             ::Line(0, 0);
  8957.             ::MoveTo(r.top, r.right - 1);
  8958.             ::Line(0, 0);
  8959.             }
  8960.         }
  8961.     }
  8962.  
  8963. void AGATabPanel::DrawTabs()
  8964.     {
  8965.     // Draw the tabs, one at a time.
  8966.  
  8967.     for (SInt32 i = 0; i < mNumTabs; i++)
  8968.         this->DrawOneTab(i, kNotPressed);
  8969.     }
  8970.  
  8971. void AGATabPanel::DrawOneTab(SInt32 tabIndex, Boolean pressed)
  8972.     {
  8973.     // Draw the specified tab.
  8974.  
  8975.     AGADrawingEnvironment    env;
  8976.  
  8977.     enum { EdgeFrame, OuterEdge, InnerEdge, Fill, InteriorFrame, InteriorOuterEdge, InteriorInnerEdge, kNumTabColors };
  8978.  
  8979.     UInt8    colorIndexes[kNumTabColors];
  8980.  
  8981.     Boolean                selected = (tabIndex == mCurrentTabIndex);
  8982.     Rect                tabBounds;
  8983.     Str255                tabLabel;
  8984.     Point                tabOrigin;
  8985.     AGAStringOutColor    textColor;
  8986.     UInt32                leftImageIndex;
  8987.     UInt32                rightImageIndex;
  8988.  
  8989.     this->GetTabBounds(tabIndex, &tabBounds);
  8990.     this->GetTabLabel(tabIndex, tabLabel);
  8991.     
  8992.     tabBounds.left += mTabImageSize.h;
  8993.     tabBounds.right -= mTabImageSize.h;
  8994.  
  8995.     if ((! mEnabled) || ! this->IsTabEnabled(tabIndex))
  8996.         {
  8997.         textColor = kDisabledOutput;
  8998.         leftImageIndex = selected ? kTabDisabledSelectedL : kTabDisabledDeselectedL;
  8999.         rightImageIndex = selected ? kTabDisabledSelectedR : kTabDisabledDeselectedR;
  9000.  
  9001.         colorIndexes[EdgeFrame] = r10;
  9002.         colorIndexes[OuterEdge] = r2;
  9003.         colorIndexes[InnerEdge] = r2;
  9004.         colorIndexes[Fill] = r2;
  9005.         colorIndexes[InteriorFrame] = selected ? r2 : r10;
  9006.         colorIndexes[InteriorOuterEdge] = r2;
  9007.         colorIndexes[InteriorInnerEdge] = r2;
  9008.         }
  9009.     else if (pressed)
  9010.         {
  9011.         textColor = kInverseOutput;
  9012.         leftImageIndex = kTabPressedL;
  9013.         rightImageIndex = kTabPressedR;
  9014.  
  9015.         colorIndexes[EdgeFrame] = rB;
  9016.         colorIndexes[OuterEdge] = r11;
  9017.         colorIndexes[InnerEdge] = r10;
  9018.         colorIndexes[Fill] = r9;
  9019.         colorIndexes[InteriorFrame] = rB;
  9020.         colorIndexes[InteriorOuterEdge] = r3;
  9021.         colorIndexes[InteriorInnerEdge] = rW;
  9022.         }
  9023.     else if (selected)
  9024.         {
  9025.         textColor = kNormalOutput;
  9026.         leftImageIndex = kTabNormalSelectedL;
  9027.         rightImageIndex = kTabNormalSelectedR;
  9028.  
  9029.         colorIndexes[EdgeFrame] = rB;
  9030.         colorIndexes[OuterEdge] = r3;
  9031.         colorIndexes[InnerEdge] = rW;
  9032.         colorIndexes[Fill] = r1;
  9033.         colorIndexes[InteriorFrame] = r1;
  9034.         colorIndexes[InteriorOuterEdge] = r1;
  9035.         colorIndexes[InteriorInnerEdge] = r1;
  9036.         }
  9037.     else
  9038.         {
  9039.         textColor = kNormalOutput;
  9040.         leftImageIndex = kTabNormalDeselectedL;
  9041.         rightImageIndex = kTabNormalDeselectedR;
  9042.  
  9043.         colorIndexes[EdgeFrame] = rB;
  9044.         colorIndexes[OuterEdge] = r3;
  9045.         colorIndexes[InnerEdge] = r2;
  9046.         colorIndexes[Fill] = r3;
  9047.         colorIndexes[InteriorFrame] = rB;
  9048.         colorIndexes[InteriorOuterEdge] = r3;
  9049.         colorIndexes[InteriorInnerEdge] = rW;
  9050.         }
  9051.     
  9052.     // Note that at this point, tabBounds is inset to avoid
  9053.     // the corner images.
  9054.  
  9055.     GDIterator    iter;
  9056.     Boolean        deep;
  9057.  
  9058.     while (iter.More(deep))
  9059.         {
  9060.         // Draw the tab corner images.
  9061.  
  9062.         tabOrigin.h = tabBounds.left - mTabImageSize.h;
  9063.         tabOrigin.v = tabBounds.top;
  9064.         
  9065.         this->CopyTabImage(leftImageIndex, tabOrigin, deep);
  9066.         tabOrigin.h = tabBounds.right;
  9067.         this->CopyTabImage(rightImageIndex, tabOrigin, deep);
  9068.         
  9069.         // Draw the straight edge shading.
  9070.  
  9071.         Rect    r = tabBounds;
  9072.  
  9073.         ::RGBForeColor(&gAGARamp[colorIndexes[EdgeFrame]]);
  9074.         ::MoveTo(r.left, r.top);
  9075.         ::LineTo(r.right - 1, r.top);
  9076.         
  9077.         if (deep)
  9078.             {
  9079.             r.top++;
  9080.             r.bottom--;
  9081.  
  9082.             ::RGBForeColor(&gAGARamp[colorIndexes[OuterEdge]]);
  9083.             ::MoveTo(r.left, r.top);
  9084.             ::LineTo(r.right - 1, r.top);
  9085.             r.top++;
  9086.  
  9087.             ::RGBForeColor(&gAGARamp[colorIndexes[InnerEdge]]);
  9088.             ::MoveTo(r.left, r.top);
  9089.             ::LineTo(r.right - 1, r.top);
  9090.             r.top++;
  9091.             
  9092.             ::RGBForeColor(&gAGARamp[colorIndexes[InteriorInnerEdge]]);
  9093.             ::MoveTo(r.left, r.bottom);
  9094.             ::LineTo(r.right - 1, r.bottom);
  9095.  
  9096.             r.bottom--;
  9097.             ::RGBForeColor(&gAGARamp[colorIndexes[InteriorOuterEdge]]);
  9098.             ::MoveTo(r.left, r.bottom);
  9099.             ::LineTo(r.right - 1, r.bottom);
  9100.  
  9101.             r.bottom--;
  9102.             ::RGBForeColor(&gAGARamp[colorIndexes[InteriorFrame]]);
  9103.             ::MoveTo(r.left, r.bottom);
  9104.             ::LineTo(r.right - 1, r.bottom);
  9105.  
  9106.             ::RGBForeColor(&gAGARamp[colorIndexes[Fill]]);
  9107.             ::PaintRect(&r);
  9108.             }
  9109.         else
  9110.             {
  9111.             // For 1-bit drawing, there's a pixel at the bottom that
  9112.             // may need to be erased or re-drawn. It's either leftover
  9113.             // from the frame (need to erase), or missing from being
  9114.             // previously selected (need to draw).
  9115.             
  9116.             r.bottom -= 3;
  9117.             r.top++;
  9118.  
  9119.             if (selected)
  9120.                 ::RGBForeColor(&gAGARamp[rW]);
  9121.             else
  9122.                 ::RGBForeColor(&gAGARamp[rB]);
  9123.  
  9124.             ::MoveTo(r.left, r.bottom);
  9125.             ::LineTo(r.right - 1, r.bottom);
  9126.             
  9127.             // The enable state of the tabs as a whole, and this
  9128.             // tab in particular require us to paint a gray pattern over
  9129.             // some or all of the tab corner images.
  9130.  
  9131.             if ((! mEnabled) || ! this->IsTabEnabled(tabIndex))
  9132.                 {
  9133.                 Rect    rectToPaint = tabBounds;
  9134.                 
  9135.                 rectToPaint.left -= mTabImageSize.h;
  9136.                 rectToPaint.right += mTabImageSize.h;
  9137.                 
  9138.                 // If whole thing is enabled but this tab is disabled,
  9139.                 // make sure we don't gray out the box frame line segment.
  9140.                 if (mEnabled && ! this->IsTabEnabled(tabIndex))
  9141.                     rectToPaint.bottom -= 3;
  9142.  
  9143.                 ::PenPat(&qd.gray);
  9144.                 ::PenMode(patBic);
  9145.                 ::PaintRect(&rectToPaint);
  9146.                 
  9147.                 ::PenNormal();
  9148.                 }
  9149.             
  9150.             // We also need to paint the tab rectangular inside area
  9151.             // black or white, depending on whether the tab is pressed,
  9152.             // in preparation for the label text.
  9153.             
  9154.             if (pressed)
  9155.                 ::RGBForeColor(&gAGARamp[rB]);
  9156.             else
  9157.                 ::RGBForeColor(&gAGARamp[rW]);
  9158.  
  9159.             ::PaintRect(&r);
  9160.             }
  9161.         
  9162.         AGAStringOut(tabLabel, &tabBounds, smTruncMiddle, teCenter, textColor, deep, mTextStyle);
  9163.         }
  9164.     }
  9165.  
  9166. void AGATabPanel::GetTabBounds(SInt32 tabIndex, Rect* tabBounds)
  9167.     {
  9168.     // Return the bounds of the specified tab.
  9169.  
  9170.     SInt16    tabOrigin = kPanelEndMargin;
  9171.     SInt16    tabWidth = (*mTabInfo)[tabIndex].mTabWidth;
  9172.     
  9173.     for (SInt32 i = 0; i < tabIndex; i++)
  9174.         tabOrigin += (*mTabInfo)[i].mTabWidth;;
  9175.  
  9176.     switch (mTabsLocation)
  9177.         {
  9178.         case kTopTabs:
  9179.         case kBottomTabs:
  9180.  
  9181.             tabBounds->left = mBounds.left + tabOrigin;
  9182.             tabBounds->right = tabBounds->left + tabWidth;
  9183.             
  9184.             if ((mDrawFrame && (mTabsLocation == kTopTabs)) ||
  9185.                 (!mDrawFrame && (mTabsLocation == kBottomTabs)))
  9186.                 {
  9187.                 tabBounds->top = mBounds.top;
  9188.                 tabBounds->bottom = mBounds.top + mTabImageSize.v;
  9189.                 }
  9190.             else
  9191.                 {
  9192.                 tabBounds->top = mBounds.bottom - mTabImageSize.v;
  9193.                 tabBounds->bottom = mBounds.bottom;
  9194.                 }
  9195.  
  9196.             break;
  9197.  
  9198.         case kLeftTabs:
  9199.         case kRightTabs:
  9200.  
  9201.             tabBounds->top = mBounds.top + tabOrigin;
  9202.             tabBounds->bottom = tabBounds->top + tabWidth;
  9203.             
  9204.             if ((mDrawFrame && (mTabsLocation == kLeftTabs)) ||
  9205.                 (!mDrawFrame && (mTabsLocation == kRightTabs)))
  9206.                 {
  9207.                 tabBounds->left = mBounds.left;
  9208.                 tabBounds->right = mBounds.left + mTabImageSize.h;
  9209.                 }
  9210.             else
  9211.                 {
  9212.                 tabBounds->left = mBounds.right - mTabImageSize.h;
  9213.                 tabBounds->right = mBounds.right;
  9214.                 }
  9215.  
  9216.             break;
  9217.         }
  9218.     }
  9219.  
  9220. void AGATabPanel::CalculateTabSizeInfo()
  9221.     {
  9222.     // Recalculate the tab image size based on the tab size kind and
  9223.     // the tab location orientation.
  9224.     // Decide whether our bounds are large enough to draw a frame.
  9225.  
  9226.     switch (mTabSize)
  9227.         {
  9228.         case kSmallTabs:
  9229.         
  9230.             switch (mTabsLocation)
  9231.                 {
  9232.                 case kTopTabs:
  9233.                 case kBottomTabs:
  9234.                     ::SetPt(&mTabImageSize, kSmallTabImageWidth, kSmallTabImageHeight);
  9235.                     break;
  9236.  
  9237.                 case kLeftTabs:
  9238.                 case kRightTabs:
  9239.                     ::SetPt(&mTabImageSize, kSmallTabImageHeight, kSmallTabImageWidth);
  9240.                     break;
  9241.                 }
  9242.  
  9243.             break;
  9244.  
  9245.         case kLargeTabs:
  9246.         
  9247.             switch (mTabsLocation)
  9248.                 {
  9249.                 case kTopTabs:
  9250.                 case kBottomTabs:
  9251.                     ::SetPt(&mTabImageSize, kLargeTabImageWidth, kLargeTabImageHeight);
  9252.                     break;
  9253.  
  9254.                 case kLeftTabs:
  9255.                 case kRightTabs:
  9256.                     ::SetPt(&mTabImageSize, kLargeTabImageHeight, kLargeTabImageWidth);
  9257.                     break;
  9258.                 }
  9259.  
  9260.             break;
  9261.         }
  9262.     
  9263.     //
  9264.     // If the bounds are small, we don't draw the frame. We allow some
  9265.     // leeway in layout so that the user doesn't have to make the bounds
  9266.     // exactly match the image size to suppress the frame. This is fine
  9267.     // because if there is a frame, it won't be that small.
  9268.     //
  9269.  
  9270.     mDrawFrame = ((mBounds.bottom - mBounds.top) > (mTabImageSize.v + 16));
  9271.     }
  9272.  
  9273. void AGATabPanel::DisposeTabInfo()
  9274.     {
  9275.     // Release the memory allocated for slider labels.
  9276.  
  9277.     if (mTabInfo != NULL)
  9278.         {
  9279.         for (SInt32 i = 0; i < mNumTabs; i++)
  9280.             ::DisposeHandle((Handle) (*mTabInfo)[i].mLabel);
  9281.  
  9282.         ::DisposeHandle((Handle) mTabInfo);
  9283.         mTabInfo = NULL;
  9284.         }
  9285.  
  9286.     mNumTabs = 0;
  9287.     }
  9288.  
  9289. // Each radio button drawing state has an offscreen image.
  9290. AGAOffscreenImage*    AGATabPanel::mgOffscreenTabImages [kNumTabImages] [kNumImageTypes];
  9291. AGAOffscreenImage*    AGATabPanel::mg1BitOffscreenTabImages [kNumTabImages] [kNumImageTypes];
  9292.  
  9293. // These are the color ramp indexes that are used to build the small tab offscreen images.
  9294. SInt8                AGATabPanel::kSmallTabImageValues [kNumTabImages] [kSmallTabImageHeight] [kSmallTabImageWidth] =
  9295.     {
  9296.         {    // kTabNormalDeselectedL
  9297.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB },
  9298.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB,  r5,  r3 },
  9299.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  r5,  r3,  r2,  r2 },
  9300.         { OUT, OUT, OUT, OUT, OUT, OUT, r12,  r5,  r2,  r2,  r3,  r3 },
  9301.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3 },
  9302.         { OUT, OUT, OUT, OUT, OUT, r12,  r3,  r2,  r3,  r3,  r3,  r3 },
  9303.         { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3 },
  9304. //        { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3 },
  9305.         { OUT, OUT, OUT, OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3 },
  9306.         { OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3 },
  9307. //        { OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3 },
  9308.         { OUT, OUT, OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3 },
  9309.         { OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3 },
  9310. //        { OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3 },
  9311.         { OUT, OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9312.         { OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9313. //        { OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9314.         { OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9315.         { OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9316. //        { OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9317.         { r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9318.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9319.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9320.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9321.         },
  9322.  
  9323.         {    // kTabNormalDeselectedR
  9324.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9325.         {  r3,  r3,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9326.         {  r2,  r2,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9327.         {  r3,  r3,  r3,  r4, r11, r12, OUT, OUT, OUT, OUT, OUT, OUT },
  9328.         {  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9329.         {  r3,  r3,  r3,  r3,  r4,  r9, r12, OUT, OUT, OUT, OUT, OUT },
  9330.         {  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT, OUT, OUT },
  9331. //        {  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT, OUT, OUT, OUT },
  9332.         {  r3,  r3,  r3,  r3,  r3,  r4,  r9, r12, OUT, OUT, OUT, OUT },
  9333.         {  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT, OUT },
  9334. //        {  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT, OUT, OUT },
  9335.         {  r3,  r3,  r3,  r3,  r3,  r3,  r4,  r9, r12, OUT, OUT, OUT },
  9336.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT },
  9337. //        {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT, OUT },
  9338.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r4,  r9, r12, OUT, OUT },
  9339.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT },
  9340. //        {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT },
  9341.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r4,  r9, r12, OUT },
  9342.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT },
  9343. //        {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT },
  9344.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r4,  r9, r12 },
  9345.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9346.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9347.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9348.         },
  9349.  
  9350.         {    // kTabNormalSelectedL
  9351.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB },
  9352.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB,  r4,  r3 },
  9353.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  r4,  r3,  rW,  rW },
  9354.         { OUT, OUT, OUT, OUT, OUT, OUT, r12,  r4,  rW,  rW,  r1,  r1 },
  9355.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1 },
  9356.         { OUT, OUT, OUT, OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1 },
  9357.         { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1 },
  9358. //        { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1 },
  9359.         { OUT, OUT, OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1 },
  9360.         { OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1 },
  9361. //        { OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1 },
  9362.         { OUT, OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1 },
  9363.         { OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1 },
  9364. //        { OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1 },
  9365.         { OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9366.         { OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9367. //        { OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9368.         { OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9369.         { OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9370. //        { OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9371.         { r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9372.         {  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9373.         {  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9374.         {  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9375.         },
  9376.  
  9377.         {    // kTabNormalSelectedR
  9378.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9379.         {  r3,  r4,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9380.         {  rW,  rW,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9381.         {  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT, OUT, OUT, OUT },
  9382.         {  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9383.         {  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT, OUT, OUT },
  9384. //        {  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT, OUT, OUT, OUT },
  9385.         {  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT },
  9386.         {  r1,  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT, OUT },
  9387. //        {  r1,  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT, OUT, OUT },
  9388.         {  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT, OUT },
  9389.         {  r1,  r1,  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT },
  9390. //        {  r1,  r1,  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT, OUT },
  9391.         {  r1,  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT },
  9392.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT },
  9393. //        {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT },
  9394.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT },
  9395.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r3, r11, r12, OUT },
  9396. //        {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT },
  9397.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r7,  rB, OUT },
  9398.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r2, r11,  rB },
  9399.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r7,  rB },
  9400.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r3,  r3 },
  9401.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  rW },
  9402.         },
  9403.  
  9404.         {    // kTabPressedL
  9405.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB },
  9406.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB, r11, r11 },
  9407.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12, r11, r11, r10, r10 },
  9408.         { OUT, OUT, OUT, OUT, OUT, OUT, r12, r11, r10, r10,  r9,  r9 },
  9409.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9 },
  9410.         { OUT, OUT, OUT, OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9 },
  9411.         { OUT, OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9 },
  9412. //        { OUT, OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9 },
  9413.         { OUT, OUT, OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9 },
  9414.         { OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9 },
  9415. //        { OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9 },
  9416.         { OUT, OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9 },
  9417.         { OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9 },
  9418. //        { OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9 },
  9419.         { OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9420.         { OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9421. //        { OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9422.         { OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9423.         { OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9424. //        { OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9425.         { r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9426.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9427.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9428.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9429.         },
  9430.  
  9431.         {    // kTabPressedR
  9432.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9433.         { r11,  r7,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9434.         { r10, r10,  r7,  r8,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9435.         {  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT, OUT, OUT, OUT },
  9436.         {  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9437.         {  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT, OUT, OUT },
  9438.         {  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT, OUT },
  9439. //        {  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT, OUT },
  9440.         {  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT, OUT },
  9441.         {  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT },
  9442. //        {  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT },
  9443.         {  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT },
  9444.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT },
  9445. //        {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT },
  9446.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT },
  9447.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT },
  9448. //        {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT },
  9449.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT },
  9450.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT },
  9451. //        {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT },
  9452.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12 },
  9453.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9454.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9455.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9456.         },
  9457.  
  9458.         {    // kTabDisabledDeselectedL
  9459.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10 },
  9460.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10,  r2,  r2 },
  9461.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2 },
  9462.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9463.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9464.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9465.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9466. //        { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9467.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9468.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9469. //        { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9470.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9471.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9472. //        { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9473.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9474.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9475. //        { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9476.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9477.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9478. //        { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9479.         { r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9480.         { r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10 },
  9481.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9482.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9483.         },
  9484.  
  9485.         {    // kTabDisabledDeselectedR
  9486.         { r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9487.         {  r2,  r2, r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9488.         {  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9489.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9490.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9491.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9492.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9493. //        {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9494.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9495.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9496. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9497.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9498.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9499. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9500.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9501.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9502. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9503.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9504.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9505. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9506.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10 },
  9507.         { r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10 },
  9508.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9509.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9510.         },
  9511.  
  9512.         {    // kTabDisabledSelectedL
  9513.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10 },
  9514.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10,  r2,  r2 },
  9515.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2 },
  9516.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9517.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9518.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9519.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9520. //        { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9521.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9522.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9523. //        { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9524.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9525.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9526. //        { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9527.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9528.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9529. //        { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9530.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9531.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9532. //        { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9533.         { r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9534.         { r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9535.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9536.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9537.         },
  9538.  
  9539.         {    // kTabDisabledSelectedR
  9540.         { r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9541.         {  r2,  r2, r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9542.         {  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9543.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9544.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9545.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9546.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9547. //        {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9548.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9549.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9550. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9551.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9552.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9553. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9554.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9555.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9556. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9557.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9558.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9559. //        {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9560.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10 },
  9561.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10 },
  9562.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9563.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9564.         },
  9565.  
  9566.     };
  9567.  
  9568. // These are the color ramp indexes that are used to build the large tab offscreen images.
  9569. SInt8                AGATabPanel::kLargeTabImageValues [kNumTabImages] [kLargeTabImageHeight] [kLargeTabImageWidth] =
  9570.     {
  9571.         {    // kTabNormalDeselectedL
  9572.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB },
  9573.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB,  r5,  r3 },
  9574.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  r5,  r3,  r2,  r2 },
  9575.         { OUT, OUT, OUT, OUT, OUT, OUT, r12,  r5,  r2,  r2,  r3,  r3 },
  9576.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3 },
  9577.         { OUT, OUT, OUT, OUT, OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3 },
  9578.         { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3 },
  9579.         { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3 },
  9580.         { OUT, OUT, OUT, OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3 },
  9581.         { OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3 },
  9582.         { OUT, OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3 },
  9583.         { OUT, OUT, OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3 },
  9584.         { OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3 },
  9585.         { OUT, OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3 },
  9586.         { OUT, OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9587.         { OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9588.         { OUT, OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9589.         { OUT, r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9590.         { OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9591.         { OUT,  rB,  r3,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9592.         { r12,  r5,  r2,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9593.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9594.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9595.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9596.         },
  9597.  
  9598.         {    // kTabNormalDeselectedR
  9599.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9600.         {  r3,  r3,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9601.         {  r2,  r2,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9602.         {  r3,  r3,  r3,  r4, r11, r12, OUT, OUT, OUT, OUT, OUT, OUT },
  9603.         {  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9604.         {  r3,  r3,  r3,  r3,  r4, r11, r12, OUT, OUT, OUT, OUT, OUT },
  9605.         {  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT, OUT, OUT },
  9606.         {  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT, OUT, OUT, OUT },
  9607.         {  r3,  r3,  r3,  r3,  r3,  r4, r11, r12, OUT, OUT, OUT, OUT },
  9608.         {  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT, OUT },
  9609.         {  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT, OUT, OUT },
  9610.         {  r3,  r3,  r3,  r3,  r3,  r3,  r4, r11, r12, OUT, OUT, OUT },
  9611.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT, OUT },
  9612.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT, OUT },
  9613.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r4, r11, r12, OUT, OUT },
  9614.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT, OUT },
  9615.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT, OUT },
  9616.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r4, r11, r12, OUT },
  9617.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r7,  rB, OUT },
  9618.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r5,  rB, OUT },
  9619.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r4,  r9, r12 },
  9620.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9621.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9622.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9623.         },
  9624.  
  9625.         {    // kTabNormalSelectedL
  9626.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB },
  9627.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB,  r4,  r3 },
  9628.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  r4,  r3,  rW,  rW },
  9629.         { OUT, OUT, OUT, OUT, OUT, OUT, r12,  r4,  r3,  rW,  r1,  r1 },
  9630.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1 },
  9631.         { OUT, OUT, OUT, OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1 },
  9632.         { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1 },
  9633.         { OUT, OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1 },
  9634.         { OUT, OUT, OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1 },
  9635.         { OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1 },
  9636.         { OUT, OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1 },
  9637.         { OUT, OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1 },
  9638.         { OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1 },
  9639.         { OUT, OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1 },
  9640.         { OUT, OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9641.         { OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9642.         { OUT, OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9643.         { OUT, r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9644.         { OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9645.         { OUT,  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9646.         { r12,  r4,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9647.         {  rB,  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9648.         {  r3,  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9649.         {  rW,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1 },
  9650.         },
  9651.  
  9652.         {    // kTabNormalSelectedR
  9653.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9654.         {  r3,  r4,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9655.         {  rW,  rW,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9656.         {  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT, OUT, OUT, OUT },
  9657.         {  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9658.         {  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT, OUT, OUT },
  9659.         {  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT, OUT, OUT, OUT },
  9660.         {  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT, OUT, OUT },
  9661.         {  r1,  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT, OUT },
  9662.         {  r1,  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT, OUT, OUT },
  9663.         {  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT, OUT },
  9664.         {  r1,  r1,  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT, OUT },
  9665.         {  r1,  r1,  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT, OUT },
  9666.         {  r1,  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT, OUT },
  9667.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r4, r11, r12, OUT, OUT },
  9668.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r3,  r7,  rB, OUT, OUT },
  9669.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT, OUT },
  9670.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r3, r11, r12, OUT },
  9671.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r2,  r7,  rB, OUT },
  9672.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r7,  rB, OUT },
  9673.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r2, r11,  rB },
  9674.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r7,  rB },
  9675.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r3,  r3 },
  9676.         {  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  r1,  rW },
  9677.         },
  9678.  
  9679.         {    // kTabPressedL
  9680.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB },
  9681.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12,  rB, r11, r11 },
  9682.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r12, r11, r11, r10, r10 },
  9683.         { OUT, OUT, OUT, OUT, OUT, OUT, r12, r11, r11, r10,  r9,  r9 },
  9684.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9 },
  9685.         { OUT, OUT, OUT, OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9 },
  9686.         { OUT, OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9 },
  9687.         { OUT, OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9 },
  9688.         { OUT, OUT, OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9 },
  9689.         { OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9 },
  9690.         { OUT, OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9 },
  9691.         { OUT, OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9 },
  9692.         { OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9 },
  9693.         { OUT, OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9 },
  9694.         { OUT, OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9695.         { OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9696.         { OUT, OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9697.         { OUT, r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9698.         { OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9699.         { OUT,  rB, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9700.         { r12, r11, r10,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9 },
  9701.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9702.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9703.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9704.         },
  9705.  
  9706.         {    // kTabPressedR
  9707.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9708.         { r11,  r7,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9709.         { r10, r10,  r7,  r8,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9710.         {  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT, OUT, OUT, OUT },
  9711.         {  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9712.         {  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT, OUT, OUT },
  9713.         {  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT, OUT },
  9714.         {  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT, OUT },
  9715.         {  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT, OUT },
  9716.         {  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT },
  9717.         {  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT, OUT },
  9718.         {  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT, OUT },
  9719.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT },
  9720.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT, OUT },
  9721.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT, OUT },
  9722.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT },
  9723.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT, OUT },
  9724.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12, OUT },
  9725.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT },
  9726.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r8,  rB, OUT },
  9727.         {  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r9,  r7, r11, r12 },
  9728.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9729.         {  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3,  r3 },
  9730.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9731.         },
  9732.  
  9733.         {    // kTabDisabledDeselectedL
  9734.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10 },
  9735.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10,  r2,  r2 },
  9736.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2 },
  9737.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9738.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9739.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9740.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9741.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9742.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9743.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9744.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9745.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9746.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9747.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9748.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9749.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9750.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9751.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9752.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9753.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9754.         { r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9755.         { r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10 },
  9756.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9757.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9758.         },
  9759.  
  9760.         {    // kTabDisabledDeselectedR
  9761.         { r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9762.         {  r2,  r2, r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9763.         {  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9764.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9765.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9766.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9767.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9768.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9769.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9770.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9771.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9772.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9773.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9774.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9775.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9776.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9777.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9778.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9779.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9780.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9781.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10 },
  9782.         { r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10, r10 },
  9783.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9784.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9785.         },
  9786.  
  9787.         {    // kTabDisabledSelectedL
  9788.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10 },
  9789.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10, r10,  r2,  r2 },
  9790.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2 },
  9791.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9792.         { OUT, OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2 },
  9793.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9794.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9795.         { OUT, OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2 },
  9796.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9797.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9798.         { OUT, OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9799.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9800.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9801.         { OUT, OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9802.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9803.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9804.         { OUT, OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9805.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9806.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9807.         { OUT, r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9808.         { r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9809.         { r10,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9810.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9811.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9812.         },
  9813.  
  9814.         {    // kTabDisabledSelectedR
  9815.         { r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9816.         {  r2,  r2, r10, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9817.         {  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9818.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9819.         {  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT, OUT },
  9820.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9821.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9822.         {  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT, OUT },
  9823.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9824.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9825.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT, OUT },
  9826.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9827.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9828.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT, OUT },
  9829.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9830.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9831.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT, OUT },
  9832.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9833.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9834.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10, OUT },
  9835.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10 },
  9836.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2, r10 },
  9837.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9838.         {  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2,  r2 },
  9839.         },
  9840.  
  9841.     };
  9842.  
  9843. // These are the color ramp indexes that are used to build the small 1-bit tab offscreen images.
  9844. SInt8                AGATabPanel::k1BitSmallTabImageValues [kNumTabImages] [kSmallTabImageHeight] [kSmallTabImageWidth] =
  9845.     {
  9846.         {    // kTabNormalDeselectedL
  9847.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  9848.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  9849.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  9850.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  9851.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  9852.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  9853.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  9854. //        { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  9855.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9856.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9857. //        { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9858.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9859.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9860. //        { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9861.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9862.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9863. //        { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9864.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9865.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9866. //        { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9867.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9868.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9869.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9870.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9871.         },
  9872.  
  9873.         {    // kTabNormalDeselectedR
  9874.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9875.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9876.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9877.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9878.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9879.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  9880.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  9881. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  9882.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  9883.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  9884. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  9885.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  9886.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  9887. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  9888.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  9889.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  9890. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  9891.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  9892.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  9893. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  9894.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  9895.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9896.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9897.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9898.         },
  9899.  
  9900.         {    // kTabNormalSelectedL
  9901.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  9902.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  9903.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  9904.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  9905.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  9906.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  9907.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  9908. //        { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  9909.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9910.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9911. //        { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9912.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9913.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9914. //        { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9915.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9916.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9917. //        { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9918.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9919.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9920. //        { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9921.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9922.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9923.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9924.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9925.         },
  9926.  
  9927.         {    // kTabNormalSelectedR
  9928.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9929.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9930.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9931.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9932.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9933.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  9934.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  9935. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  9936.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  9937.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  9938. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  9939.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  9940.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  9941. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  9942.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  9943.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  9944. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  9945.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  9946.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  9947. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  9948.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  9949.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  9950.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9951.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9952.         },
  9953.  
  9954.         {    // kTabPressedL
  9955.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  9956.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB },
  9957.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB },
  9958.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB },
  9959.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB },
  9960.         { OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9961.         { OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9962. //        { OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9963.         { OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9964.         { OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9965. //        { OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9966.         { OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9967.         { OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9968. //        { OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9969.         { OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9970.         { OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9971. //        { OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9972.         { OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9973.         { OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9974. //        { OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9975.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9976.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  9977.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9978.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  9979.         },
  9980.  
  9981.         {    // kTabPressedR
  9982.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9983.         {  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9984.         {  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  9985.         {  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9986.         {  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  9987.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT },
  9988.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT },
  9989. //        {  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT },
  9990.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT },
  9991.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT },
  9992. //        {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT },
  9993.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT },
  9994.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT },
  9995. //        {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT },
  9996.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT },
  9997.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT },
  9998. //        {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT },
  9999.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT },
  10000.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT },
  10001. //        {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT },
  10002.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10003.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10004.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10005.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10006.         },
  10007.  
  10008.         {    // kTabDisabledDeselectedL
  10009.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  10010.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  10011.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  10012.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10013.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10014.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10015.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10016. //        { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10017.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10018.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10019. //        { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10020.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10021.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10022. //        { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10023.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10024.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10025. //        { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10026.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10027.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10028. //        { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10029.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10030.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10031.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10032.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10033.         },
  10034.  
  10035.         {    // kTabDisabledDeselectedR
  10036.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10037.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10038.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10039.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10040.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10041.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10042.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10043. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10044.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10045.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10046. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10047.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10048.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10049. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10050.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10051.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10052. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10053.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10054.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10055. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10056.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10057.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10058.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10059.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10060.         },
  10061.  
  10062.         {    // kTabDisabledSelectedL
  10063.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  10064.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  10065.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  10066.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10067.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10068.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10069.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10070. //        { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10071.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10072.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10073. //        { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10074.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10075.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10076. //        { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10077.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10078.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10079. //        { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10080.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10081.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10082. //        { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10083.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10084.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10085.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10086.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10087.         },
  10088.  
  10089.         {    // kTabDisabledSelectedR
  10090.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10091.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10092.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10093.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10094.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10095.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10096.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10097. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10098.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10099.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10100. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10101.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10102.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10103. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10104.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10105.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10106. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10107.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10108.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10109. //        {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10110.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10111.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10112.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10113.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10114.         },
  10115.  
  10116.     };
  10117.  
  10118. // These are the color ramp indexes that are used to build the large 1-bit tab offscreen images.
  10119. SInt8                AGATabPanel::k1BitLargeTabImageValues [kNumTabImages] [kLargeTabImageHeight] [kLargeTabImageWidth] =
  10120.     {
  10121.         {    // kTabNormalDeselectedL
  10122.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  10123.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  10124.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  10125.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10126.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10127.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10128.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10129.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10130.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10131.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10132.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10133.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10134.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10135.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10136.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10137.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10138.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10139.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10140.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10141.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10142.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10143.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10144.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10145.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10146.         },
  10147.  
  10148.         {    // kTabNormalDeselectedR
  10149.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10150.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10151.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10152.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10153.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10154.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10155.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10156.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10157.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10158.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10159.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10160.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10161.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10162.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10163.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10164.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10165.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10166.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10167.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10168.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10169.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10170.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10171.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10172.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10173.         },
  10174.  
  10175.         {    // kTabNormalSelectedL
  10176.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  10177.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  10178.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  10179.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10180.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10181.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10182.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10183.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10184.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10185.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10186.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10187.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10188.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10189.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10190.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10191.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10192.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10193.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10194.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10195.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10196.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10197.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10198.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10199.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10200.         },
  10201.  
  10202.         {    // kTabNormalSelectedR
  10203.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10204.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10205.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10206.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10207.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10208.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10209.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10210.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10211.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10212.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10213.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10214.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10215.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10216.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10217.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10218.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10219.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10220.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10221.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10222.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10223.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10224.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10225.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10226.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10227.         },
  10228.  
  10229.         {    // kTabPressedL
  10230.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  10231.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB },
  10232.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB },
  10233.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB },
  10234.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB },
  10235.         { OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10236.         { OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10237.         { OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10238.         { OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10239.         { OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10240.         { OUT, OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10241.         { OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10242.         { OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10243.         { OUT, OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10244.         { OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10245.         { OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10246.         { OUT, OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10247.         { OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10248.         { OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10249.         { OUT,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10250.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10251.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10252.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10253.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10254.         },
  10255.  
  10256.         {    // kTabPressedR
  10257.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10258.         {  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10259.         {  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10260.         {  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10261.         {  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10262.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT },
  10263.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT },
  10264.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT, OUT },
  10265.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT },
  10266.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT },
  10267.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT, OUT },
  10268.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT },
  10269.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT },
  10270.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT, OUT },
  10271.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT },
  10272.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT },
  10273.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT, OUT },
  10274.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT },
  10275.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT },
  10276.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB, OUT },
  10277.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10278.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10279.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10280.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10281.         },
  10282.  
  10283.         {    // kTabDisabledDeselectedL
  10284.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  10285.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  10286.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  10287.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10288.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10289.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10290.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10291.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10292.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10293.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10294.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10295.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10296.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10297.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10298.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10299.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10300.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10301.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10302.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10303.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10304.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10305.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10306.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10307.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10308.         },
  10309.  
  10310.         {    // kTabDisabledDeselectedR
  10311.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10312.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10313.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10314.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10315.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10316.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10317.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10318.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10319.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10320.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10321.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10322.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10323.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10324.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10325.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10326.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10327.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10328.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10329.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10330.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10331.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10332.         {  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB,  rB },
  10333.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10334.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10335.         },
  10336.  
  10337.         {    // kTabDisabledSelectedL
  10338.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB },
  10339.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rB,  rW,  rW },
  10340.         { OUT, OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW },
  10341.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10342.         { OUT, OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW },
  10343.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10344.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10345.         { OUT, OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW },
  10346.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10347.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10348.         { OUT, OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10349.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10350.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10351.         { OUT, OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10352.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10353.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10354.         { OUT, OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10355.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10356.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10357.         { OUT,  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10358.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10359.         {  rB,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10360.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10361.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10362.         },
  10363.  
  10364.         {    // kTabDisabledSelectedR
  10365.         {  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10366.         {  rW,  rW,  rB,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10367.         {  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT, OUT },
  10368.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10369.         {  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT, OUT },
  10370.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10371.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10372.         {  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT, OUT },
  10373.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10374.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10375.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT, OUT },
  10376.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10377.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10378.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT, OUT },
  10379.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10380.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10381.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT, OUT },
  10382.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10383.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10384.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB, OUT },
  10385.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10386.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rB },
  10387.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10388.         {  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW,  rW },
  10389.         },
  10390.  
  10391.     };
  10392.  
  10393. OSErr AGATabPanel::AllocateTabImages()
  10394.     {
  10395.     // Allocate the offscreen images for the various sizes & states.
  10396.  
  10397.     OSErr    result = noErr;
  10398.     Point    imageSize;
  10399.     
  10400.     if (result == noErr)
  10401.         {
  10402.         SetPt(&imageSize, kLargeTabImageWidth, kLargeTabImageHeight);
  10403.  
  10404.         for (UInt32 imageIndex = 0; (imageIndex < kNumTabImages) && (result == noErr); imageIndex++)
  10405.             {
  10406.             mgOffscreenTabImages [imageIndex] [kLargeTabImages] = new AGAOffscreenImage;
  10407.         
  10408.             result = mgOffscreenTabImages [imageIndex] [kLargeTabImages] ->CreateImageData(
  10409.                         imageSize,
  10410.                         &kLargeTabImageValues[imageIndex][0][0],
  10411.                         NULL, 
  10412.                         &gAGARamp[r2]);
  10413.             }
  10414.         }
  10415.         
  10416.     if (result == noErr)
  10417.         {
  10418.         SetPt(&imageSize, kSmallTabImageWidth, kSmallTabImageHeight);
  10419.  
  10420.         for (UInt32 imageIndex = 0; (imageIndex < kNumTabImages) && (result == noErr); imageIndex++)
  10421.             {
  10422.             mgOffscreenTabImages [imageIndex] [kSmallTabImages] = new AGAOffscreenImage;
  10423.         
  10424.             result = mgOffscreenTabImages [imageIndex] [kSmallTabImages] ->CreateImageData(
  10425.                         imageSize,
  10426.                         &kSmallTabImageValues[imageIndex][0][0],
  10427.                         NULL, 
  10428.                         &gAGARamp[r2]);
  10429.             }
  10430.         }
  10431.         
  10432.     if (result == noErr)
  10433.         {
  10434.         SetPt(&imageSize, kLargeTabImageWidth, kLargeTabImageHeight);
  10435.  
  10436.         for (UInt32 imageIndex = 0; (imageIndex < kNumTabImages) && (result == noErr); imageIndex++)
  10437.             {
  10438.             mg1BitOffscreenTabImages [imageIndex] [kLargeTabImages] = new AGAOffscreenImage;
  10439.         
  10440.             result = mg1BitOffscreenTabImages [imageIndex] [kLargeTabImages] ->CreateImageData(
  10441.                         imageSize,
  10442.                         &k1BitLargeTabImageValues[imageIndex][0][0],
  10443.                         NULL, 
  10444.                         &gAGARamp[r2]);
  10445.             }
  10446.         }
  10447.         
  10448.     if (result == noErr)
  10449.         {
  10450.         SetPt(&imageSize, kSmallTabImageWidth, kSmallTabImageHeight);
  10451.  
  10452.         for (UInt32 imageIndex = 0; (imageIndex < kNumTabImages) && (result == noErr); imageIndex++)
  10453.             {
  10454.             mg1BitOffscreenTabImages [imageIndex] [kSmallTabImages] = new AGAOffscreenImage;
  10455.         
  10456.             result = mg1BitOffscreenTabImages [imageIndex] [kSmallTabImages] ->CreateImageData(
  10457.                         imageSize,
  10458.                         &k1BitSmallTabImageValues[imageIndex][0][0],
  10459.                         NULL, 
  10460.                         &gAGARamp[r2]);
  10461.             }
  10462.         }
  10463.         
  10464.     return result;
  10465.     }
  10466.  
  10467. void AGATabPanel::CopyTabImage(UInt32 imageIndex, Point imageDestination, Boolean deep)
  10468.     {
  10469.     // Blast the specified offscreen image into the radio button's button area.
  10470.  
  10471.     if (deep)
  10472.         mgOffscreenTabImages [imageIndex] [(mTabSize == kSmallTabs) ? kSmallTabImages : kLargeTabImages]->DrawImage(imageDestination.h, imageDestination.v);
  10473.     else
  10474.         mg1BitOffscreenTabImages [imageIndex] [(mTabSize == kSmallTabs) ? kSmallTabImages : kLargeTabImages]->DrawImage(imageDestination.h, imageDestination.v);
  10475.     }
  10476.  
  10477. void AGATabPanel::DisposeTabImages()
  10478.     {
  10479.     for (UInt32 imageIndex = 0; imageIndex < kNumTabImages; imageIndex++)
  10480.         if (mgOffscreenTabImages [imageIndex] [kLargeTabImages] != NULL)
  10481.             delete mgOffscreenTabImages [imageIndex] [kLargeTabImages];
  10482.  
  10483.     for (UInt32 imageIndex = 0; imageIndex < kNumTabImages; imageIndex++)
  10484.         if (mgOffscreenTabImages [imageIndex] [kSmallTabImages] != NULL)
  10485.             delete mgOffscreenTabImages [imageIndex] [kSmallTabImages];
  10486.  
  10487.     for (UInt32 imageIndex = 0; imageIndex < kNumTabImages; imageIndex++)
  10488.         if (mg1BitOffscreenTabImages [imageIndex] [kLargeTabImages] != NULL)
  10489.             delete mg1BitOffscreenTabImages [imageIndex] [kLargeTabImages];
  10490.  
  10491.     for (UInt32 imageIndex = 0; imageIndex < kNumTabImages; imageIndex++)
  10492.         if (mg1BitOffscreenTabImages [imageIndex] [kSmallTabImages] != NULL)
  10493.             delete mg1BitOffscreenTabImages [imageIndex] [kSmallTabImages];
  10494.     }
  10495.  
  10496. //
  10497. // AGAStringOut --------------------------------------------------------
  10498. //
  10499. // This is the routine we use for all of our one-line text output.
  10500. //
  10501.  
  10502. void AGAStringOut(StringPtr aString,
  10503.                     Rect* centeringFrame,
  10504.                     SInt32 truncation,
  10505.                     SInt32 justification,
  10506.                     AGAStringOutColor outColor,
  10507.                     Boolean deep,
  10508.                     const AGATextStyle& textStyle)
  10509.     {
  10510.     Str255        outputString;
  10511.     FontInfo    fontInfo;
  10512.     SInt16        frameWidth = centeringFrame->right - centeringFrame->left;
  10513.     SInt16        frameHeight = centeringFrame->bottom - centeringFrame->top;
  10514.     Point        penOrigin;
  10515.     Boolean        setColor = true;
  10516.     UInt8        colorIndex;
  10517.     
  10518.     textStyle.PrepareForDrawing();
  10519.     ::GetFontInfo(&fontInfo);
  10520.  
  10521.     switch (outColor)
  10522.         {
  10523.         case kNormalOutput:
  10524.             colorIndex = rB;
  10525.             break;
  10526.         case kDisabledOutput:
  10527.             if (deep)
  10528.                 colorIndex = r7;
  10529.             else
  10530.                 colorIndex = rB;
  10531.             break;
  10532.         case kInverseOutput:
  10533.             colorIndex = rW;
  10534.             break;
  10535.         case kUseCurrentColor:
  10536.             setColor = false;
  10537.             break;
  10538.         }
  10539.  
  10540.     if (setColor)
  10541.         ::RGBForeColor(&gAGARamp[colorIndex]);
  10542.     
  10543.     AGA_PLstrcpy(outputString, aString);
  10544.     
  10545.     // Truncate the string if it does not fit the width of the frame.
  10546.     if (truncation != kNoTruncation)
  10547.         {
  10548.         // If the string would be truncated at the current
  10549.         // font settings, try again with condensed text.
  10550.         if (::TruncString(frameWidth, outputString, truncation) == truncated)
  10551.             {
  10552.             AGA_PLstrcpy(outputString, aString);
  10553.             ::TextFace(condense);
  10554.             (void) ::TruncString(frameWidth, outputString, truncation);
  10555.             }
  10556.         }
  10557.     
  10558.     // Center the text vertically. Pen goes at baseline of
  10559.     // text, i.e. between the ascent and descent.
  10560.     penOrigin.v = centeringFrame->top + (frameHeight / 2) + ((fontInfo.ascent + fontInfo.descent) / 2) - fontInfo.descent;
  10561.     
  10562.     // Position the text horizontally left, centered, or right, based
  10563.     // on the specified justification and the system script direction.
  10564.     switch (RuntimeJustify(justification))
  10565.         {
  10566.         case teCenter:
  10567.             penOrigin.h = centeringFrame->left + (frameWidth / 2) - (::StringWidth(outputString) / 2);
  10568.             break;
  10569.         case teFlushRight:
  10570.             penOrigin.h = centeringFrame->right - ::StringWidth(outputString);
  10571.             break;
  10572.         default: //case teFlushLeft:
  10573.             penOrigin.h = centeringFrame->left;
  10574.             break;
  10575.         }
  10576.  
  10577.     ::MoveTo(penOrigin.h, penOrigin.v);
  10578.  
  10579.     GrafPtr    currentPort;
  10580.     ::GetPort(¤tPort);
  10581.     SInt16    savedTxMode = currentPort->txMode;
  10582.     ::TextMode(srcOr);
  10583.     ::DrawString(outputString);
  10584.     ::TextMode(savedTxMode);
  10585.     
  10586.     if ((outColor == kDisabledOutput) && ! deep)
  10587.         {
  10588.         ::PenPat(&qd.gray);
  10589.         ::PenMode(patBic);
  10590.         ::PaintRect(centeringFrame);
  10591.  
  10592.         ::PenNormal();
  10593.         }
  10594.     }
  10595.  
  10596. //
  10597. // AGATextBox --------------------------------------------------------
  10598. //
  10599. // This is a replacement for TETextBox.
  10600. //
  10601.  
  10602. void AGATextBox(const void *textPtr,
  10603.                 SInt32 textLength,
  10604.                 const Rect *textFrame,
  10605.                 SInt16 justification,
  10606.                 AGAStringOutColor outColor,
  10607.                 Boolean deep,
  10608.                 const AGATextStyle& textStyle,
  10609.                 const RGBColor* teBackgroundColor)
  10610.     {
  10611.     FontInfo    fontInfo;
  10612.     Boolean        setColor = true;
  10613.     UInt8        colorIndex;
  10614.     RGBColor    savedBackColor;
  10615.     
  10616.     ::GetBackColor(&savedBackColor);
  10617.     ::RGBBackColor(teBackgroundColor);
  10618.     
  10619.     textStyle.PrepareForDrawing();
  10620.     ::GetFontInfo(&fontInfo);
  10621.  
  10622.     switch (outColor)
  10623.         {
  10624.         case kNormalOutput:
  10625.             colorIndex = rB;
  10626.             break;
  10627.         case kDisabledOutput:
  10628.             if (deep)
  10629.                 colorIndex = r7;
  10630.             else
  10631.                 colorIndex = rB;
  10632.             break;
  10633.         case kInverseOutput:
  10634.             colorIndex = rW;
  10635.             break;
  10636.         case kUseCurrentColor:
  10637.             setColor = false;
  10638.             break;
  10639.         }
  10640.  
  10641.     if (setColor)
  10642.         ::RGBForeColor(&gAGARamp[colorIndex]);
  10643.     
  10644.     ::TETextBox(textPtr, textLength, textFrame, justification);
  10645.  
  10646.     if ((outColor == kDisabledOutput) && ! deep)
  10647.         {
  10648.         ::PenPat(&qd.gray);
  10649.         ::PenMode(patBic);
  10650.         ::PaintRect(textFrame);
  10651.  
  10652.         ::PenNormal();
  10653.         }
  10654.  
  10655.     ::RGBBackColor(&savedBackColor);
  10656.     }
  10657.  
  10658. //
  10659. // GDIterator -----------------------------------------------------
  10660. //
  10661.  
  10662. RgnHandle GDIterator::mSavedClipping = ::NewRgn();
  10663.  
  10664. GDIterator::GDIterator()
  10665.     {
  10666.     this->Setup();
  10667.     }
  10668.  
  10669. GDIterator::~GDIterator()
  10670.     {
  10671.     this->Cleanup();
  10672.     }
  10673.  
  10674. void GDIterator::Setup()
  10675.     {
  10676.     // Save the current clipping so we can put it back in Cleanup
  10677.     // and use it as we iterate over each device.
  10678.  
  10679.     ::GetClip(mSavedClipping);
  10680.     
  10681.     mIteratedYet = false;
  10682.     mCurrentGDHandle = NULL;
  10683.     }
  10684.  
  10685. Boolean GDIterator::More(Boolean& deep)
  10686.     {
  10687.     // If there's another device to draw on, get its GDHandle and deepness,
  10688.     // and return true. Otherwise, return false.
  10689.  
  10690.     if (gAGAHasColorQD)
  10691.         {
  10692.         mCurrentGDHandle = this->FindNextValidDevice(mCurrentGDHandle, deep);
  10693.         return (mCurrentGDHandle != NULL);
  10694.         }
  10695.     else
  10696.         {
  10697.         deep = false;
  10698.         return ! mIteratedYet;
  10699.         }
  10700.     }
  10701.  
  10702. void GDIterator::Cleanup()
  10703.     {
  10704.     // Restore clipping to what it was when we were constructed.
  10705.  
  10706.     ::SetClip(mSavedClipping);
  10707.     }
  10708.  
  10709. void GDIterator::ClipFurtherToCurrentDevice()
  10710.     {
  10711.     // Clip further to prevent drawing outside the current device.
  10712.  
  10713.     this->ClipFurtherToDevice(mCurrentGDHandle);
  10714.     }
  10715.  
  10716. GDHandle GDIterator::FindNextValidDevice(GDHandle currentDevice, Boolean& deep)
  10717.     {
  10718.     // Return the GDHandle of the next valid device, if any, and indicate
  10719.     // whether it is "deep".
  10720.     // As a designed side-effect, when we find a next device, we restore
  10721.     // the original clipping and then re-clip further to this next device
  10722.     // so no drawing occurs on other devices.
  10723.  
  10724.     GDHandle    deviceToTest;
  10725.     GDHandle    deviceFound = NULL;
  10726.     
  10727.     deep = false;
  10728.     
  10729.     if (currentDevice == NULL)
  10730.         deviceToTest = ::GetDeviceList();
  10731.     else
  10732.         deviceToTest = ::GetNextDevice(currentDevice);
  10733.  
  10734.     while ((deviceToTest != NULL) && (deviceFound == NULL))
  10735.         {
  10736.         Boolean    isValidDevice = false;
  10737.         
  10738.         if (::TestDeviceAttribute(deviceToTest, screenDevice))
  10739.             if (::TestDeviceAttribute(deviceToTest, screenActive))
  10740.                 {
  10741.                 isValidDevice = true;
  10742.                 
  10743.                 SInt16    pixelDepth = (**((**deviceToTest).gdPMap)).pixelSize;
  10744.                 Boolean    isColor = ::TestDeviceAttribute(deviceToTest, gdDevType);
  10745.                 
  10746.                 deep = (pixelDepth >= kDeepColorBits) || ((pixelDepth >= kDeepGrayscaleBits) && ! isColor);
  10747.                 
  10748.                 deviceFound = deviceToTest;
  10749.                 }
  10750.  
  10751.         if (! isValidDevice)
  10752.             deviceToTest = ::GetNextDevice(deviceToTest);
  10753.         }
  10754.     
  10755.     if (deviceFound != NULL)
  10756.         {
  10757.         ::SetClip(mSavedClipping);
  10758.         this->ClipFurtherToDevice(deviceFound);
  10759.         }
  10760.  
  10761.     return deviceFound;
  10762.     }
  10763.  
  10764. void GDIterator::ClipFurtherToDevice(GDHandle aDevice)
  10765.     {
  10766.     // Clip further to the specified device so no drawing will occur
  10767.     // on other devices.
  10768.  
  10769.     if (aDevice != NULL)
  10770.         {
  10771.         Rect    deviceRect = (**aDevice).gdRect;
  10772.         Point    drTopLeft;
  10773.         Point    drBotRight;
  10774.         
  10775.         ::SetPt(&drTopLeft, deviceRect.left, deviceRect.top);
  10776.         ::SetPt(&drBotRight, deviceRect.right, deviceRect.bottom);
  10777.         
  10778.         ::GlobalToLocal(&drTopLeft);
  10779.         ::GlobalToLocal(&drBotRight);
  10780.         
  10781.         ::SetRect(&deviceRect, drTopLeft.h, drTopLeft.v, drBotRight.h, drBotRight.v);
  10782.         
  10783.         AGAClipFurther(&deviceRect);
  10784.         }
  10785.     }
  10786.  
  10787. //
  10788. // AGABackgroundPaint ------------------------------------------------
  10789. //
  10790.  
  10791. void AGABackgroundPaint(const Rect* backgroundBounds,
  10792.                         Boolean drawFill,
  10793.                         AGABackgroundKind backgroundKind,
  10794.                         Boolean isActive,
  10795.                         Boolean hasGrowBox)
  10796.     {
  10797.     if (backgroundKind == kNoBackgroundPaint)
  10798.         return;
  10799.  
  10800.     AGADrawingEnvironment    env;
  10801.  
  10802.     // Draw in the specified active/inactive state.
  10803.  
  10804.     enum { kBGFill, kBGActiveLight, kBGActiveShadow, kBGActiveCorner, kBGInactiveLight, kBGInactiveShadow, kBGInactiveCorner, kBGNumIndexes };
  10805.  
  10806.     UInt8    colorIndexes[kBGNumIndexes];
  10807.  
  10808.     switch (backgroundKind)
  10809.         {
  10810.         case kRaisedModelessBackground:
  10811.             colorIndexes[kBGFill] = r2;
  10812.             colorIndexes[kBGActiveLight] = rW;
  10813.             colorIndexes[kBGActiveShadow] = r6;
  10814.             colorIndexes[kBGActiveCorner] = r2;
  10815.             colorIndexes[kBGInactiveLight] = r2;
  10816.             colorIndexes[kBGInactiveShadow] = r2;
  10817.             colorIndexes[kBGInactiveCorner] = r2;
  10818.             break;
  10819.  
  10820.         case kRaisedModalBackground:
  10821.             colorIndexes[kBGFill] = r2;
  10822.             colorIndexes[kBGActiveLight] = rW;
  10823.             colorIndexes[kBGActiveShadow] = r6;
  10824.             colorIndexes[kBGActiveCorner] = r4;
  10825.             colorIndexes[kBGInactiveLight] = r2;
  10826.             colorIndexes[kBGInactiveShadow] = r2;
  10827.             colorIndexes[kBGInactiveCorner] = r2;
  10828.             break;
  10829.  
  10830.         case kFlatWindowBackground:
  10831.             colorIndexes[kBGFill] = r2;
  10832.             colorIndexes[kBGActiveLight] = r2;
  10833.             colorIndexes[kBGActiveShadow] = r2;
  10834.             colorIndexes[kBGActiveCorner] = r2;
  10835.             colorIndexes[kBGInactiveLight] = r2;
  10836.             colorIndexes[kBGInactiveShadow] = r2;
  10837.             colorIndexes[kBGInactiveCorner] = r2;
  10838.             break;
  10839.         }
  10840.  
  10841.     GDIterator    iter;
  10842.     Boolean        deep;
  10843.  
  10844.     while (iter.More(deep))
  10845.         {
  10846.         Rect    r = *backgroundBounds;
  10847.  
  10848.         if (deep)
  10849.             {
  10850.             ::InsetRect(&r, 1, 1);
  10851.             
  10852.             if (drawFill)
  10853.                 {
  10854.                 ::RGBForeColor(&gAGARamp[colorIndexes[kBGFill]]);
  10855.             
  10856.                 ::PaintRect(&r);
  10857.                 }
  10858.             
  10859.             if (isActive)
  10860.                 ::RGBForeColor(&gAGARamp[colorIndexes[kBGActiveCorner]]);
  10861.             else
  10862.                 ::RGBForeColor(&gAGARamp[colorIndexes[kBGInactiveCorner]]);
  10863.  
  10864.             ::MoveTo(r.left - 1, r.bottom);
  10865.             ::Line(0, 0);
  10866.             ::MoveTo(r.right, r.top - 1);
  10867.             ::Line(0, 0);
  10868.             
  10869.             if (isActive)
  10870.                 ::RGBForeColor(&gAGARamp[colorIndexes[kBGActiveLight]]);
  10871.             else
  10872.                 ::RGBForeColor(&gAGARamp[colorIndexes[kBGInactiveLight]]);
  10873.  
  10874.             ::MoveTo(r.left - 1, r.bottom - 1);
  10875.             ::LineTo(r.left - 1, r.top - 1);
  10876.             ::LineTo(r.right - 1, r.top - 1);
  10877.             
  10878.             if (isActive)
  10879.                 ::RGBForeColor(&gAGARamp[colorIndexes[kBGActiveShadow]]);
  10880.             else
  10881.                 ::RGBForeColor(&gAGARamp[colorIndexes[kBGInactiveShadow]]);
  10882.  
  10883.             ::MoveTo(r.left, r.bottom);
  10884.             
  10885.             if (hasGrowBox)
  10886.                 {
  10887.                 ::LineTo(r.right - 15, r.bottom);
  10888.                 ::Line(0, -15);
  10889.                 ::Line(15, 0);
  10890.                 }
  10891.             else
  10892.                 ::LineTo(r.right, r.bottom);
  10893.  
  10894.             ::LineTo(r.right, r.top);
  10895.             }
  10896.         else    // 1-bit
  10897.             {
  10898.             if (drawFill)
  10899.                 {
  10900.                 ::RGBBackColor(&gAGARamp[rW]);
  10901.                 ::EraseRect(&r);
  10902.                 }
  10903.             }
  10904.         }
  10905.     }
  10906.  
  10907. //
  10908. // AGAInstallGrayWCTB ------------------------------------------------
  10909. //
  10910.  
  10911. OSErr AGAInstallGrayWCTB(WindowPtr aWindow)
  10912.     {
  10913.     //
  10914.     // If it's a color window, make a copy of the default
  10915.     // color table, set the background to r2, and install
  10916.     // it into the window.
  10917.     //
  10918.  
  10919.     OSErr            err = noErr;
  10920.     AuxWinHandle    auxWinHandle;
  10921.     CTabHandle        colorTableHandle;
  10922.  
  10923.     ::GetAuxWin(NULL, &auxWinHandle);
  10924.  
  10925.     if (auxWinHandle != NULL)
  10926.         {
  10927.         colorTableHandle = (**auxWinHandle).awCTable;
  10928.         
  10929.         err = ::HandToHand((Handle*) &colorTableHandle);
  10930.  
  10931.         if (err == noErr)
  10932.             {
  10933.             (**colorTableHandle).ctTable->rgb = gAGARamp[r2];    
  10934.             ::SetWinColor(aWindow, (WCTabHandle) colorTableHandle);
  10935.             }
  10936.         }
  10937.     
  10938.     return err;
  10939.     }
  10940.  
  10941. //
  10942. // AGADrawBorderFrame ------------------------------------------------
  10943. //
  10944.  
  10945. void AGADrawBorderFrame(const Rect* bounds, Boolean isEnabled, Boolean isNotched, Boolean drawFrame, const RGBColor* windowBackgroundColor)
  10946.     {
  10947.     // Draw the frame with shading outside.
  10948.     
  10949.     enum { Shadow, Frame, Light, kNumColors };
  10950.  
  10951.     Rect    r = *bounds;
  10952.     
  10953.     GDIterator    iter;
  10954.     Boolean        deep;
  10955.  
  10956.     while (iter.More(deep))
  10957.         {
  10958.         AGADrawingEnvironment    env;
  10959.  
  10960.         if (drawFrame)
  10961.             {
  10962.             if (deep)
  10963.                 {
  10964.                 if (isEnabled)
  10965.                     ::RGBForeColor(&gAGARamp[rB]);
  10966.                 else
  10967.                     ::RGBForeColor(&gAGARamp[r10]);
  10968.                 }
  10969.             else
  10970.                 {
  10971.                 ::RGBForeColor(&gAGARamp[rB]);
  10972.  
  10973.                 if (isEnabled)
  10974.                     ::PenPat(&qd.black);
  10975.                 else
  10976.                     ::PenPat(&qd.gray);
  10977.                 }
  10978.  
  10979.             ::InsetRect(&r, 1, 1);
  10980.             
  10981.             if (isNotched)
  10982.                 {
  10983.                 ::MoveTo(r.right - 1, r.top);
  10984.                 ::LineTo(r.left, r.top);
  10985.                 ::LineTo(r.left, r.bottom - 1);
  10986.                 ::LineTo(r.right - 16, r.bottom - 1);
  10987.                 ::Line(0, -15);
  10988.                 ::Line(15, 0);
  10989.                 ::LineTo(r.right - 1, r.top);
  10990.                 }
  10991.             else
  10992.                 ::FrameRect(&r);
  10993.  
  10994.             ::InsetRect(&r, -1, -1);
  10995.             }
  10996.         
  10997.         if (deep)
  10998.             {
  10999.             if (isEnabled)
  11000.                 ::RGBForeColor(&gAGARamp[r5]);
  11001.             else
  11002.                 ::RGBForeColor(windowBackgroundColor);
  11003.  
  11004.             ::MoveTo(r.left, r.bottom - 2);
  11005.             ::LineTo(r.left, r.top);
  11006.             ::LineTo(r.right - 2, r.top);
  11007.             
  11008.             if (isEnabled)
  11009.                 ::RGBForeColor(&gAGARamp[rW]);
  11010.             else
  11011.                 ::RGBForeColor(windowBackgroundColor);
  11012.  
  11013.             ::MoveTo(r.left + 1, r.bottom - 1);
  11014.  
  11015.             if (isNotched)
  11016.                 {
  11017.                 ::LineTo(r.right - 16, r.bottom - 1);
  11018.                 ::Line(0, -15);
  11019.                 ::Line(15, 0);
  11020.                 }
  11021.             else
  11022.                 ::LineTo(r.right - 1, r.bottom - 1);
  11023.  
  11024.             ::LineTo(r.right - 1, r.top + 1);
  11025.             }
  11026.         }
  11027.     }
  11028.  
  11029. //
  11030. // AGAComputeTargetBorderRegion ------------------------------------------------
  11031. //
  11032.  
  11033. void AGAComputeTargetBorderRegion(RgnHandle borderRegion, const Rect* bounds, Boolean isNotched)
  11034.     {
  11035.     // Compute the border region to be painted.
  11036.  
  11037.     RgnHandle    innerRegion = ::NewRgn();
  11038.     Rect        r = *bounds;
  11039.  
  11040.     // First create a region framing the outer edge of the border.
  11041.     ::OpenRgn();
  11042.     ::FrameRoundRect(&r, 4, 4);
  11043.     ::CloseRgn(borderRegion);
  11044.  
  11045.     // Now subtract away the hollow inside area.
  11046.     ::InsetRect(&r, 2, 2);
  11047.     ::RectRgn(innerRegion, &r);
  11048.     ::DiffRgn(borderRegion, innerRegion, borderRegion);
  11049.     
  11050.     if (isNotched)
  11051.         {
  11052.         // OK, region madness as we add the top/left sides
  11053.         // of a new "notch" rect frame, and also remove the
  11054.         // bottom/right corner of our existing non-notched frame.
  11055.         
  11056.         RgnHandle    notchRegion = ::NewRgn();
  11057.         Rect        notchRect;
  11058.         
  11059.         // Create a new round rect for the corner area and
  11060.         // union it with the existing region.
  11061.         notchRect = *bounds;
  11062.         notchRect.left = notchRect.right - 17;
  11063.         notchRect.top = notchRect.bottom - 17;
  11064.  
  11065.         ::RectRgn(notchRegion, ¬chRect);
  11066.         ::UnionRgn(borderRegion, notchRegion, borderRegion);
  11067.         
  11068.         // Subtract away the corner of the existing frame.
  11069.         notchRect.left += 2;
  11070.         notchRect.top += 2;
  11071.  
  11072.         ::RectRgn(notchRegion, ¬chRect);
  11073.         ::DiffRgn(borderRegion, notchRegion, borderRegion);
  11074.         
  11075.         // Almost done. There's an extra pixel at each notch
  11076.         // corner that needs to be removed to make round corners.
  11077.         
  11078.         Rect    pixelRect;
  11079.         
  11080.         // The top/right corner.
  11081.         pixelRect = notchRect;
  11082.         pixelRect.left = pixelRect.right - 1;
  11083.         pixelRect.top--;
  11084.         pixelRect.bottom = pixelRect.top + 1;
  11085.         ::RectRgn(notchRegion, &pixelRect);
  11086.         ::DiffRgn(borderRegion, notchRegion, borderRegion);
  11087.         
  11088.         // The bottom/left corner.
  11089.         pixelRect = notchRect;
  11090.         pixelRect.top = pixelRect.bottom - 1;
  11091.         pixelRect.left--;
  11092.         pixelRect.right = pixelRect.left + 1;
  11093.         ::RectRgn(notchRegion, &pixelRect);
  11094.         ::DiffRgn(borderRegion, notchRegion, borderRegion);
  11095.         
  11096.         // The top/left corner.
  11097.         pixelRect = notchRect;
  11098.         pixelRect.top -= 2;
  11099.         pixelRect.left -= 2;
  11100.         pixelRect.bottom = pixelRect.top + 1;
  11101.         pixelRect.right = pixelRect.left + 1;
  11102.         ::RectRgn(notchRegion, &pixelRect);
  11103.         ::DiffRgn(borderRegion, notchRegion, borderRegion);
  11104.         
  11105.         ::DisposeRgn(notchRegion);
  11106.         }
  11107.     
  11108.     ::DisposeRgn(innerRegion);
  11109.     }
  11110.  
  11111. //
  11112. // AGAClipFurther ------------------------------------------------
  11113. //
  11114.  
  11115. void AGAClipFurther(Rect* clippingRect)
  11116.     {
  11117.     // Shrink the clip region further to prevent drawing outside
  11118.     // the specified rect.
  11119.  
  11120.     RgnHandle    oldClip = ::NewRgn();
  11121.     RgnHandle    newClip = ::NewRgn();
  11122.     
  11123.     if ((oldClip != NULL) && (newClip != NULL))
  11124.         {
  11125.         ::GetClip(oldClip);
  11126.         ::RectRgn(newClip, clippingRect);
  11127.  
  11128.         ::SectRgn(oldClip, newClip, newClip);
  11129.         ::SetClip(newClip);
  11130.         
  11131.         ::DisposeRgn(oldClip);
  11132.         ::DisposeRgn(newClip);
  11133.         }
  11134.     }
  11135.  
  11136. //
  11137. // AGA_PLstrcpy ------------------------------------------------
  11138. //
  11139.  
  11140. void AGA_PLstrcpy(StringPtr str1, ConstStr255Param str2)
  11141.     {
  11142.     // Copy pascal string str2 into pascal string str1.
  11143.  
  11144.     ::BlockMoveData((Ptr) str2, (Ptr) str1, 1 + str2[0]);
  11145.     }
  11146.  
  11147. //
  11148. // AGA Defaults ------------------------------------------------
  11149. //
  11150.  
  11151. void SetGrayCouncilDefault(UInt32 itemMask, Boolean turnOn)
  11152.     {
  11153.     if (turnOn)
  11154.         gAGADefaults |= itemMask;
  11155.     else
  11156.         gAGADefaults &= ~itemMask;
  11157.     }
  11158.  
  11159. Boolean TestGrayCouncilDefault(UInt32 itemMask)
  11160.     {
  11161.     return ((gAGADefaults & itemMask) != 0);
  11162.     }
  11163.  
  11164. //
  11165. // Variable-color background support -------------------------------
  11166. //
  11167. // Tab panels provide us a more complicated background color situation
  11168. // than other situations. While the normal AGA background is gray ramp
  11169. // value r2, the tab panels are lighter, namely r1. However, when a tab
  11170. // panel is dimmed, it becomes r2. Thus the panel subpanes can't just
  11171. // blindly use the window background color, and if the tab panel becomes
  11172. // dimmed they can't just blindly use r1 either.
  11173. //
  11174. // So what we do is maintain static color values that are picked up by
  11175. // any adapter classes that need to erase their background. There are
  11176. // separate color values for enabled and disabled states. When a panel
  11177. // view hierarchy is installed into a tab panel pane, the tab panel class
  11178. // temporarily sets these color values so that any subpanes of the panel
  11179. // will pick them up as they are instantiated.
  11180. //
  11181.  
  11182. static Boolean    gUseSpecialBackgroundColors = false;    // toggled by tab panel installer
  11183. static RGBColor    gEnabledBackgroundColor;
  11184. static RGBColor    gDisabledBackgroundColor;
  11185.  
  11186. Boolean DetermineAGABackgroundColors(RGBColor* enabledColor, RGBColor* disabledColor, Boolean installIfNotCustom)
  11187.     {
  11188.     Boolean    wereColorsSet = false;
  11189.  
  11190.     if (gUseSpecialBackgroundColors)
  11191.         {
  11192.         *enabledColor = gEnabledBackgroundColor;
  11193.         *disabledColor = gDisabledBackgroundColor;
  11194.         wereColorsSet = true;
  11195.         }
  11196.     else if (installIfNotCustom)
  11197.         {
  11198.         // The calling view must have focused and set the port bg color.
  11199.         ::GetBackColor(enabledColor);
  11200.         *disabledColor = *enabledColor;
  11201.         wereColorsSet = true;
  11202.         }
  11203.  
  11204.     return wereColorsSet;
  11205.     }
  11206.  
  11207. void InstallAGABackgroundColors(AGAObject* itsAGAObject, Boolean installIfNotCustom)
  11208.     {
  11209.     RGBColor    enabledColor;
  11210.     RGBColor    disabledColor;
  11211.  
  11212.     if (DetermineAGABackgroundColors(&enabledColor, &disabledColor, installIfNotCustom))
  11213.         itsAGAObject->SetBackgroundColors(&enabledColor, &disabledColor);
  11214.     }
  11215.  
  11216. void TurnOnCustomAGABackgroundColors(RGBColor* enabledColor, RGBColor* disabledColor)
  11217.     {
  11218.     gUseSpecialBackgroundColors = true;
  11219.     gEnabledBackgroundColor = *enabledColor;
  11220.     gDisabledBackgroundColor = *disabledColor;
  11221.     }
  11222.  
  11223. void TurnOffCustomAGABackgroundColors()
  11224.     {
  11225.     gUseSpecialBackgroundColors = false;
  11226.     }
  11227.  
  11228. //
  11229. // Global variables ---------------------------------------------------
  11230. //
  11231.  
  11232. const Str255 gGrayCouncilCopyright = kGrayCouncilCopyright;
  11233.  
  11234. Boolean gAGAHasColorQD;
  11235. UInt32    gAGADefaults = 0;
  11236. AGAGroupsContainer* gGroupsContainer;
  11237.  
  11238. // Standard system text style, used by most standard controls.
  11239. AGATextStyle gAGAStdSystemStyle = AGATextStyle();
  11240.  
  11241. // Standard small text style, used for slider labels.
  11242. AGATextStyle gAGAStdSmallStyle = AGATextStyle(applFont, 10, normal);
  11243.  
  11244. // Standard small bold text style, used for small tab panels.
  11245. AGATextStyle gAGAStdBoldSmallStyle = AGATextStyle(applFont, 10, bold);
  11246.  
  11247. // Extra small text style, a de facto standard.
  11248. AGATextStyle gAGAExtraSmallStyle = AGATextStyle(applFont, 9, normal);
  11249.  
  11250. // These are the AGA-specified color values.
  11251. RGBColor gAGARamp[kNumRampColors] =
  11252.     {
  11253.     {65535, 65535, 65535},    // rW    white
  11254.     {61166, 61166, 61166},    // r1    lightest gray
  11255.     {56797, 56797, 56797},    // r2
  11256.     {52428, 52428, 52428},    // r3
  11257.     {48059, 48059, 48059},    // r4    light grays
  11258.     {43690, 43690, 43690},    // r5
  11259.     {39321, 39321, 39321},    // r6
  11260.     {34952, 34952, 34952},    // r7
  11261.     {30583, 30583, 30583},    // r8    dark grays
  11262.     {26214, 26214, 26214},    // r9
  11263.     {21845, 21845, 21845},    // r10
  11264.     {17476, 17476, 17476},    // r11
  11265.     {13107, 13107, 13107},    // r12    darkest "n" gray
  11266.     {8738, 8738, 8738},        // rA1    additional darker gray value 1
  11267.     {4369, 4369, 4369},        // rA2    additional darker gray value 2
  11268.     {0, 0, 0},                // rB    black
  11269.     {52428, 52428, 65535},    // rP1    lightest purple
  11270.     {39321, 39321, 65535},    // rP2    light purple
  11271.     {26214, 26214, 65535},    // rP3    dark purple
  11272.     {13107, 13107, 26214}    // rP4    darkest purple
  11273.     };
  11274.  
  11275.