TweetFollow Us on Twitter

MACINTOSH C CARBON

Demonstration Program Controls3

Goto Contents

// *******************************************************************************************
// Controls3.h                                                             CLASSIC EVENT MODEL
// *******************************************************************************************
//
// This program demonstrates the creation and handling of those controls not demonstrated in
// the programs Controls1 and Controls2 (Chapter 7), with the exception of List boxes
// and determinate progress bars.
// 
// The program utilises the following resources:
//
// o  A 'plst' resource.
//
// o  An 'MBAR' resource, and 'MENU' resources for Apple, File, Edit, and Demonstration menus
//    (preload, non-purgeable).
//
// o  'MENU' resources (non-purgeable) for bevel button menus and for a pop-up group box.
//
// o  A 'WIND' resource (purgeable) (initially not visible).
//
// o  'DLOG' resources and associated 'DITL', 'dlgx' and 'dftb' resources (purgeable).  
//
// o  'CNTL' resources (purgeable).
//
// o  A 'tab#' resource (purgeable.
//
// o  An icon family resource (purgeable).
//
// o  'PICT' resources (purgeable).
//
// o  'cicn' resources (purgeable).
//
// o  'STR#' resources (purgeable).
//
// o  'TEXT' and 'styl' resources (purgeable).
//
// o  'hrct' and an 'hwin' resources (preload, purgeable), which provide help balloons
//    describing  the various controls.  
//
// o  A 'SIZE' resource with the acceptSuspendResumeEvents, canBackground, 
//    doesActivateOnFGSwitch, and isHighLevelEventAware flags set.
//
// *******************************************************************************************

// .................................................................................. includes

#include <Carbon.h>
#include <string.h>

// ................................................................................... defines

#define rMenubar                128
#define mAppleApplication       128
#define  iAbout                 1
#define mFile                   129
#define  iQuit                  12
#define mDemonstration          131
#define  iBevelAndImage          1
#define  iTabEditClock          2
#define  iGroupArrowsProgress   3
#define  iSliders               4
#define  iTextBoxes             5
#define  iSmallControls         6
#define rBevelImageWindow       128
#define  cBevelButton1          128
#define  cBevelButton2          129
#define  cBevelButton3          130
#define  cBevelButton4          131
#define  cBevelButton5          132
#define  cBevelButton6          133
#define  cBevelButton7          134
#define  cBevelButton8          135
#define  cBevelButton9          136
#define  cBevelButton10         137
#define  cBevelButton11         138
#define  cBevelButton12         139
#define  cBevelButton13         140
#define  cBevelButton14         141
#define  cBevelButton15         142
#define  cBevelButton16         143
#define  cBevelButton17         144
#define  cBevelButton18         145
#define  cBevelButton19         146
#define  cBevelButton20         147
#define  cBevelButton21         148
#define  cImageWell1            149
#define  cImageWell2            150
#define  cPicture1              151
#define  cPicture2              152
#define  cColourIcon1           153
#define  cColourIcon2           154
#define  cIconSuite1            155
#define  cIconSuite2            156
#define  cWindowHeader          157
#define  rPartCodeStrings       128
#define  rGraphicAlignStrings   129
#define  rTextAlignStrings      130
#define  rTextPlacementStrings  131
#define rTabEditClockDialog     128
#define  iTabs                  2
#define  tabEditText            1
#define  tabClocks              2
#define  iEditTextUserPane      3
#define  iEditText1             5
#define  iEditText2             7
#define  iEditText3             9
#define  iExtractEditText       10
#define  iClocksUserPane        12
#define  iImageWellEditText     11
#define  iClocks1               14
#define  iClocks2               16
#define  iClocks3               18
#define  iExtractClocks         19
#define  iImageWellClocks       20
#define  kLeftArrow             0x1C
#define  kRightArrow            0x1D
#define  kUpArrow               0x1E
#define  kDownArrow             0x1F
#define  kBackspace             0x08
#define  kDelete                0x7F
#define rGroupArrowsProgDialog  129
#define  iCheckboxGroup         2
#define  iRadioGroupColour      3
#define  iStaticTextColourDepth 7
#define  iPopupGroup            8
#define  iUserPaneNamesInitials 9
#define  iRadioGroupNames       10
#define  iCheckboxShowInitials  13
#define  iUserPaneScoreAverage  15
#define  iRadioGroupScores      16
#define  iCheckboxShowAverages  19
#define  iStaticTextCache       26
#define  iLittleArrows          27
#define  iPushButtonExtract     28
#define  iImageWell             29
#define  iDisclosureTriangle    31
#define  iStaticTextDisclosure  32
#define  iProgressBar           34
#define rSlidersDialog          131
#define  iSlider1               2
#define  iSlider2               3
#define  iSlider3               4
#define  iSlider4               5
#define  iSlider1StaticText     9
#define  iSlider2StaticText     11
#define  iSlider3StaticText     13
#define  iSlider4StaticText     15
#define  iSlider5               17
#define  iUserPane1             18
#define  iSlider6               19
#define cSmallPopup             203
#define rSmallControlsString    136
#define rAboutDialog            132
#define MAX_UINT32              0xFFFFFFFF
#define MIN(a,b)                ((a) < (b) ? (a) : (b))

// .................................................................................. typedefs

typedef struct
{
  ControlRef bevelButton1Ref;
  ControlRef bevelButton2Ref;
  ControlRef bevelButton3Ref;
  ControlRef bevelButton4Ref;
  ControlRef bevelButton5Ref;
  ControlRef bevelButton6Ref;
  ControlRef bevelButton7Ref;
  ControlRef bevelButton8Ref;
  ControlRef bevelButton9Ref;
  ControlRef bevelButton10Ref;
  ControlRef bevelButton11Ref;
  ControlRef bevelButton12Ref;
  ControlRef bevelButton13Ref;
  ControlRef bevelButton14Ref;
  ControlRef bevelButton15Ref;
  ControlRef bevelButton16Ref;
  ControlRef bevelButton17Ref;
  ControlRef bevelButton18Ref;
  ControlRef bevelButton19Ref;
  ControlRef bevelButton20Ref;
  ControlRef bevelButton21Ref;
  ControlRef imageWell1Ref;
  ControlRef imageWell2Ref;
  ControlRef picture1Ref;
  ControlRef picture2Ref;
  ControlRef colourIcon1Ref;
  ControlRef colourIcon2Ref;
  ControlRef iconSuite1Ref;
  ControlRef iconSuite2Ref;
  ControlRef windowHeaderRef;
} BevelDocStruc;

typedef BevelDocStruc **BevelDocStrucHandle;

// ....................................................................... function prototypes

void    main                          (void);
void    doPreliminaries               (void);
OSErr   quitAppEventHandler           (AppleEvent *,AppleEvent *,SInt32);
void    doGetControls                 (WindowRef);
void    doEvents                      (EventRecord *);
void    doMouseDown                   (EventRecord *);
void    doMenuChoice                  (SInt32);
void    doUpdate                      (EventRecord *);
void    doActivate                    (EventRecord *);
void    doActivateWindow              (WindowRef,Boolean);
void    doConcatPStrings              (Str255,Str255);
void    doCopyPString                 (Str255,Str255);

void    doBevelImagePictIcon          (void);
void    doBevelImagePictIconContent   (EventRecord *,WindowRef);
void    doDrawPartCode                (WindowRef,ControlRef,SInt16,SInt16);
void    doGraphicAlignment            (WindowRef,ControlRef,ControlRef);
void    doTextAlignment               (WindowRef,ControlRef,ControlRef);
void    doTextOffset                  (WindowRef,ControlRef,ControlRef);
void    doTextPlacement               (WindowRef,ControlRef,ControlRef);
void    doDrawMessage                 (WindowRef,Boolean);
void    doDrawLegends                 (WindowRef,Boolean);
void    helpTagsBevelImagePictIcon    (WindowRef);

void    doTabEditClock                (void);
void    doExtractEditText             (DialogRef);
void    doExtractDateTime             (DialogRef);
void    helpTagsTabEditClock          (DialogRef);

void    doGroupArrowsProgress         (void);
void    doCheckBoxGroupBox            (DialogRef);
void    doPopupGroupBox               (DialogRef);
void    doChasingAndProgress          (DialogRef);
void    doExtractCurrentStatus        (DialogRef);
void    helpTagsGroupArrowsProgress   (DialogRef);

void    doSliderUserPane              (void);
void    doDrawSliderValues            (DialogRef,ControlRef);
void    helpTagsSliders               (DialogRef);

void    doTextBox                     (void);

void    doSmallControls               (void);
void    doMouseDownSmallControls      (WindowRef,EventRecord *);

Boolean eventFilter                   (DialogRef,EventRecord *,SInt16 *);
void    editTextValidator             (ControlRef);
ControlKeyFilterResult  numericFilter (ControlRef,SInt16 *,SInt16 *,EventModifiers *);
void    arrowsActionFunction          (ControlRef,SInt16);
void    sliderActionFunction1         (ControlRef,SInt16);
void    sliderActionFunction2         (ControlRef,SInt16);
void    userPaneDrawFunction          (ControlRef,SInt16);
void    userPaneActivateFunction      (ControlRef,Boolean);

// *******************************************************************************************
// Controls3.c
// *******************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// .......................................................................... global variables

Boolean gRunningOnX                = false;
Boolean gInBackground              = false;
Boolean gDone;
Str255  gCurrentString;
Boolean gBevelAndImageActive       = false;
Boolean gGroupArrowsProgressActive = false;
Boolean gSlidersActive             = false;

// ************************************************************************************** main

void  main(void)
{
  MenuBarHandle menubarHdl;
  SInt32        response;
  MenuRef       menuRef;
  EventRecord   eventStructure;

  // ......................................................................... do prelimiaries

  doPreliminaries();

  // ............................................................... set up menu bar and menus
  
  menubarHdl = GetNewMBar(rMenubar);
  if(menubarHdl == NULL)
    ExitToShell();
  SetMenuBar(menubarHdl);
  DrawMenuBar();

  Gestalt(gestaltMenuMgrAttr,&response);
  if(response & gestaltMenuMgrAquaLayoutMask)
  {
    menuRef = GetMenuRef(mFile);
    if(menuRef != NULL)
    {
      DeleteMenuItem(menuRef,iQuit);
      DeleteMenuItem(menuRef,iQuit - 1);
      DisableMenuItem(menuRef,0);
    }

    menuRef = GetMenuRef(mDemonstration);
    if(menuRef != NULL)
      EnableMenuItem(menuRef,iSmallControls);

    gRunningOnX = true;
  }

  // ........................................................................ enter eventLoop

  gDone = false;

  while(!gDone)
  {
    if(WaitNextEvent(everyEvent,&eventStructure,MAX_UINT32,NULL))
      doEvents(&eventStructure);
  }
}

// *************************************************************************** doPreliminaries

void  doPreliminaries(void)
{
  OSErr osError;

  MoreMasterPointers(512);
  InitCursor();
  FlushEvents(everyEvent,0);

  osError = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
                            NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
                            0L,false);
  if(osError != noErr)
    ExitToShell();
}

// **************************************************************************** doQuitAppEvent

OSErr  quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
  OSErr    osError;
  DescType returnedType;
  Size     actualSize;

  osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
                              &actualSize);

  if(osError == errAEDescNotFound)
  {
    gDone = true;
    osError = noErr;
  } 
  else if(osError == noErr)
    osError = errAEParamMissed;

  return osError;
}

// ********************************************************************************** doEvents

void  doEvents(EventRecord *eventStrucPtr)
{
  SInt32 menuChoice;
  SInt16 menuID, menuItem;

  switch(eventStrucPtr->what)
  {
    case kHighLevelEvent:
      AEProcessAppleEvent(eventStrucPtr);
      break;

    case keyDown:
      if((eventStrucPtr->modifiers & cmdKey) != 0)
      {
        menuChoice = MenuEvent(eventStrucPtr);
        menuID = HiWord(menuChoice);
        menuItem = LoWord(menuChoice);
        if(menuID == mFile && menuItem  == iQuit)
          gDone = true;
      }
      break;

    case mouseDown:
      doMouseDown(eventStrucPtr);
      break;

    case updateEvt:
      doUpdate(eventStrucPtr);
      break;

    case activateEvt:
      doActivate(eventStrucPtr);
      break;

    case osEvt:
      switch((eventStrucPtr->message >> 24) & 0x000000FF)
      {
        case suspendResumeMessage:
          if((eventStrucPtr->message & resumeFlag) == 1)
          {
            SetThemeCursor(kThemeArrowCursor);
            gInBackground = false;
          }
          else
            gInBackground = true;
      }
      break;
  }
}

// ******************************************************************************* doMouseDown

void  doMouseDown(EventRecord *eventStrucPtr)
{
  WindowPartCode partCode;
  WindowRef      windowRef;
  MenuRef        menuRef;
  WindowClass    windowClass;

  partCode = FindWindow(eventStrucPtr->where,&windowRef);

  switch(partCode)
  {
    case inMenuBar:
      menuRef = GetMenuRef(mDemonstration);
      if(gBevelAndImageActive)
        DisableMenuItem(menuRef,iBevelAndImage);
      else
        EnableMenuItem(menuRef,iBevelAndImage);
      doMenuChoice(MenuSelect(eventStrucPtr->where));
      break;

    case inContent:
      GetWindowClass(windowRef,&windowClass);
      if(windowClass == kFloatingWindowClass)
        doMouseDownSmallControls(windowRef,eventStrucPtr);
      else if(windowRef != FrontNonFloatingWindow())
        SelectWindow(windowRef);
      else
      {
        if(gBevelAndImageActive)
          doBevelImagePictIconContent(eventStrucPtr,windowRef);
      }
      break;

    case inDrag:
      DragWindow(windowRef,eventStrucPtr->where,NULL);
      break;

    case inGoAway:
      if(TrackGoAway(windowRef,eventStrucPtr->where) == true)
      {
        DisposeWindow(windowRef);
        gBevelAndImageActive = false;
      }
      break;

  }
}

// ****************************************************************************** doMenuChoice

void  doMenuChoice(SInt32 menuChoice)
{
  MenuID        menuID;
  MenuItemIndex menuItem;
  MenuRef       menuRef;
  
  menuID = HiWord(menuChoice);
  menuItem = LoWord(menuChoice);

  if(menuID == 0)
    return;

  switch(menuID)
  {
    case mAppleApplication:
      if(menuItem == iAbout)
        SysBeep(10);
      break;

    case mFile:
      if(menuItem == iQuit)
        gDone = true;
      break;

    case mDemonstration:
      switch(menuItem)
      {
        case iBevelAndImage:
          gBevelAndImageActive = true;
          doBevelImagePictIcon();
          break;

        case iTabEditClock:
          doTabEditClock();
          break;

        case iGroupArrowsProgress:
          gGroupArrowsProgressActive = true;
          doGroupArrowsProgress();
          break;
        
        case iSliders:
          gSlidersActive = true;
          doSliderUserPane();
          break;

        case iTextBoxes:
          doTextBox();
          break;

        case iSmallControls:
          doSmallControls();
          menuRef = GetMenuRef(mDemonstration);
          DisableMenuItem(menuRef,iSmallControls);
          break;
      }
      break;
  }

  HiliteMenu(0);
}

// ********************************************************************************** doUpdate

void  doUpdate(EventRecord *eventStrucPtr)
{
  WindowRef windowRef;
  RgnHandle visibleRegionHdl = NewRgn();
  Boolean   drawMode = false;

  windowRef = (WindowRef) eventStrucPtr->message;

  BeginUpdate(windowRef);

  SetPortWindowPort(windowRef);
    
  GetPortVisibleRegion(GetWindowPort(windowRef),visibleRegionHdl);
  UpdateControls(windowRef,visibleRegionHdl);

  if(gBevelAndImageActive)
  {
    if(windowRef == FrontNonFloatingWindow())
    {    
      doDrawMessage(windowRef,!gInBackground);
      doDrawLegends(windowRef,!gInBackground);
    }
    else
    {
      doDrawMessage(windowRef,gInBackground);
      doDrawLegends(windowRef,gInBackground);
    }
  }

  EndUpdate(windowRef);
}

// ******************************************************************************** doActivate

void  doActivate(EventRecord *eventStrucPtr)
{
  WindowRef windowRef;
  Boolean   becomingActive;

  windowRef = (WindowRef) eventStrucPtr->message;
  becomingActive = ((eventStrucPtr->modifiers & activeFlag) == activeFlag);

  doActivateWindow(windowRef,becomingActive);
}

// ************************************************************************** doActivateWindow

void  doActivateWindow(WindowRef windowRef,Boolean becomingActive)
{  
  ControlRef controlRef;

  GetRootControl(windowRef,&controlRef);

  if(becomingActive)
  {
    if(gBevelAndImageActive)
    {
      ActivateControl(controlRef);
      doDrawMessage(windowRef,becomingActive);
      doDrawLegends(windowRef,becomingActive);
    }
  }
  else
  {
    if(gBevelAndImageActive)
    {
      DeactivateControl(controlRef);
      doDrawMessage(windowRef,becomingActive);
      doDrawLegends(windowRef,becomingActive);
    }
  }
}

// ************************************************************************** doConcatPStrings

void  doConcatPStrings(Str255 targetString,Str255 appendString)
{
  SInt16 appendLength;

  appendLength = MIN(appendString[0],255 - targetString[0]);

  if(appendLength > 0)
  {
    BlockMoveData(appendString+1,targetString+targetString[0]+1,(SInt32) appendLength);
    targetString[0] += appendLength;
  }
}

// ***************************************************************************** doCopyPString

void  doCopyPString(Str255 sourceString,Str255 destinationString)
{
  SInt16 stringLength;

  stringLength = sourceString[0];
  BlockMove(sourceString + 1,destinationString + 1,stringLength);
  destinationString[0] = stringLength;
}

// *******************************************************************************************
// BevelImagePictIcon.c
// *******************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// .......................................................................... global variables

WindowRef gWindowRef;

extern Boolean gRunningOnX;
extern Str255  gCurrentString;
extern Boolean gInBackground;

// ********************************************************************** doBevelImagePictIcon

void  doBevelImagePictIcon(void)
{
  BevelDocStrucHandle bevelDocStrucHdl;

  // ................................................. initial advisory text for window header

  doCopyPString("\pBalloon (OS 8/9) and Help tag (OS X) help is available",gCurrentString);

  // ............. open a window, set font size, set theme-compliant colour/pattern for window

  if(!(gWindowRef = GetNewCWindow(rBevelImageWindow,NULL,(WindowRef)-1)))
    ExitToShell();

  SetPortWindowPort(gWindowRef);
  UseThemeFont(kThemeSmallSystemFont,smSystemScript);

  SetThemeWindowBackground(gWindowRef,kThemeBrushDialogBackgroundActive,true);

  // ........... get block for document structure, assign handle to window record refCon field

  if(!(bevelDocStrucHdl = (BevelDocStrucHandle) NewHandle(sizeof(BevelDocStruc))))
    ExitToShell();

  SetWRefCon(gWindowRef,(SInt32) bevelDocStrucHdl);

  // ........................................ get controls, help tags if OS X, and show window

  doGetControls(gWindowRef);

  if(gRunningOnX)
    helpTagsBevelImagePictIcon(gWindowRef);

  ShowWindow(gWindowRef);
}

// ***************************************************************************** doGetControls

void  doGetControls(WindowRef windowRef)
{
  ControlRef                 controlRef;
  BevelDocStrucHandle        bevelDocStrucHdl;
  ThemeButtonKind            buttonKind = kThemeRoundedBevelButton;
  ControlButtonTextPlacement textPlacementBelow = kControlBevelButtonPlaceBelowGraphic;
  ControlButtonTextPlacement textPlacementAbove = kControlBevelButtonPlaceAboveGraphic;
  Boolean                    centrePopupGlyph = true;
  ControlFontStyleRec        controlFontStyleStruc;

  // ............... create root control for window, get handle to window's document structure

  if(!gRunningOnX)
    CreateRootControl(windowRef,&controlRef);

  bevelDocStrucHdl = (BevelDocStrucHandle) (GetWRefCon(windowRef));

  // ........................................................................ get the controls

  if(!((*bevelDocStrucHdl)->bevelButton1Ref = GetNewControl(cBevelButton1,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton2Ref = GetNewControl(cBevelButton2,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton3Ref = GetNewControl(cBevelButton3,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton4Ref = GetNewControl(cBevelButton4,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton5Ref = GetNewControl(cBevelButton5,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton6Ref = GetNewControl(cBevelButton6,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton7Ref = GetNewControl(cBevelButton7,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton8Ref = GetNewControl(cBevelButton8,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton9Ref = GetNewControl(cBevelButton9,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton10Ref = GetNewControl(cBevelButton10,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton11Ref = GetNewControl(cBevelButton11,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton12Ref = GetNewControl(cBevelButton12,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton13Ref = GetNewControl(cBevelButton13,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton14Ref = GetNewControl(cBevelButton14,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton15Ref = GetNewControl(cBevelButton15,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton16Ref = GetNewControl(cBevelButton16,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton17Ref = GetNewControl(cBevelButton17,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton18Ref = GetNewControl(cBevelButton18,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton19Ref = GetNewControl(cBevelButton19,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton20Ref = GetNewControl(cBevelButton20,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->bevelButton21Ref = GetNewControl(cBevelButton21,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->imageWell1Ref = GetNewControl(cImageWell1,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->imageWell2Ref = GetNewControl(cImageWell2,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->picture1Ref = GetNewControl(cPicture1,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->picture2Ref = GetNewControl(cPicture2,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->colourIcon1Ref = GetNewControl(cColourIcon1,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->colourIcon2Ref = GetNewControl(cColourIcon2,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->iconSuite1Ref= GetNewControl(cIconSuite1,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->iconSuite2Ref= GetNewControl(cIconSuite2,windowRef)))
    ExitToShell();
  if(!((*bevelDocStrucHdl)->windowHeaderRef = GetNewControl(cWindowHeader,windowRef)))
    ExitToShell();

  // ............................... if running on OS X, make first four bevel buttons rounded

  if(gRunningOnX)
  {
    SetControlData((*bevelDocStrucHdl)->bevelButton1Ref,kControlEntireControl,
                   kControlBevelButtonKindTag,sizeof(buttonKind),&buttonKind);
    SetControlData((*bevelDocStrucHdl)->bevelButton2Ref,kControlEntireControl,
                   kControlBevelButtonKindTag,sizeof(buttonKind),&buttonKind);
    SetControlData((*bevelDocStrucHdl)->bevelButton3Ref,kControlEntireControl,
                   kControlBevelButtonKindTag,sizeof(buttonKind),&buttonKind);
    SetControlData((*bevelDocStrucHdl)->bevelButton4Ref,kControlEntireControl,
                   kControlBevelButtonKindTag,sizeof(buttonKind),&buttonKind);
  }

  // ........................................ set text placement for 2nd and 21st bevel button

  SetControlData((*bevelDocStrucHdl)->bevelButton2Ref,kControlEntireControl,
                 kControlBevelButtonTextPlaceTag,sizeof(textPlacementBelow),
                 &textPlacementBelow);
  SetControlData((*bevelDocStrucHdl)->bevelButton21Ref,kControlEntireControl,
                 kControlBevelButtonTextPlaceTag,sizeof(textPlacementAbove),
                 &textPlacementAbove);
                 
  // ........................................ set position of pop-up arrow in 6th bevel button

  SetControlData((*bevelDocStrucHdl)->bevelButton6Ref,kControlEntireControl,
                 kControlBevelButtonCenterPopupGlyphTag,sizeof(centrePopupGlyph),
                 ¢rePopupGlyph);

  // ................................ set font for 20th bevel button to small bold system font

  controlFontStyleStruc.flags = kControlUseFontMask;
  controlFontStyleStruc.font = kControlFontSmallBoldSystemFont;
  SetControlFontStyle((*bevelDocStrucHdl)->bevelButton20Ref,&controlFontStyleStruc);

  // ................................................. set 3rd bevel button to the mixed state

  SetControlValue((*bevelDocStrucHdl)->bevelButton3Ref,2);
}

// *************************************************************** doBevelImagePictIconContent

void  doBevelImagePictIconContent(EventRecord *eventStrucPtr,WindowRef windowRef)
{
  BevelDocStrucHandle bevelDocStrucHdl;
  ControlRef          controlRef;
  SInt16              partCode, menuItem;

  bevelDocStrucHdl = (BevelDocStrucHandle) (GetWRefCon(windowRef));

  SetPortWindowPort(windowRef);
  GlobalToLocal(&eventStrucPtr->where);
  partCode = FindControl(eventStrucPtr->where,windowRef,&controlRef);

  doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,1234);

  if(partCode)
  {
    partCode = TrackControl(controlRef,eventStrucPtr->where,NULL);

    if(controlRef == (*bevelDocStrucHdl)->bevelButton1Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton2Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton3Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton4Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton9Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton13Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton14Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton15Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton16Ref ||
       controlRef == (*bevelDocStrucHdl)->bevelButton17Ref)  
    {
      doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
    }
    else if(controlRef == (*bevelDocStrucHdl)->bevelButton5Ref ||
            controlRef == (*bevelDocStrucHdl)->bevelButton6Ref ||
            controlRef == (*bevelDocStrucHdl)->bevelButton7Ref ||
            controlRef == (*bevelDocStrucHdl)->bevelButton8Ref)
    {
      if(partCode == kControlMenuPart)
      {
        GetBevelButtonMenuValue(controlRef,&menuItem);
        doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,menuItem);
      }
      else
        doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
    }
    else if(controlRef == (*bevelDocStrucHdl)->bevelButton10Ref ||
            controlRef == (*bevelDocStrucHdl)->bevelButton11Ref ||
            controlRef == (*bevelDocStrucHdl)->bevelButton12Ref)
    {
      if(partCode != kControlEntireControl)
      {
        SetControlValue((*bevelDocStrucHdl)->bevelButton10Ref,0);
        SetControlValue((*bevelDocStrucHdl)->bevelButton11Ref,0);
        SetControlValue((*bevelDocStrucHdl)->bevelButton12Ref,0);
        SetControlValue(controlRef,1);
      }
      doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
    }
    else if(controlRef == (*bevelDocStrucHdl)->bevelButton18Ref)
    {
      doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
      doGraphicAlignment(windowRef,controlRef,(*bevelDocStrucHdl)->windowHeaderRef);
    }
    else if(controlRef == (*bevelDocStrucHdl)->bevelButton19Ref)
    {
      doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
      doTextAlignment(windowRef,controlRef,(*bevelDocStrucHdl)->windowHeaderRef);
    }
    else if(controlRef == (*bevelDocStrucHdl)->bevelButton20Ref)
    {
      doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
      doTextOffset(windowRef,controlRef,(*bevelDocStrucHdl)->windowHeaderRef);
    }
    else if(controlRef == (*bevelDocStrucHdl)->bevelButton21Ref)
    {
      doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
      doTextPlacement(windowRef,controlRef,(*bevelDocStrucHdl)->windowHeaderRef);
    }
    else
      doDrawPartCode(windowRef,(*bevelDocStrucHdl)->windowHeaderRef,partCode,4321);
  }
}

// **************************************************************************** doDrawPartCode

void  doDrawPartCode(WindowRef windowRef,ControlRef windowHeaderRef,SInt16 partCode,
                     SInt16 menuItem)
{
  SInt16 stringIndex;
  Str255 theString;

  if(partCode == kControlEntireControl)
    stringIndex = 1;
  else if(partCode == kControlMenuPart)
    stringIndex = 2;
  else if(partCode == kControlTrianglePart)
    stringIndex = 3;
  else if(partCode == kControlEditTextPart)
    stringIndex = 4;
  else if(partCode == kControlPicturePart)
    stringIndex = 5;
  else if(partCode == kControlIconPart)
    stringIndex = 6;
  else if(partCode == kControlClockPart)
    stringIndex = 7;
  else if(partCode == kControlListBoxPart)
    stringIndex = 8;
  else if(partCode == kControlListBoxDoubleClickPart)
    stringIndex = 9;
  else if(partCode == kControlImageWellPart)
    stringIndex = 10;
  else if(partCode == kControlRadioGroupPart)
    stringIndex = 11;
  else if(partCode == kControlButtonPart)
    stringIndex = 12;
  else if(partCode == kControlIndicatorPart)
    stringIndex = 13;

  if(menuItem > 0 && menuItem < 1234)
  {
    doCopyPString("\pTrackControl returned ",gCurrentString);
    GetIndString(theString,rPartCodeStrings,stringIndex);
    doConcatPStrings(gCurrentString,theString);
    doConcatPStrings(gCurrentString,"\p    GetBevelButtonMenuValue returned menu item ");
    NumToString((SInt32) menuItem,theString);
    doConcatPStrings(gCurrentString,theString);
  }
  else if(menuItem == 1234 || menuItem == 4321)
  {
    if(menuItem == 1234)
      doCopyPString("\pMouse-down in ",gCurrentString);
    else if(menuItem == 4321)
      doCopyPString("\pTrackControl returned ",gCurrentString);
    GetIndString(theString,rPartCodeStrings,stringIndex);
    doConcatPStrings(gCurrentString,theString);
  }

  Draw1Control(windowHeaderRef);
  doDrawMessage(windowRef,true);
}

// ************************************************************************ doGraphicAlignment

void  doGraphicAlignment(WindowRef windowRef,ControlRef controlRef,ControlRef windowHeaderRef)
{
  SInt16                        a, b;
  UInt32                        finalTicks;
  ControlButtonGraphicAlignment alignmentConstant = 0;
  
  if(!gRunningOnX)
    SetThemeCursor(kThemeWatchCursor);

  for(a=1;a<10;a++)
  {
    Delay(60,&finalTicks);
    alignmentConstant++;
    if(alignmentConstant == 9)
      alignmentConstant = 0;

    Draw1Control(windowHeaderRef);
    GetIndString(gCurrentString,rGraphicAlignStrings,a);
    doDrawMessage(windowRef,true);

    for(b=0;b<=52;b++)
    {
      SetBevelButtonGraphicAlignment(controlRef,alignmentConstant,b,b);
      Delay(2,&finalTicks);
      Draw1Control(controlRef);
      QDFlushPortBuffer(GetWindowPort(FrontNonFloatingWindow()),NULL);
    }
  }

  if(!gRunningOnX)
    SetThemeCursor(kThemeArrowCursor);
}

// *************************************************************************** doTextAlignment

void  doTextAlignment(WindowRef windowRef,ControlRef controlRef,ControlRef windowHeaderRef)
{
  SInt16                     a, b;
  UInt32                     finalTicks;
  ControlButtonTextAlignment alignmentConstant = -3;

  if(!gRunningOnX)
    SetThemeCursor(kThemeWatchCursor);

  for(a=1;a<4;a++)
  {
    Delay(60,&finalTicks);
    alignmentConstant++;
    if(alignmentConstant == 0)
      alignmentConstant++;

    Draw1Control(windowHeaderRef);
    GetIndString(gCurrentString,rTextAlignStrings,a);
    doDrawMessage(windowRef,true);

    for(b=0;b<=40;b++)
    {
      SetBevelButtonTextAlignment(controlRef,alignmentConstant,b);
      Delay(2,&finalTicks);
      Draw1Control(controlRef);
      QDFlushPortBuffer(GetWindowPort(FrontNonFloatingWindow()),NULL);
    }
  }

  if(!gRunningOnX)
    SetThemeCursor(kThemeArrowCursor);
}

// ****************************************************************************** doTextOffset

void  doTextOffset(WindowRef windowRef,ControlRef controlRef,ControlRef windowHeaderRef)
{
  ControlButtonTextAlignment alignmentConstant;
  SInt16                     offset;
  UInt32                     finalTicks;

  if(!gRunningOnX)
    SetThemeCursor(kThemeWatchCursor);

  Draw1Control(windowHeaderRef);
  doCopyPString("\pOffset from left",gCurrentString);
  doDrawMessage(windowRef,true);

  alignmentConstant = kControlBevelButtonAlignTextFlushLeft;
  SetControlData(controlRef,kControlEntireControl,kControlBevelButtonTextAlignTag,
                  sizeof(alignmentConstant),&alignmentConstant);
  Draw1Control(controlRef);

  for(offset=1;offset<27;offset++)
  {
    Delay(15,&finalTicks);
    SetControlData(controlRef,kControlEntireControl,kControlBevelButtonTextOffsetTag,
                   sizeof(offset),&offset);
    Draw1Control(controlRef);
    QDFlushPortBuffer(GetWindowPort(FrontNonFloatingWindow()),NULL);
  }

  Delay(60,&finalTicks);

  Draw1Control(windowHeaderRef);
  doCopyPString("\pOffset from right",gCurrentString);
  doDrawMessage(windowRef,true);

  alignmentConstant = kControlBevelButtonAlignTextFlushRight;
  SetControlData(controlRef,kControlEntireControl,kControlBevelButtonTextAlignTag,
                  sizeof(alignmentConstant),&alignmentConstant);

  for(offset=0;offset<13;offset++)
  {
    Delay(15,&finalTicks);
    SetControlData(controlRef,kControlEntireControl,kControlBevelButtonTextOffsetTag,
                   sizeof(offset),&offset);
    Draw1Control(controlRef);
    QDFlushPortBuffer(GetWindowPort(FrontNonFloatingWindow()),NULL);
  }

  if(!gRunningOnX)
    SetThemeCursor(kThemeArrowCursor);
}

// *************************************************************************** doTextPlacement

void  doTextPlacement(WindowRef windowRef,ControlRef controlRef,ControlRef windowHeaderRef)
{
  ControlButtonTextPlacement placementConstant;
  UInt32                     finalTicks;

  if(!gRunningOnX)
    SetThemeCursor(kThemeWatchCursor);

  for(placementConstant = 1;placementConstant < 5;placementConstant++)
  {
    Delay(60,&finalTicks);
    SetBevelButtonTextPlacement(controlRef,placementConstant);
    Draw1Control(controlRef);
    Draw1Control(windowHeaderRef);
    GetIndString(gCurrentString,rTextPlacementStrings,placementConstant);
    doDrawMessage(windowRef,true);
    QDFlushPortBuffer(GetWindowPort(FrontNonFloatingWindow()),NULL);
  }

  if(!gRunningOnX)
    SetThemeCursor(kThemeArrowCursor);
}

// ***************************************************************************** doDrawMessage

void  doDrawMessage(WindowRef windowRef,Boolean inState)
{
  Rect        portRect;
  CFStringRef stringRef;
  Rect        textBoxRect;

  if(windowRef == gWindowRef)
  {
    SetPortWindowPort(windowRef);

    GetWindowPortBounds(windowRef,&portRect);

    stringRef = CFStringCreateWithPascalString(NULL,gCurrentString,kCFStringEncodingMacRoman);
    SetRect(&textBoxRect,portRect.left,7,portRect.right,22);

    if(inState == kThemeStateActive)
      TextMode(srcOr);
    else
      TextMode(grayishTextOr);

    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,inState,true,&textBoxRect,teJustCenter,
                       NULL);
    if(stringRef != NULL)
      CFRelease(stringRef);
  }
}

// ***************************************************************************** doDrawLegends

void  doDrawLegends(WindowRef windowRef,Boolean inState)
{
  Rect theRect;

  if(windowRef == gWindowRef)
  {
    SetPortWindowPort(windowRef);

    if(gRunningOnX)
    {
      SetRect(&theRect,30,54,585,67);
      EraseRect(&theRect);
      OffsetRect(&theRect,0,91);
      EraseRect(&theRect);
      OffsetRect(&theRect,0,92);
      EraseRect(&theRect);
    }

    if(inState == kThemeStateActive)
      TextMode(srcOr);
    else
      TextMode(grayishTextOr);

    SetRect(&theRect,30,53,220,68);
    if(gRunningOnX)
      DrawThemeTextBox(CFSTR("Bevel button content"),kThemeSmallSystemFont,inState,false,
                       &theRect,teJustLeft,NULL);
    else
      DrawThemeTextBox(CFSTR("Bevel sizes and bevel button content"),kThemeSmallSystemFont,
                       inState,false,&theRect,teJustLeft,NULL);
    SetRect(&theRect,313,53,513,68);
    DrawThemeTextBox(CFSTR("Menu position and behaviour"),kThemeSmallSystemFont,inState,
                     false,&theRect,teJustLeft,NULL);
    SetRect(&theRect,30,144,180,159);
    DrawThemeTextBox(CFSTR("Bevel button behaviour"),kThemeSmallSystemFont,inState,false,
                     &theRect,teJustLeft,NULL);
    SetRect(&theRect,313,144,513,159);
    DrawThemeTextBox(CFSTR("Graphic/text alignment & offset"),kThemeSmallSystemFont,inState,
                     false,&theRect,teJustLeft,NULL);
    SetRect(&theRect,490,144,640,159);
    DrawThemeTextBox(CFSTR("Text placement"),kThemeSmallSystemFont,inState,false,&theRect,
                     teJustLeft,NULL);
    SetRect(&theRect,30,235,180,250);
    DrawThemeTextBox(CFSTR("Image wells"),kThemeSmallSystemFont,inState,false,&theRect,
                     teJustLeft,NULL);
    SetRect(&theRect,168,235,308,250);
    DrawThemeTextBox(CFSTR("Picture controls"),kThemeSmallSystemFont,inState,false,&theRect,
                     teJustLeft,NULL);
    SetRect(&theRect,313,235,463,250);
    DrawThemeTextBox(CFSTR("Icon controls (cicn)"),kThemeSmallSystemFont,inState,false,
                     &theRect,teJustLeft,NULL);
    SetRect(&theRect,451,235,601,250);
    DrawThemeTextBox(CFSTR("Icon controls (icon suite)"),kThemeSmallSystemFont,inState,false,
                     &theRect,teJustLeft,NULL);
  }
}

// **************************************************************** helpTagsBevelImagePictIcon

void  helpTagsBevelImagePictIcon(WindowRef windowRef)
{
  BevelDocStrucHandle bevelDocStrucHdl;
  HMHelpContentRec    helpContent;

  bevelDocStrucHdl = (BevelDocStrucHandle) (GetWRefCon(windowRef));

  memset(&helpContent,0,sizeof(helpContent));
  HMSetTagDelay(500);
  HMSetHelpTagsDisplayed(true);

  helpContent.version = kMacHelpVersion;
  helpContent.tagSide = kHMOutsideTopCenterAligned;
  helpContent.content[kHMMinimumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmResID = 132;

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 1;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton1Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 2;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton2Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 3;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton3Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 4;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton4Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 5;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton5Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 6;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton6Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 7;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton7Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 8;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton8Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 9;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton9Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 10;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton10Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 10;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton11Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 10;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton12Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 11;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton13Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 11;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton14Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 11;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton15Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 12;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton16Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 13;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton17Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 14;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton18Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 15;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton19Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 16;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton20Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 17;
  HMSetControlHelpContent((*bevelDocStrucHdl)->bevelButton21Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 18;
  HMSetControlHelpContent((*bevelDocStrucHdl)->imageWell1Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 19;
  HMSetControlHelpContent((*bevelDocStrucHdl)->imageWell2Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 20;
  HMSetControlHelpContent((*bevelDocStrucHdl)->picture1Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 21;
  HMSetControlHelpContent((*bevelDocStrucHdl)->picture2Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 22;
  HMSetControlHelpContent((*bevelDocStrucHdl)->colourIcon1Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 23;
  HMSetControlHelpContent((*bevelDocStrucHdl)->colourIcon2Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 24;
  HMSetControlHelpContent((*bevelDocStrucHdl)->iconSuite1Ref,&helpContent);

  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 25;
  HMSetControlHelpContent((*bevelDocStrucHdl)->iconSuite2Ref,&helpContent);
}

// *******************************************************************************************
// TabEditClock.c
// *******************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// .......................................................................... global variables

extern Boolean  gRunningOnX;

// **************************************************************************** doTabEditClock

void  doTabEditClock(void)
{
  DialogRef                    dialogRef;
  ControlRef                   controlRef;
  Str255                       initialName = "\pYour name here";
  ControlEditTextSelectionRec  selectionRec;
  ControlKeyFilterUPP          numericFilterUPP;
  ModalFilterUPP               eventFilterUPP;
  ControlEditTextValidationUPP editTextValidatorUPP;
  SInt16                       tabHit, itemHit;

  if(FrontNonFloatingWindow())
    doActivateWindow(FrontNonFloatingWindow(),false);

  if(!(dialogRef = GetNewDialog(rTabEditClockDialog,NULL,(WindowRef) -1)))
    ExitToShell();

  SetWTitle(GetDialogWindow(dialogRef),"\pTab, Edit Text, and Clock Controls");
  SetPortDialogPort(dialogRef);

  // .................................................. set default button and cursor tracking

  SetDialogDefaultItem(dialogRef,kStdOkItemIndex);
  SetDialogTracksCursor(dialogRef,true);

  // ..................................................... hide user pane with embedded clocks

  GetDialogItemAsControl(dialogRef,iClocksUserPane,&controlRef);
  HideControl(controlRef);

  // ............... assign some text to the first edit text control and select the whole text

  GetDialogItemAsControl(dialogRef,iEditText1,&controlRef);
  SetControlData(controlRef,kControlEntireControl,kControlEditTextTextTag,initialName[0],
                 &initialName[1]);
  selectionRec.selStart = 0;
  selectionRec.selEnd = 32767;
  SetControlData(controlRef,kControlEntireControl,kControlEditTextSelectionTag,
                 sizeof(selectionRec),&selectionRec);
                 
  // create universal procedure pointers for event filter, key filter, and edit text validator

  eventFilterUPP        = NewModalFilterUPP((ModalFilterProcPtr) eventFilter);
  numericFilterUPP      = NewControlKeyFilterUPP((ControlKeyFilterProcPtr) numericFilter);
  editTextValidatorUPP  = NewControlEditTextValidationUPP((ControlEditTextValidationProcPtr)
                                                          editTextValidator); 

  // .................. attach an edit text validation function to the first edit text control
  
  GetDialogItemAsControl(dialogRef,iEditText1,&controlRef);
  SetControlData(controlRef,kControlEntireControl,kControlEditTextValidationProcTag,
                 sizeof(editTextValidatorUPP),&editTextValidatorUPP);

// .............................. attach a key filter function to the second edit text control

  GetDialogItemAsControl(dialogRef,iEditText2,&controlRef);
  SetControlData(controlRef,kControlEntireControl,kControlEditTextKeyFilterTag,
                 sizeof(numericFilterUPP),&numericFilterUPP);

  // ................................. set help tags, show dialog, and enter modal dialog loop

  if(gRunningOnX)
    helpTagsTabEditClock(dialogRef);

  ShowWindow(GetDialogWindow(dialogRef));

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);

    if(itemHit == iTabs)
    {
      GetDialogItemAsControl(dialogRef,iTabs,&controlRef);
      tabHit = GetControlValue(controlRef);
      
      if(tabHit == tabEditText)
      {
        SetWTitle(GetDialogWindow(dialogRef),"\pTab, Edit Text, and Clock Controls");

        GetDialogItemAsControl(dialogRef,iClocksUserPane,&controlRef);
        HideControl(controlRef);

        GetDialogItemAsControl(dialogRef,iEditTextUserPane,&controlRef);
        ActivateControl(controlRef);
        ShowControl(controlRef);

        GetDialogItemAsControl(dialogRef,iEditText1,&controlRef);
        SetKeyboardFocus(GetDialogWindow(dialogRef),controlRef,kControlFocusNextPart);
      }
      else if(tabHit == tabClocks)
      {
        SetWTitle(GetDialogWindow(dialogRef),"\pTab, Clock, and Edit Text Controls");

        GetDialogItemAsControl(dialogRef,iEditTextUserPane,&controlRef);
        DeactivateControl(controlRef);
        HideControl(controlRef);

        GetDialogItemAsControl(dialogRef,iClocksUserPane,&controlRef);
        ShowControl(controlRef);

        GetDialogItemAsControl(dialogRef,iClocks1,&controlRef);
        SetKeyboardFocus(GetDialogWindow(dialogRef),controlRef,kControlFocusNextPart);
      }
    }
    else if(itemHit == iExtractEditText)
    {
      GetDialogItemAsControl(dialogRef,iImageWellEditText,&controlRef);
      Draw1Control(controlRef);
      doExtractEditText(dialogRef);
    }
    else if(itemHit == iExtractClocks)
    {
      GetDialogItemAsControl(dialogRef,iImageWellClocks,&controlRef);
      Draw1Control(controlRef);
      doExtractDateTime(dialogRef);
    }
  } while(itemHit != kStdOkItemIndex);

  DisposeDialog(dialogRef);
  DisposeModalFilterUPP(eventFilterUPP);
  DisposeControlKeyFilterUPP(numericFilterUPP);
  DisposeControlEditTextValidationUPP(editTextValidatorUPP);
}

// ************************************************************************* doExtractEditText

void  doExtractEditText(DialogRef dialogRef)
{
  GrafPtr     oldPort;
  RGBColor    saveBackColour, whiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
  SInt16      iType;
  Handle      theHandle;
  Rect        theRect;
  Str255      theString;
  CFStringRef stringRef;
  ControlRef  controlRef;
  Size        actualSize;

  GetPort(&oldPort);
  SetPortDialogPort(dialogRef);
  GetBackColor(&saveBackColour);
  RGBBackColor(&whiteColour);
  
  GetDialogItem(dialogRef,iEditText1,&iType,&theHandle,&theRect);
  GetDialogItemText(theHandle,theString);
  if(!gRunningOnX)
  {
    MoveTo(124,177);
    DrawString(theString);
  }
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,124,166,314,181);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
  }

  GetDialogItem(dialogRef,iEditText2,&iType,&theHandle,&theRect);
  GetDialogItemText(theHandle,theString);
  if(!gRunningOnX)
  {
    MoveTo(124,190);
    DrawString(theString);
  }
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,124,179,314,194);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
  }

  GetDialogItemAsControl(dialogRef,iEditText3,&controlRef);
  GetControlDataSize(controlRef,kControlEditTextPart,kControlEditTextTextTag,&actualSize);
  GetControlData(controlRef,kControlEntireControl,kControlEditTextPasswordTag,actualSize,
                 &theString[1],NULL);
  theString[0] = actualSize;
  if(!gRunningOnX)
  {
    MoveTo(124,203);
    DrawString(theString);
  }
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,124,192,314,207);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
  }

  if(gRunningOnX)
  {
    if(stringRef != NULL)
      CFRelease(stringRef);
  }

  RGBBackColor(&saveBackColour);
  SetPort(oldPort);
}

// ************************************************************************* doExtractDateTime

void  doExtractDateTime(DialogRef dialogRef)
{
  GrafPtr     oldPort;
  RGBColor    saveBackColour, whiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
  ControlRef  controlRef;
  LongDateRec longDateTimeStruc;
  SInt16      second, minute, hour, day, month, year;
  Str255      theString, tempString;
  CFStringRef stringRef;
  Rect        theRect;
    
  GetPort(&oldPort);
  SetPortDialogPort(dialogRef);
  GetBackColor(&saveBackColour);
  RGBBackColor(&whiteColour);

  GetDialogItemAsControl(dialogRef,iClocks1,&controlRef);
  GetControlData(controlRef,kControlEntireControl,kControlClockLongDateTag,
                 sizeof(longDateTimeStruc),&longDateTimeStruc,NULL);
  hour = longDateTimeStruc.ld.hour;
  minute = longDateTimeStruc.ld.minute;
  second = longDateTimeStruc.ld.second;
  doCopyPString("\pHour ",theString);  
  NumToString((SInt32) hour,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Minute ");
  NumToString((SInt32) minute,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Second ");
  NumToString((SInt32) second,tempString);
  doConcatPStrings(theString,tempString);
  MoveTo(124,177);
  if(!gRunningOnX)
    DrawString(theString);
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,124,166,314,181);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
    if(stringRef != NULL)    
      CFRelease(stringRef);
  }
  
  GetDialogItemAsControl(dialogRef,iClocks2,&controlRef);
  GetControlData(controlRef,kControlEntireControl,kControlClockLongDateTag,
                 sizeof(longDateTimeStruc),&longDateTimeStruc,NULL);
  day = longDateTimeStruc.ld.day;
  month = longDateTimeStruc.ld.month;
  year = longDateTimeStruc.ld.year;
  doCopyPString("\pDay ",theString);  
  NumToString((SInt32) day,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Month ");
  NumToString((SInt32) month,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Year ");
  NumToString((SInt32) year,tempString);
  doConcatPStrings(theString,tempString);
  MoveTo(124,190);
  if(!gRunningOnX)
    DrawString(theString);
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,124,179,314,194);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
    if(stringRef != NULL)    
      CFRelease(stringRef);
  }

  GetDialogItemAsControl(dialogRef,iClocks3,&controlRef);
  GetControlData(controlRef,kControlEntireControl,kControlClockLongDateTag,
                 sizeof(longDateTimeStruc),&longDateTimeStruc,NULL);
  month = longDateTimeStruc.ld.month;
  year = longDateTimeStruc.ld.year;
  doCopyPString("\pMonth ",theString);  
  NumToString((SInt32) month,tempString);
  doConcatPStrings(theString,tempString);
  doConcatPStrings(theString,"\p, Year ");
  NumToString((SInt32) year,tempString);
  doConcatPStrings(theString,tempString);
  MoveTo(124,203);
  if(!gRunningOnX)
    DrawString(theString);
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,124,192,314,207);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
    if(stringRef != NULL)    
      CFRelease(stringRef);
  }

  RGBBackColor(&saveBackColour);
  SetPort(oldPort);
}

// ***************************************************************************** numericFilter

ControlKeyFilterResult  numericFilter(ControlRef controlRef,SInt16* keyCode,SInt16 *charCode,
                                      EventModifiers *modifiers)
{
  if(((char) *charCode >= '0') && ((char) *charCode <= '9') || 
     (BitTst(modifiers,15 - cmdKeyBit)))
  {
    return kControlKeyFilterPassKey;
  }

  switch(*charCode)
  {
    case kLeftArrow:
    case kRightArrow:
    case kUpArrow:
    case kDownArrow:
    case kBackspace:
    case kDelete:
      return kControlKeyFilterPassKey;
      break;
  }
    
  SysBeep(10);
  return kControlKeyFilterBlockKey;
}

// ************************************************************************* editTextValidator

void  editTextValidator(ControlRef controlRef)
{
  Str255 oldText, newText;
  Size   actualSize;
  UInt8  a, count = 0;

  GetControlData(controlRef,kControlEntireControl,kControlEditTextTextTag,sizeof(oldText) -1,
                 &oldText[1],&actualSize);

  if(actualSize <= 255)
    oldText[0] = actualSize;
  else
    oldText[0] = 255;
    
  for(a=1;a<=oldText[0];a++)
  {
    if(((oldText[a] >= 'A') && (oldText[a] <= 'Z') ||
        (oldText[a] >= 'a') && (oldText[a] <= 'z')) ||
        (oldText[a] == ' ') || (oldText[a] == '.'))
    {
      newText[count + 1] = oldText[a];
      count++;  
    }
  }

  newText[0] = count;

  SetControlData(controlRef,kControlEntireControl,kControlEditTextTextTag,newText[0],
                 &newText[1]);

  Draw1Control(controlRef);
}

// ********************************************************************** helpTagsTabEditClock

void  helpTagsTabEditClock(DialogRef dialogRef)
{
  HMHelpContentRec helpContent;
  SInt16           a;
  static SInt16    itemNumber[10] = { 2,5,7,9,11,21,14,16,18,20 };
  ControlRef       controlRef;

  memset(&helpContent,0,sizeof(helpContent));
  HMSetTagDelay(500);
  HMSetHelpTagsDisplayed(true);

  helpContent.version = kMacHelpVersion;
  helpContent.tagSide = kHMOutsideTopCenterAligned;
  helpContent.content[kHMMinimumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmResID = 133;

  for(a = 1;a <= 10; a++)
  {
    helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = a;
    GetDialogItemAsControl(dialogRef,itemNumber[a - 1],&controlRef);
    HMSetControlHelpContent(controlRef,&helpContent);
  }
}

// *******************************************************************************************
// GroupArrowsProgress.c
// *******************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// .......................................................................... global variables

ControlRef       gCacheSizeControlRef;
ControlRef       gLittleArrowsControlRef;
ControlActionUPP gArrowsActionFunctionUPP;
extern Boolean   gRunningOnX;
extern Boolean   gGroupArrowsProgressActive;

// ********************************************************************* doGroupArrowsProgress

void  doGroupArrowsProgress(void)
{
  DialogRef      dialogRef;
  ControlRef     controlRef;
  ModalFilterUPP eventFilterUPP;
  SInt16         controlValue, itemHit;
  Str255         theString;

  if(FrontNonFloatingWindow())
    doActivateWindow(FrontNonFloatingWindow(),false);

  if(!(dialogRef = GetNewDialog(rGroupArrowsProgDialog,NULL,(WindowRef) -1)))
    ExitToShell();

  SetPortDialogPort(dialogRef);

  // ........................................................... set default button, help tags

  SetDialogDefaultItem(dialogRef,kStdOkItemIndex);

  // .. create universal procedure pointers for event filter and little arrows action function

  eventFilterUPP            = NewModalFilterUPP((ModalFilterProcPtr) eventFilter);
  gArrowsActionFunctionUPP  = NewControlActionUPP((ControlActionProcPtr) arrowsActionFunction);

  // ................................................ set initial value for checkbox group box

  GetDialogItemAsControl(dialogRef,iCheckboxGroup,&controlRef);
  SetControlValue(controlRef,1);

  // ....................................... get and set initial cache value for little arrows

  GetDialogItemAsControl(dialogRef,iLittleArrows,&gLittleArrowsControlRef);
  NumToString((SInt32) GetControlValue(gLittleArrowsControlRef),theString);
  doConcatPStrings(theString,"\pK");
  GetDialogItemAsControl(dialogRef,iStaticTextCache,&gCacheSizeControlRef);
  SetControlData(gCacheSizeControlRef,kControlEntireControl,kControlStaticTextTextTag,
                 theString[0],&theString[1]);

  // ............................................... hide second user pane in pop-up group box

  GetDialogItemAsControl(dialogRef,iUserPaneScoreAverage,&controlRef);
  HideControl(controlRef);

  // .................................. set help tags, show dialog, and enter ModalDialog loop

  if(gRunningOnX)
    helpTagsGroupArrowsProgress(dialogRef);

  ShowWindow(GetDialogWindow(dialogRef));

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);

    if(itemHit == iCheckboxGroup)
    {
      doCheckBoxGroupBox(dialogRef);
    }    
    else if(itemHit == iPopupGroup)
    {
      doPopupGroupBox(dialogRef);
    }
    else if(itemHit == iCheckboxShowInitials)
    {
      GetDialogItemAsControl(dialogRef,iCheckboxShowInitials,&controlRef);
      controlValue = (!(GetControlValue(controlRef)));
      SetControlValue(controlRef,controlValue);
    }
    else if(itemHit == iCheckboxShowAverages)
    {
      GetDialogItemAsControl(dialogRef,iCheckboxShowAverages,&controlRef);
      controlValue = (!(GetControlValue(controlRef)));
      SetControlValue(controlRef,controlValue);
    }
    else if(itemHit == iDisclosureTriangle)
    {
      doChasingAndProgress(dialogRef);
    }
    else if(itemHit == iPushButtonExtract)
    {
      GetDialogItemAsControl(dialogRef,iImageWell,&controlRef);
      Draw1Control(controlRef);
      doExtractCurrentStatus(dialogRef);
    }
  } while(itemHit != kStdOkItemIndex);

  // ................................................................................ clean up

  DisposeDialog(dialogRef);
  DisposeModalFilterUPP(eventFilterUPP);
  DisposeControlActionUPP(gArrowsActionFunctionUPP);

  gGroupArrowsProgressActive = false;
}

// ************************************************************************ doCheckBoxGroupBox

void  doCheckBoxGroupBox(DialogRef dialogRef)
{
  ControlRef controlRef;
  SInt16     controlValue;

  GetDialogItemAsControl(dialogRef,iCheckboxGroup,&controlRef);
  controlValue = (!(GetControlValue(controlRef)));
  SetControlValue(controlRef,controlValue);
  
  if(controlValue == 0)
  {
    GetDialogItemAsControl(dialogRef,iRadioGroupColour,&controlRef);
    DeactivateControl(controlRef);  
    GetDialogItemAsControl(dialogRef,iStaticTextColourDepth,&controlRef);
    DeactivateControl(controlRef);  
  }
  else if(controlValue == 1)
  {
    GetDialogItemAsControl(dialogRef,iRadioGroupColour,&controlRef);
    ActivateControl(controlRef);  
    GetDialogItemAsControl(dialogRef,iStaticTextColourDepth,&controlRef);
    ActivateControl(controlRef);  
  }
}

// *************************************************************************** doPopupGroupBox

void  doPopupGroupBox(DialogRef dialogRef)
{
  ControlRef controlRef;
  SInt16     controlValue;

  GetDialogItemAsControl(dialogRef,iPopupGroup,&controlRef);
  controlValue = GetControlValue(controlRef);

  if(controlValue == 1)
  {
    GetDialogItemAsControl(dialogRef,iUserPaneScoreAverage,&controlRef);
    HideControl(controlRef);
    GetDialogItemAsControl(dialogRef,iUserPaneNamesInitials,&controlRef);
    ShowControl(controlRef);
  }
  else if(controlValue == 2)
  {
    GetDialogItemAsControl(dialogRef,iUserPaneNamesInitials,&controlRef);
    HideControl(controlRef);
    GetDialogItemAsControl(dialogRef,iUserPaneScoreAverage,&controlRef);
    ShowControl(controlRef);
  }
}

// ********************************************************************** doChasingAndProgress

void  doChasingAndProgress(DialogRef dialogRef)
{
  ControlRef controlRef;
  SInt16     controlValue;
  Handle     ditlHdl;
  Boolean    indeterminateFlag = 1;
  Str255     expandString   = "\pHide Progress Bar and Chasing Arrows";
  Str255     collapseString = "\pShow Progress Bar and Chasing Arrows";

  GetDialogItemAsControl(dialogRef,iDisclosureTriangle,&controlRef);
  controlValue = (!(GetControlValue(controlRef)));
  SetControlValue(controlRef,controlValue);

  if(controlValue == 1)
  {
    ditlHdl = GetResource('DITL',130);
    AppendDITL(dialogRef,ditlHdl,appendDITLBottom);
    ReleaseResource(ditlHdl);

    GetDialogItemAsControl(dialogRef,iProgressBar,&controlRef);
    SetControlData(controlRef,kControlEntireControl,kControlProgressBarIndeterminateTag,
                   sizeof(indeterminateFlag),&indeterminateFlag);

    GetDialogItemAsControl(dialogRef,kStdOkItemIndex,&controlRef);
    MoveControl(controlRef,277,351);
    
    GetDialogItemAsControl(dialogRef,iStaticTextDisclosure,&controlRef);
    SetControlData(controlRef,kControlEntireControl,kControlStaticTextTextTag,
                   expandString[0],&expandString[1]);
    Draw1Control(controlRef);
  }
  else if(controlValue == 0)
  {
    GetDialogItemAsControl(dialogRef,kStdOkItemIndex,&controlRef);
    MoveControl(controlRef,277,280);

    ShortenDITL(dialogRef,3);
    SizeWindow(GetDialogWindow(dialogRef),362,321,false);

    GetDialogItemAsControl(dialogRef,iStaticTextDisclosure,&controlRef);
    SetControlData(controlRef,kControlEntireControl,kControlStaticTextTextTag,
                   collapseString[0],&collapseString[1]);
    Draw1Control(controlRef);
  }
}

// ******************************************************************** doExtractCurrentStatus

void  doExtractCurrentStatus(DialogRef dialogRef)
{
  GrafPtr     oldPort;
  RGBColor    saveBackColour, whiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
  ControlRef  controlRef;
  SInt16      controlValue;
  Str255      theString;
  CFStringRef stringRef;
  Rect        theRect;

  GetPort(&oldPort);
  SetPortDialogPort(dialogRef);
  GetBackColor(&saveBackColour);
  RGBBackColor(&whiteColour);

  GetDialogItemAsControl(dialogRef,iCheckboxGroup,&controlRef);
  controlValue = GetControlValue(controlRef);  
  if(controlValue)
  {
    doCopyPString("\pUse colour,",theString);
    GetDialogItemAsControl(dialogRef,iRadioGroupColour,&controlRef);
    controlValue = GetControlValue(controlRef);
    if(controlValue == 1)
      doConcatPStrings(theString,"\p 8 bit.");
    else if(controlValue == 2)
      doConcatPStrings(theString,"\p 16 bit.");
    else if(controlValue == 3)
      doConcatPStrings(theString,"\p 32 bit.");
  }
  else
    doCopyPString("\pDont use colour.",theString);

  if(!gRunningOnX)
  {
    MoveTo(108,216);
    DrawString(theString);
  }
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,108,205,347,220);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
    if(stringRef != NULL)    
      CFRelease(stringRef);
  }

  GetDialogItemAsControl(dialogRef,iPopupGroup,&controlRef);
  controlValue = GetControlValue(controlRef);  
  if(controlValue == 1)
  {
    doCopyPString("\pPlayer, ",theString);
    GetDialogItemAsControl(dialogRef,iRadioGroupNames,&controlRef);
    controlValue = GetControlValue(controlRef);
    if(controlValue == 1)
      doConcatPStrings(theString,"\pname first,");
    else if(controlValue == 2)
      doConcatPStrings(theString,"\pname last,");
    GetDialogItemAsControl(dialogRef,iCheckboxShowInitials,&controlRef);
    controlValue = GetControlValue(controlRef);
    if(controlValue == 1)
      doConcatPStrings(theString,"\p show number.");
    else if(controlValue == 0)
      doConcatPStrings(theString,"\p no number.");
  }
  else if(controlValue == 2)
  {
    doCopyPString("\pScore, ",theString);
    GetDialogItemAsControl(dialogRef,iRadioGroupScores,&controlRef);
    controlValue = GetControlValue(controlRef);
    if(controlValue == 1)
      doConcatPStrings(theString,"\pbatting, ");
    else if(controlValue == 2)
      doConcatPStrings(theString,"\pbowling, ");
    GetDialogItemAsControl(dialogRef,iCheckboxShowAverages,&controlRef);
    controlValue = GetControlValue(controlRef);
    if(controlValue == 1)
      doConcatPStrings(theString,"\pshow average.");
    else if(controlValue == 0)
      doConcatPStrings(theString,"\pno average.");
  }

  if(!gRunningOnX)
  {
    MoveTo(108,229);
    DrawString(theString);
  }
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,108,219,347,234);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
    if(stringRef != NULL)    
      CFRelease(stringRef);
  }

  if(!gRunningOnX)
  {
    MoveTo(108,242);      
    DrawString("\pCache size: ");
  }
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,"\pCache size: ",
                                               kCFStringEncodingMacRoman);
    SetRect(&theRect,108,232,347,247);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
    if(stringRef != NULL)    
      CFRelease(stringRef);
  }

  GetDialogItemAsControl(dialogRef,iLittleArrows,&controlRef);
  NumToString((SInt32) GetControlValue(controlRef),theString);
  if(!gRunningOnX)
    DrawString(theString);
  else
  {
    stringRef = CFStringCreateWithPascalString(NULL,theString,kCFStringEncodingMacRoman);
    SetRect(&theRect,174,232,347,247);
    DrawThemeTextBox(stringRef,kThemeSmallSystemFont,true,false,&theRect,teJustLeft,NULL);
    if(stringRef != NULL)    
      CFRelease(stringRef);
  }

  RGBBackColor(&saveBackColour);
  SetPort(oldPort);
}

// *************************************************************** helpTagsGroupArrowsProgress

void  helpTagsGroupArrowsProgress(DialogRef dialogRef)
{
  HMHelpContentRec helpContent;
  SInt16           a;
  static SInt16    itemNumber[8] = { 2,9,21,25,27,29,31,32 };
  ControlRef       controlRef;

  memset(&helpContent,0,sizeof(helpContent));
  HMSetTagDelay(500);
  HMSetHelpTagsDisplayed(true);

  helpContent.version = kMacHelpVersion;
  helpContent.tagSide = kHMOutsideTopCenterAligned;
  helpContent.content[kHMMinimumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmResID = 134;

  for(a = 1;a <= 8; a++)
  {
    helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = a;
    GetDialogItemAsControl(dialogRef,itemNumber[a - 1],&controlRef);
    HMSetControlHelpContent(controlRef,&helpContent);
  }
}

// *******************************************************************************************
// Sliders.c
// *******************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// .......................................................................... global variables

extern Boolean gRunningOnX;

// .......................................................................... global variables

ControlActionUPP           gSliderActionFunction1UPP;
ControlActionUPP           gSliderActionFunction2UPP;
ControlUserPaneDrawUPP     gUserPaneDrawFunctionUPP;
ControlUserPaneActivateUPP gUserPaneActivateFunctionUPP;
ControlRef                 gSlider1Ref;
ControlRef                 gSlider2Ref;
ControlRef                 gSlider3Ref;
ControlRef                 gSlider4Ref;
ControlRef                 gSlider5Ref;
ControlRef                 gSlider6Ref;
RGBColor                   gRedColour;
RGBColor                   gBlueColour;
RGBColor                   gBlackColour   = { 0x0000, 0x0000, 0x0000 };
Boolean                    gDrawActivated = true;
extern Boolean             gSlidersActive;

// ************************************************************************** doSliderUserPane

void  doSliderUserPane(void)
{
  DialogRef      dialogRef;
  ModalFilterUPP eventFilterUPP;
  ControlRef     controlRef;
  SInt16         itemHit;

  if(FrontNonFloatingWindow())
    doActivateWindow(FrontNonFloatingWindow(),false);

  if(!(dialogRef = GetNewDialog(rSlidersDialog,NULL,(WindowRef) -1)))
    ExitToShell();

  // ...................................................................... set default button

  SetDialogDefaultItem(dialogRef,kStdOkItemIndex);

  // ............................ create universal procedure pointer for event filter function

  eventFilterUPP = NewModalFilterUPP((ModalFilterProcPtr) eventFilter);

  // ......................... create universal procedure pointers for slider action functions

  gSliderActionFunction1UPP = NewControlActionUPP((ControlActionProcPtr)
                              sliderActionFunction1);
  gSliderActionFunction2UPP = NewControlActionUPP((ControlActionProcPtr) 
                              sliderActionFunction2);

  // .... create universal procedure pointers for user pane functions, set user pane functions

  gUserPaneDrawFunctionUPP = NewControlUserPaneDrawUPP((ControlUserPaneDrawProcPtr)
                                                       userPaneDrawFunction);
  GetDialogItemAsControl(dialogRef,iUserPane1,&controlRef);
  SetControlData(controlRef,kControlEntireControl,kControlUserPaneDrawProcTag, 
                 sizeof(gUserPaneDrawFunctionUPP),&gUserPaneDrawFunctionUPP);

  gUserPaneActivateFunctionUPP = NewControlUserPaneActivateUPP((ControlUserPaneActivateProcPtr)
                                                               userPaneActivateFunction);
  GetDialogItemAsControl(dialogRef,iUserPane1,&controlRef);
  SetControlData(controlRef,kControlEntireControl,kControlUserPaneActivateProcTag, 
                 sizeof(gUserPaneActivateFunctionUPP),&gUserPaneActivateFunctionUPP);

  // ........... get control handles of, and draw initial control values for, top four sliders
  
  GetDialogItemAsControl(dialogRef,iSlider1,&gSlider1Ref);
  doDrawSliderValues(dialogRef,gSlider1Ref);
  GetDialogItemAsControl(dialogRef,iSlider2,&gSlider2Ref);
  doDrawSliderValues(dialogRef,gSlider2Ref);
  GetDialogItemAsControl(dialogRef,iSlider3,&gSlider3Ref);
  doDrawSliderValues(dialogRef,gSlider3Ref);
  GetDialogItemAsControl(dialogRef,iSlider4,&gSlider4Ref);
  doDrawSliderValues(dialogRef,gSlider4Ref);

  // ....................... get control handles and values for bottom two sliders, set colour

  GetDialogItemAsControl(dialogRef,iSlider5,&gSlider5Ref);
  gRedColour.red = 2 * GetControlValue(gSlider5Ref);
  GetDialogItemAsControl(dialogRef,iSlider6,&gSlider6Ref);
  gBlueColour.blue = 2 * GetControlValue(gSlider5Ref);

  // .................................. set help tags, show dialog, and enter ModalDialog loop

  if(gRunningOnX)
    helpTagsSliders(dialogRef);

  ShowWindow(GetDialogWindow(dialogRef));

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);
  } while(itemHit != kStdOkItemIndex);

  // ................................................................................ clean up

  DisposeDialog(dialogRef);
  DisposeModalFilterUPP(eventFilterUPP);
  DisposeControlActionUPP(gSliderActionFunction1UPP);
  DisposeControlActionUPP(gSliderActionFunction2UPP);
  DisposeControlUserPaneDrawUPP(gUserPaneDrawFunctionUPP);
  DisposeControlUserPaneActivateUPP(gUserPaneActivateFunctionUPP);
  gSlidersActive = false;
}

// ************************************************************************ doDrawSliderValues

void  doDrawSliderValues(DialogRef dialogRef,ControlRef controlRef)
{
  Str255  theString;
  SInt16  staticTextItem;

  NumToString((SInt32) GetControlValue(controlRef),theString);

  if(controlRef == gSlider1Ref)
    staticTextItem = iSlider1StaticText;
  else if(controlRef == gSlider2Ref)
    staticTextItem = iSlider2StaticText;
  else if(controlRef == gSlider3Ref)
    staticTextItem = iSlider3StaticText;
  else if(controlRef == gSlider4Ref)
    staticTextItem = iSlider4StaticText;

  GetDialogItemAsControl(dialogRef,staticTextItem,&controlRef);
  SetControlData(controlRef,kControlEntireControl,kControlStaticTextTextTag,theString[0],
                 &theString[1]);
  Draw1Control(controlRef);
}

// ********************************************************************** userPaneDrawFunction

void  userPaneDrawFunction(ControlRef theControl,SInt16 thePart)
{
  Rect theRect;

  SetRect(&theRect,218,175,238,195);
  DrawThemePlacard(&theRect,gDrawActivated);
  InsetRect(&theRect,2,2);

  if(gDrawActivated)
  {
    RGBForeColor(&gRedColour);
    PaintRect(&theRect);
  }

  SetRect(&theRect,218,196,238,216);
  DrawThemePlacard(&theRect,gDrawActivated);
  InsetRect(&theRect,2,2);

  if(gDrawActivated)
  {
    RGBForeColor(&gBlueColour);
    PaintRect(&theRect);
  }

 }

// ****************************************************************** userPaneActivateFunction

void  userPaneActivateFunction(ControlRef control,Boolean activating)
{
  if(activating)
    gDrawActivated = true;
  else
    gDrawActivated = false;
}

// *************************************************************************** helpTagsSliders

void  helpTagsSliders(DialogRef dialogRef)
{
  HMHelpContentRec helpContent;
  SInt16           a;
  static SInt16    itemNumber[7] = { 2,3,4,5,17,19,18 };
  ControlRef       controlRef;

  memset(&helpContent,0,sizeof(helpContent));
  HMSetTagDelay(500);
  HMSetHelpTagsDisplayed(true);

  helpContent.version = kMacHelpVersion;
  helpContent.tagSide = kHMOutsideTopCenterAligned;
  helpContent.content[kHMMinimumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmResID = 135;

  for(a = 1;a <= 7; a++)
  {
    helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = a;
    GetDialogItemAsControl(dialogRef,itemNumber[a - 1],&controlRef);
    HMSetControlHelpContent(controlRef,&helpContent);
  }
}

// *******************************************************************************************
// TextBox.c
//********************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// ********************************************************************************* doTextBox

void  doTextBox(void)
{
  DialogRef      dialogRef;
  ModalFilterUPP eventFilterUPP;
  SInt16         itemHit;

  if(FrontNonFloatingWindow())
    doActivateWindow(FrontNonFloatingWindow(),false);

  if(!(dialogRef = GetNewDialog(rAboutDialog,NULL,(WindowRef) -1)))
    ExitToShell();

  // ...................................................................... set default button

  SetDialogDefaultItem(dialogRef,kStdOkItemIndex);
  
  // ..................................... create universal procedure pointer for event filter

  eventFilterUPP = NewModalFilterUPP((ModalFilterProcPtr) eventFilter);

  // ................................................. show dialog and enter modal dialog loop

  ShowWindow(GetDialogWindow(dialogRef));

  do
  {
    ModalDialog(eventFilterUPP,&itemHit);
  } while(itemHit != kStdOkItemIndex);

  DisposeDialog(dialogRef);
  DisposeModalFilterUPP(eventFilterUPP);
}

// *******************************************************************************************
// Callbacks.c
//********************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// .......................................................................... global variables

extern Boolean          gGroupArrowsProgressActive;
extern Boolean          gSlidersActive;
extern ControlActionUPP gArrowsActionFunctionUPP;
extern ControlActionUPP gSliderActionFunction1UPP;
extern ControlActionUPP gSliderActionFunction2UPP;
extern ControlRef       gLittleArrowsControlRef;
extern ControlRef       gCacheSizeControlRef;
extern ControlRef       gSlider1Ref;
extern ControlRef       gSlider2Ref;
extern ControlRef       gSlider3Ref;
extern ControlRef       gSlider4Ref;
extern ControlRef       gSlider5Ref;
extern ControlRef       gSlider6Ref;
extern RGBColor         gRedColour;
extern RGBColor         gBlueColour;
extern RGBColor         gBlackColour;

// ******************************************************************************* eventFilter

Boolean  eventFilter(DialogRef dialogRef,EventRecord *eventStrucPtr,SInt16 *itemHit)
{
  Boolean    handledEvent;
  GrafPtr    oldPort;
  Point      mouseXY;
  ControlRef controlRef;

  handledEvent = false;

  if((eventStrucPtr->what == updateEvt) && 
     ((WindowRef) eventStrucPtr->message != GetDialogWindow(dialogRef)))
  {
    doUpdate(eventStrucPtr);
  }
  else if((eventStrucPtr->what == autoKey) && ((eventStrucPtr->modifiers & cmdKey) != 0))
  {
    handledEvent = true;
    return handledEvent;
  }
  else
  {
    GetPort(&oldPort);
    SetPortDialogPort(dialogRef);

    if(gGroupArrowsProgressActive)
    {
      if(eventStrucPtr->what == mouseDown)
      {
        mouseXY = eventStrucPtr->where;
        GlobalToLocal(&mouseXY);
        if(FindControl(mouseXY,GetDialogWindow(dialogRef),&controlRef))
        {
          if(controlRef == gLittleArrowsControlRef)
          {
            TrackControl(controlRef,mouseXY,gArrowsActionFunctionUPP);
            handledEvent = true;
          }
        }
      }
    }
    else if(gSlidersActive)
    {
      if(eventStrucPtr->what == mouseDown)
      {
        mouseXY = eventStrucPtr->where;
        GlobalToLocal(&mouseXY);
        if(FindControl(mouseXY,GetDialogWindow(dialogRef),&controlRef))
        {
          if(controlRef == gSlider1Ref || controlRef == gSlider2Ref)
          {
            TrackControl(controlRef,mouseXY,NULL);
            doDrawSliderValues(dialogRef,controlRef);
            handledEvent = true;
          }
          else if(controlRef == gSlider3Ref || controlRef == gSlider4Ref)
          {
            TrackControl(controlRef,mouseXY,gSliderActionFunction1UPP);
            handledEvent = true;
          }
          else if(controlRef == gSlider5Ref || controlRef == gSlider6Ref)
          {
            TrackControl(controlRef,mouseXY,gSliderActionFunction2UPP);
            handledEvent = true;
          }
        }
      }
    }
    else
    {
      handledEvent = StdFilterProc(dialogRef,eventStrucPtr,itemHit);
    }

    SetPort(oldPort);
  }

  return handledEvent;
}

// ********************************************************************** arrowsActionFunction

void  arrowsActionFunction(ControlRef controlRef,SInt16 partCode)
{
  Str255 theString;
  SInt32 controlValue;

  if(partCode)
  {
    controlValue = GetControlValue(controlRef);

    switch(partCode)
    {
      case kControlUpButtonPart:
        controlValue += 32;
        if(controlValue > GetControlMaximum(controlRef))
        {
          controlValue = GetControlMaximum(controlRef);
          return;
        }
      break;
      
      case kControlDownButtonPart:
        controlValue -= 32;
        if(controlValue < GetControlMinimum(controlRef))
        {
          controlValue = GetControlMinimum(controlRef);
          return;
        }
        break;
    }

    SetControlValue(controlRef,controlValue);

    NumToString((SInt32) controlValue,theString);
    doConcatPStrings(theString,"\pK");
    SetControlData(gCacheSizeControlRef,kControlEntireControl,kControlStaticTextTextTag,
                   theString[0],&theString[1]);
    Draw1Control(gCacheSizeControlRef);
  }
}

// ********************************************************************* sliderActionFunction1

void  sliderActionFunction1(ControlRef controlRef,SInt16 partCode)
{
  SInt16    staticTextItem;
  Str255    theString;
  DialogRef dialogRef;

  NumToString((SInt32) GetControlValue(controlRef),theString);

  dialogRef = GetDialogFromWindow(GetControlOwner(controlRef));

  if(controlRef == gSlider3Ref)
    staticTextItem = iSlider3StaticText;
  else if(controlRef == gSlider4Ref)
    staticTextItem = iSlider4StaticText;

  GetDialogItemAsControl(dialogRef,staticTextItem,&controlRef);
  SetControlData(controlRef,kControlEntireControl,kControlStaticTextTextTag,theString[0],
                 &theString[1]);
  Draw1Control(controlRef);
}

// ********************************************************************* sliderActionFunction2

void  sliderActionFunction2(ControlRef controlRef,SInt16 partCode)
{
  SInt16 controlValue;
  Rect   theRect;

  controlValue = GetControlValue(controlRef);

  if(controlRef == gSlider5Ref)
  {
    gRedColour.red = 2 * controlValue;
    RGBForeColor(&gRedColour);
    SetRect(&theRect,220,177,236,193);
  }
  else if(controlRef == gSlider6Ref)
  {
    gBlueColour.blue = 2 * controlValue;
    RGBForeColor(&gBlueColour);
    SetRect(&theRect,220,198,236,214);
  }
  
  PaintRect(&theRect);
  RGBForeColor(&gBlackColour);
}

// *******************************************************************************************
// SmallControls.c
//********************************************************************************************

// .................................................................................. includes

#include "Controls3.h"

// *************************************************************************** doSmallControls

void  doSmallControls(void)
{
  OSStatus            osError;
  Str255              pascalString;
  CFStringRef         stringRef;
  Rect                contentRect        = {   0,  0,388,175 };
  Rect                staticTextRect     = {   8, 20, 86,144 };
  Rect                vertScrollBarRect  = {  -1,164,378,175 };
  Rect                horizScrollBarRect = { 377, -1,388,165 };
  Rect                tabRect            = { 106, 20,144,144 };
  Rect                sliderRect         = { 164, 20,182,145 };
  Rect                radioButtonRect    = { 200, 23,216,144 };
  Rect                checkBoxRect       = { 220, 23,236,144 };
  Rect                editTextRect       = { 300, 26,313,139 };
  Rect                pushButtonRect     = { 338, 21,356,144 };
  WindowRef           windowRef;
  ControlFontStyleRec controlFontStyleStruc;
  ControlRef          controlRef;
  ControlSize         controlSize = kControlSizeSmall;
  ControlTabEntry     tabArray[2];

  if(!(osError = CreateNewWindow(kFloatingWindowClass,kWindowStandardFloatingAttributes + 
                                 kWindowResizableAttribute,&contentRect,
                                 &windowRef)))
  {
    ChangeWindowAttributes(windowRef,0,kWindowCloseBoxAttribute);
    RepositionWindow(windowRef,NULL,kWindowAlertPositionOnMainScreen);
    SetThemeWindowBackground(windowRef,kThemeBrushDialogBackgroundActive,false);
    SetPortWindowPort(windowRef);
    UseThemeFont(kThemeSmallSystemFont,smSystemScript);
    ShowWindow(windowRef);
  }
  else
  {
    SysBeep(10);
    return;
  }

  GetIndString(pascalString,rSmallControlsString,1);
  stringRef = CFStringCreateWithPascalString(NULL,pascalString,kCFStringEncodingMacRoman);
  
  controlFontStyleStruc.flags = kControlUseFontMask | kControlUseJustMask;
  controlFontStyleStruc.font   = kControlFontSmallSystemFont;
  controlFontStyleStruc.just  = teJustCenter;

  CreateStaticTextControl(windowRef,&staticTextRect,stringRef,&controlFontStyleStruc,
                          &controlRef);

  // ............................................................................. scroll bars
  
  if((osError = CreateScrollBarControl(windowRef,&vertScrollBarRect,0,0,200,200,false,NULL,
                                       &controlRef)) == noErr)
    SetControlData(controlRef,kControlEntireControl,kControlSizeTag,sizeof(controlSize),
                   &controlSize);

  if((osError = CreateScrollBarControl(windowRef,&horizScrollBarRect,0,0,300,300,false,NULL,
                                       &controlRef)) == noErr)
    SetControlData(controlRef,kControlEntireControl,kControlSizeTag,sizeof(controlSize),
                   &controlSize);

  // ..................................................................................... tab

  tabArray[0].icon = tabArray[1].icon = NULL;
  tabArray[0].name = CFSTR("Tab 1");
  tabArray[1].name = CFSTR("Tab 2");
  tabArray[0].enabled = tabArray[1].enabled = true;

  CreateTabsControl(windowRef,&tabRect,kControlTabSizeSmall,kControlTabDirectionSouth,2,
                    tabArray,&controlRef);

  // .................................................................................. slider
  
  if((osError = CreateSliderControl(windowRef,&sliderRect,0,0,100,
                                    kControlSliderPointsDownOrRight,5,false,NULL,
                                    &controlRef)) == noErr)
    SetControlData(controlRef,kControlEntireControl,kControlSizeTag,sizeof(controlSize),
                   &controlSize);

  // ............................................................................ radio button

  if((osError = CreateRadioButtonControl(windowRef,&radioButtonRect,
                                         CFSTR("Small Radio Button"),1,false,
                                         &controlRef)) == noErr)
  {
    SetControlData(controlRef,kControlEntireControl,kControlSizeTag,sizeof(controlSize),
                   &controlSize);
    SetControlFontStyle(controlRef,&controlFontStyleStruc);
  }

  // ................................................................................ checkbox

  if((osError = CreateCheckBoxControl(windowRef,&checkBoxRect,CFSTR("Small Checkbox"),1,false,
                                      &controlRef)) == noErr)
  {
    SetControlData(controlRef,kControlEntireControl,kControlSizeTag,sizeof(controlSize),
                   &controlSize);
    SetControlFontStyle(controlRef,&controlFontStyleStruc);
  }

  // ...................................................................... pop-up menu button

  if(controlRef = GetNewControl(cSmallPopup,windowRef))
    SetControlValue(controlRef,3);
  
  // ............................................................................... edit text

  if((osError = CreateEditTextControl(windowRef,&editTextRect,CFSTR("Small Edit Text"),false,
                                      false,&controlFontStyleStruc,&controlRef)) == noErr)
    SetKeyboardFocus(windowRef,controlRef,kControlFocusNextPart);

  // ............................................................................. push button

  if((osError = CreatePushButtonControl(windowRef,&pushButtonRect,CFSTR("Small Push Button"),
                                        &controlRef)) == noErr)
    SetControlFontStyle(controlRef,&controlFontStyleStruc);
}

// ****************************************************************** doMouseDownSmallControls

void  doMouseDownSmallControls(WindowRef windowRef,EventRecord *eventStrucPtr)
{
  SInt16      controlPartCode;
  ControlRef  controlRef = NULL;
  ControlKind controlKind;

  SetPortWindowPort(windowRef);
  GlobalToLocal(&eventStrucPtr->where);
  controlPartCode = FindControl(eventStrucPtr->where,windowRef,&controlRef);
  if(controlPartCode)
    TrackControl(controlRef,eventStrucPtr->where,NULL);
  
  if(controlRef)
  {
    GetControlKind(controlRef,&controlKind);
    if((controlKind.kind == kControlKindRadioButton) || 
        controlKind.kind == kControlKindCheckBox)
      SetControlValue(controlRef,!GetControlValue(controlRef));
  }
}

// *******************************************************************************************

Demonstration Program Controls3 Comments

When this program is run, the user should:

o Choose items from the Demonstration menu to view and operate the various controls.  (Note
  that the Small Controls item is only available when the program is run on Mac OS X.)

o On Mac OS 8/9, choose Show Balloons from the Help menu and note the information in the help
  balloons as the cursor is moved over the various controls.

o On Mac OS X, hover the cursor over the various controls and note the information in the help
  tags.

o Click in the Finder and then back in the window/dialog, noting control
  activation/deactivation.

o In the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window:

  o Click in the various controls, noting in the window header the control part code returned
    by FindControl (or immediately by TrackControl in the case of the non-tracking icon 
    controls).

  o Click in the various controls and then release the mouse button both within and outside the
    control, noting the control part code returned by TrackControl.

o In the Tab, Edit Text, and Clock Controls dialog:

  o In the Edit Text Controls tab:

    o Change the keyboard focus using the tab key and mouse clicks.

    o Enter a name, age, and password, noting the effect of the key filter function attached to
      the "Age" edit text control and the behaviour of the "Password" edit text control.

    o Paste some text containing characters other than alphabetic characters, the space
      character, and the period character to the "Name" edit text control, noting that the edit
      text validation function strips out the "illegal" characters.

    o Note the cursor shape change when the cursor is over the top two edit text controls.

    o Click the Extract push button to extract and display the contents of the edit text
      controls.

o In the Clock Controls Tab:

  o Change the keyboard focus using the tab key and mouse clicks.

  o Change the clock setting by typing and by using the integral little arrows.

  o Click the Extract push button to extract and display the clock settings.

o In the Group Boxes, Arrows, and Progress Bar dialog:

  o Change the group box settings, the settings of the controls within the group boxes, and the
    (simulated) cache size setting controlled by the little arrows, and then click the Extract
    button to extract and display the settings of the various controls.

  o Click the disclosure triangle to show and hide the chasing arrows and indeterminate 
    progress bar.

o In the Sliders and User Pane Functions dialog:

  o Operate the sliders and note the difference in the appearance of the dragged indicator in 
    the live scrolling and non-live scrolling variants of the sliders.

  o Note the appearance, in the activated and deactivated modes, of the two custom "controls"
    to the right of the two horizontal sliders.  Also note that these controls are re-drawn, in
    the appropriate mode, when an overlaying window or help balloon is removed (Mac OS 8/9).

o In the Text Boxes dialog, observe the auto scrolling variant and scroll the
  non-auto-scrolling variant.

o On Mac OS X, observe the small controls in the Small Controls floating window.

Control3.h

defines

Constants are established for the resource IDs and dialog item numbers associated with the
various demonstrations.

typedefs

A variable of type BevelDocStruc will be used to hold references to the various controls
created in the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window.

Control3.c

Controls3.c is simply the basic "engine" which supports the demonstration.  There is nothing in
this file which has not featured in previous demonstration programs.

doMouseDown

In the inContent case, if a mouse-down occurs in the Bevel Buttons, Image Wells, Picture
Controls, and Icon Controls window when it is the front window, the function
doBevelImagePictIconContent is called.

In the inGoAway case, the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls
window is disposed of.

doUpdate

If the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window is open,
UpdateControls is called to redraw the controls in the appropriate mode.

doActivateWindow

If the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls window is open, and if
it receives an activate event, GetRootControl is called to get a reference to the window's root
control.  The controls are then activated or deactivated en masse.

BevelImagePictIcon.c

BevelImagePictIcon.c contains most of the source code relating to the Bevel Buttons, Image
Wells, Picture Controls, and Icon Controls window.

doBevelImagePictIcon

doBevelImagePictIcon opens a window, creates a relocatable block for a structure of type
BevelDocStruc (to whose fields references to the various controls will be assigned) and stores
the handle to this block in the window object.

The call to GetNewCWindow then creates the window.  (Note that error handling here and in other
areas of the demonstration is somewhat rudimentary in that the program simply terminates.) 
NewHandle creates the block for the variable of type BevelDocStruc and SetWRefCon stores the
handle to the block as a reference constant in the window object.

Before ShowWindow is called to make the window visible, the function doGetControls is called to
create the controls.

doGetControls

doGetControls creates the controls from the various 'CNTL' resources.
At the first line, if the program is running on Mac OS 8/9, CreateRootControl is called to create a root control for the window. On Mac OS 8/9, the first control created must be always be the root control (which is implemented as a user pane). This call is not necessary on Mac OS X because, on Mac OS X, root controls are created automatically for windows which have at least one control. A handle to the structure in which the reference to the control objects will be stored is then retrieved. The following calls to GetNewControl create a control object for each control, insert the reference to the object into the control list for the specified window and draw the control. At the same time, the reference to each control object is assigned to the appropriate field of the window's "document" structure. At the next block, if the program is running on Mac OS X, SetControlData is called to make the first four bevel button's corners rounded. (Mac OS X bevel buttons have square corners by default.) At the next block, SetControlData is called twice to cause the text in the specified bevel buttons to be placed above the graphic. At the next block, SetControlData is called to cause the pop-up glyph in the specified bevel button to be centred. At the next block, the font for the text in the specified bevel button is changed. The flags and font fields of a control font style structure are assigned constants so that the following call to SetControlFontStyle will set the font to the small emphasised system font. The final line sets the value of the specified bevel button to 2, causing it to appear in the mixed state.

doBevelImagePictIconContent

Recall that, if a mouse-down occurs in the Bevel Buttons, Image Wells, Picture Controls, and
Icon Controls window when it is the front window, doBevelImagePictIconContent is called to
further handle the event.

At the first line a handle to the structure containing references to all the control objects is
obtained.

The call to GlobalToLocal changes the coordinates at which the mouse-down occurred to the local
coordinates required by the following call to FindControl.  The constant representing the part
code returned by FindControl is then drawn in the window header.

If the part code returned by FindControl is not kControlNoPart (0), meaning that an enabled
control was under the mouse cursor at the time of the mouse-down, the if block executes. 
TrackControl takes control while the mouse button remains down, returning a part code when the
button is released.

In the case of the first 10 specified controls (bevel buttons), the control part code returned
by TrackControl is simply drawn in the window header.

The next four controls are bevel button with menus.  In these cases, if the part code returned
indicates that the mouse button was released while the cursor was within the menu,
GetBevelButtonMenuValue is called to get the menu item number.  The part code and menu item
number are then drawn in the window header.  If the cursor was not in the menu when the mouse
button was released, the part code returned by TrackControl is drawn in the window header.

The 10th, 11th, and 12th bevel buttons have toggle behaviour.  With some assistance from the
application, they behave like radio buttons.  If the control in which the mouse-down occurred
was one of these bevel buttons, and if the cursor was still within the control when the mouse
button was released, SetControlValue is called to set the three controls to the unchecked
state, following which the selected control is set to the checked state.  Either way, the part
code returned by TrackControl is drawn in the window header.

The 18th bevel button is used to demonstrate bevel button graphic alignments using a single
bevel button.  A mouse-down within this button causes the function doGraphicAlignment to be
called.

The 19th bevel button is used to demonstrate bevel button text alignments using a single bevel
button.  A mouse-down within this button causes the function doTextAlignment to be called.

The 20th bevel button is used to demonstrate text offsetting using a single bevel button.  A
mouse-down within this button causes the function doTextOffset to be called.

The 21st bevel button is used to demonstrate bevel button text placement in relation to the
bevel button's graphic using a single bevel button.  A mouse-down within this button causes the
function doTextPlacement to be called.

Finally, if the mouse-down was in an image well, picture control, or icon control, and except
for the non-tracking picture and icon control variants, the part code returned by TrackControl
is drawn in the window header.

doDrawPartCode

doDrawPartCode takes part codes and menu item numbers and assembles them into descriptive
strings for drawing in the window header.  The constants used are stored in 'STR#' resources,
and are retrieved using GetIndString.  In the final two lines, Draw1Control is called to redraw
the window header control (in effect erasing the current text drawn within the window header
area) and doDrawMessage is called to draw the assembled string.

doGraphicAlignment

doGraphicAlignment is called to demonstrate bevel button graphic alignment using the helper
function SetBevelButtonGraphicAlignment, which facilitates finer adjustment of graphic
placement that using SetControlData with the kControlBevelButtonGraphicAlignTag control data
tag constant.  Each time around the outer for loop, the alignment constant is changed.  In the
inner for loop, SetBevelButtonGraphicAlignment is called 53 times, with the two offset
parameters incremented and Draw1Control called at each call.  The alignment constant used
during each pass through the outer for loop is drawn in the window header.

doTextAlignment

doTextAlignment is called to demonstrate the effect of the bevel button text alignment
constants using the helper function SetBevelButtonTextAlignment, which facilitates finer
adjustment of text placement that using SetControlData with the
kControlBevelButtonGraphicAlignTag control data tag constant.  Each time around the outer for
loop, the alignment constant is changed. In the inner for loop, SetBevelButtonTextAlignmentis
called 41 times, with the offset parameter incremented and Draw1Control called at each call. 
The alignment constant used during each pass through the outer for loop is drawn in the window
header.

doTextOffset

doTextOffset is called to demonstrate text offsetting from the left and the right within a
bevel button.  For the purposes of the demonstration, two animations involving incrementing
offsets values are used.  Prior to first animation, SetControlData is called with the
kControlBevelButtonTextOffsetTag tag to align the text on the left.  Prior to second animation,
SetControlData is called with the kControlBevelButtonTextOffsetTag tag to align the text on the
right.  Within the for loops, SetControlData is called with the
kControlBevelButtonTextOffsetTag tag to offset the text from the left or right by the specified
number of pixels, and Draw1Control re-draws the control.

doTextPlacement

doTextPlacement is called to demonstrate the effect of the bevel button text placement
constants.  Within a for loop which increments the text placement constant,
SetBevelButtonTextPlacement is called and Draw1Control re-draws the control.

doDrawMessage and doDrawLegends

doDrawMessage and doDrawLegends are incidental to the demonstration.  Both functions draw text
in the window in either black or gray depending on whether the window is currently in front or
in the background.

TabEditClock.c

TabEditClock.c creates a movable modal dialog in which is demonstrated a tab control, edit text
controls and clock controls.  A numeric key filter function is attached to the second edit text
control.  The third edit text control is for password input.  The controls displayed by each
tab are embedded in user panes.

The kDialogFlagsUsesControlHierarchy flag is set in the 'dlgx' resources for all dialogs used
in the demonstration.  Recall that this means that the Dialog Manager creates a root control in
the dialog and establishes an embedding hierarchy, that all dialog items automatically become
controls, and that the Dialog Manager uses AutoEmbedControl to position dialog items in an
embedding hierarchy based on both visual containment and their item list number.

The dialog item list used by the dialog created by TabEditClock.c is shown in the following, in
which the indentation represents the embedding hierarchy:

1.    OK push button primitive.
2.    Tab control (kTabControlLargeProc variant).
      Visually contains the two user panes (items 3 and 12) and thus automatically embeds
      those items.
      3.    User pane control with kControlSupportsEmbedding feature bit set (initial value set
            to 2).
            Visually contains items 4 to 11 and thus automatically embeds those items.
            4.    Static text primitive "Name:".
            5     Edit text primitive.
            6.    Static text primitive "Age:".
            7.    Edit text primitive.
            8.    Static text primitive "Password:".
            9.    Edit text control (kControlEditTextPasswordProc variant).
            10.   Extract push button primitive.
            11.   Image well control.
     12.    User pane control with kControlSupportsEmbedding feature bit set (initial value set
            to 2).
            Visually contains items 13 to 20 and thus automatically embeds those items.
            13.    Static text primitive "Hours, Mins, Secs:".
            14.    Clock control (kControlClockTimeSecondsProc variant).
            15.    Static text primitive "Date, Month, Year:".
            16.    Clock control (kControlClockDateProc variant).
            17.    Static text primitive "Month, Year:".
            18.    Clock control (kControlClockMonthYearProc variant).
            19.    Extract push button primitive.
            20.    Image well control.
21.    Clock control (kControlClockTimeSecondsProc variant, live, display only.)
22.    Group box (kControlGroupBoxSecondaryTextTitleProc variant).
       Visually contains item 23 and thus automatically embeds that item:
       23.    Static text primitive.

doTabEditClock

doTabEditClock creates the dialog, calls ModalDialog to handle events in the dialog, and
disposes of the dialog when the user hits the OK push button.

Firstly, and as is always required when a dialog is to be displayed, the front window (if one
exists) is explicitly deactivated.

The call to GetNewDialog creates the dialog.  The call to SetWTitle sets the window's title so
as to force an association with the 'hrct' resource containing the help balloons for the Edit
Text Control tab.  (Later calls to SetWTitle in this function are used for similar purposes.)

SetDialogDefaultItem tells the Dialog Manager which is the default push button item, to alias
the Return and Enter keys to that item, and to draw the default ring around that item (Mac OS
8/9) or make it pulsing blue (Mac OS X).  SetDialogTracksCursor will cause the Dialog Manager
to change the cursor shape to the I-Beam cursor whenever the cursor is over an edit text item
specified in the 'DITL' as an edit text primitive.

The first call to GetDialogItemAsControl gets a reference to the user pane used for the clocks
tab.  HideControls hides this user pane and all the controls automatically embedded within it.

At the next block, SetControlData is called with the kControlEditTextTextTag tag to assign some
text to the first edit text control.  The fields of an edit text selection structure are then
assigned values which will cause the following call to SetControlData to select the entire edit
text control.

The next block creates universal procedure pointers for event filter, key filter, and edit text
validator callback functions.  (The event filter function is defined in the source code file
Callbacks.c.)  SetControlData is then called with the kControlEditTextValidationProcTag tag to
attach the edit text validation function to the first edit text control.  SetControlData is
then called again with the kControlEditTextKeyFilterTag tag to attach the key filter function
to the second edit text control.

With those preliminaries attended to, ShowWindow is called to display the window, following
which the ModalDialog loop is entered.  The loop will execute until the user hits the OK push
button. Note that the previously created UPP is passed in the filterProc parameter of
ModalDialog.

When a mouse-down event occurs in an enabled item, ModalDialog returns the item number of the
item hit.  If the item hit was the tab item, GetDialogItemAsControl is called to get a
reference to the tab control and GetControlValue is called to determine which of the two tabs
was hit.  If the tab hit was the Edit Text Controls tab, the Clock Controls user pane is
hidden, the Edit Text Controls user pane is shown, and the keyboard focus is set to the first
edit text control.  If the tab hit was the Clock Controls tab, the Edit Text Controls user pane
is hidden, the Clock Controls user pane is shown, and the keyboard focus is set to the first
clock control.

If the item hit was the Extract push button in the Edit Text Controls pane, the image well
control is re-drawn to erase any previous text and a function is called to extract and display
the contents of the edit text controls.

If the item hit was the Extract push button in the Clock Controls pane, the image well control
is re-drawn to erase any previous text and a function is called to extract and display the
contents of the clock controls.

When the user hits the OK button, DisposeDialog closes the dialog and disposes of the
associated memory, and the universal procedure pointers associated with the event filter
function and key filter function are disposed of.

doExtractEditText

doExtractEditText extracts the text from the edit text controls and draws it in the image well
area.  In the case of the Password edit text control, the text extracted is the actual password
typed, not the bullet text.

In the case of the first two edit text controls, GetDialogItem is used to get the handle to the
hText field of the TERec structure used by the item.  This is where the characters are located. 
(Exactly what is returned in the iHandle field of a GetDialogItem call depends on the item
type.)  GetDialogItemText then copies these characters to a variable of type Str255.

In the case of the third (password) edit text control, GetDialogItemAsControl gets a reference
to the control.  GetControlDataSize is then called with the kControlEditTextTextTag tag to get
the number of characters and GetControlData is called with the kControlEditTextPasswordTag to
get the clear password text from the control.

doExtractDateTime

doExtractDateTime gets the settings in the three clock controls into a long date structure,
extracts the content of the relevant fields of that structure, and draws that content in the
image well area.

For each clock, GetControlData is called with the kControlClockLongDateTag tag to get the
information into a long date structure.  The rest of the code simply converts the values in the
relevant fields of this structure to strings, which are concatenated with other identifying
strings prior to being drawn in the image well.

numericFilter

numericFilter is the key filter function attached to the second edit text control.

The character code and modifiers parameters passed to this function by the control are first
examined to determine whether (1) the character code represents the numeric characters between
0 and 9 inclusive or (2) whether the Command key was down.  If either of these conditions is
true, the function returns kControlKeyFilterPassKey.  This means that, if the character is
between 0 and 9 inclusive, it will be accepted.  It also means that, if the Command key was
down, non-numeric characters will be accepted as well.  This latter is necessary to ensure that
the user can edit the text in the edit text control using the usual Edit menu Command-key
equivalents.

If a return does not occur at that point, the character code is further examined to determine
whether it represents one of the arrow keys, the backspace key or the delete key.  If so,
kControlKeyFilterPassKey is returned.  If not, the system alert sound is played and
kControlKeyFilterBlockKey is returned, meaning that the character is to be rejected.

editTextValidator

editTextValidator is the edit text validation callback function attached to the first edit text
control.

The call to GetControlData gets the text to be examined from the control into the variable
oldText.  The next block sets the length byte in oldText to the actual number of characters in
the text, limited to 255 characters.  The for loop then examines each character and, if it is
an alphabetic character, the space character, or the period character, inserts it into the
newText variable and increments a variable which is eventually used to set the length byte of
newText.  When the if loop exits, the length byte is set and SetControlData is called to put
the replacement text into the control.  Finally, Draw1Control redraws the control.

GroupArrowsProgress.c

GroupArrowsProgress.c creates a movable modal dialog in which is demonstrated a checkbox group
box, a pop-up group box, little arrows, a disclosure triangle, chasing arrows, and an
indeterminate progress bar.

The checkbox group box contains a static text item and three radio buttons.  The radio buttons
are embedded in a radio group.  The pop-up group box contains two user panes.  Embedded in each
user pane are a checkbox and a radio group.  Embedded in each radio group are two radio
buttons.

The dialog item list used by the dialog created by GroupArrowsProgress.c is shown in the
following, in which the indentation represents the embedding hierarchy:

1.    Push button primitive.
2.    Group box control (kControlGroupBoxCheckboxProc variant).
      3.    Radio group control.
            4.    Radio button primitive.
            5.    Radio button primitive.
            6.    Radio button primitive.
      7.    Checkbox primitive.
8.    Group box control(kControlGroupBoxPopupButtonProc variant).
      9.    User pane control with kControlSupportsEmbedding feature bit set (initial value set
            to 2).
            10.    Radio group control
                   11.    Radio button primitive.
                   12.    Radio button primitive.
            13.    Checkbox primitive.
            14.    Static text primitive.
      15.   User pane control with kControlSupportsEmbedding feature bit set (initial value set
            to 2).
            16.    Radio group control
                   17.    Radio button primitive.
                   18.    Radio button primitive.
            19.    Checkbox primitive.
            20.    Static text primitive.
21.    Group box control (kControlGroupBoxSecondaryTextTitleProc variant).
       22.    Static text primitive.
23.    Group box control (kControlGroupBoxSecondaryTextTitleProc variant).
       24.    Static text primitive.
       25.    Placard control.
              26.    Static text primitive.
       27.    Little arrows control.
28.    Extract push button primitive.
29.    Image well
30.    Separator line
31.    Disclosure triangle (kControlTriangleProc variant).
32.    Static text primitive.

A second dialog item list resource, containing a chasing arrows control and a progress bar
control, is appended to the dialog when the disclosure triangle is clicked.

doGroupArrowsProgress

doGroupArrowsProgress creates the dialog, calls ModalDialog to handle events until the user
hits the OK push button, and then disposes of the dialog.

At the first two lines, if the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls
window is open, it is explicitly deactivated.

The call to GetNewDialog creates the dialog and SetDialogDefaultItem establishes the OK push
button as the default push button.

The next two lines create universal procedure pointers for the application-defined event filter
(callback) function and an application-defined action function for the little arrows control. 
(The event filter function is in the source code file Callbacks.c.)

The next block sets the initial value of the checkbox group box to 1 (checked).

The little arrows are used to set a (simulated) cache size, which is displayed in a static text
item overlayed on a placard item.  The little arrows initial value is set in the 'CNTL'
resource to 96.  The first three lines of the next block extract this value, convert it to a
string and append the character "K".  SetControlData is then called with the
kControlStaticTextTextTag to set this string in the static text item.

The second user pane in the pop-up group box is then hidden before the call to ShowWindow,
following which the ModalDialog loop is entered.  Note that the UPP associated with the
application-defined event filter function is passed in the filterProc parameter of ModalDialog.

If ModalDialog reports that the item hit was the checkbox group box's checkbox or the pop-up
group box's pop-up menu, functions are called to further handle the hit.

if the item hit was one of the checkboxes within the pop-up group box, the control's control
value is set so that the control is checked if it was unchecked, or unchecked if it was
checked.

If the item hit was the disclosure triangle, an function is called to further handle the hit.

If the item hit was the Extract push button, Draw1Control is called to redraw the image well,
thus erasing any previous text in the well, and a function is called to extract the control
settings and draw them in the image well area.

Note that hits on the radio buttons will be handled automatically by the radio group controls
in which they are embedded.  The radio group control will set the new control values according
to which radio button is hit, and will change the checked/unchecked appearance of the radio
buttons to match.

Note also that mouse-down events in the little arrows are detected and handled in the event
filter function.  (See the source code file Callbacks.c.)

When the OK button is hit, the loop exits, DisposeDialog closes the dialog and disposes of the
associated memory, and the two previously created universal procedure pointers are disposed of. 
In addition, the global variable which flags that the dialog was open is set to false.

doCheckBoxGroupBox

doCheckBoxGroupBox further handles a hit in the checkbox group box's checkbox.

The first three lines flip the control's value; that is, if the control's value was 1
(checked), it is set to 0 (unchecked), and vice versa.

If the new value of the control is 0 (unchecked), the radio group and checkbox within the group
box are deactivated.  Since the radio buttons are embedded in the radio group, they will also
be deactivated when the radio group is deactivated.

If the new value of the control is 1 (checked), the radio group and checkbox within the group
box are activated.  Since the radio buttons are embedded in the radio group, they will also be
activated when the radio group is activated.

doPopupGroupBox

doPopupGroupBox further handles a hit in the pop-up group box's pop-up menu button.

The first two lines get the control's value, which represents the menu item chosen.  Depending
on the item chosen, the appropriate user panes are hidden or shown, thus hiding or showing all
controls embedded in each user pane.

doChasingAndProgress

doChasingAndProgress further handles a hit in the disclosure triangle.

The first three lines flip the control's value; that is, if the control's value was 1
(expanded), it is set to 0 (collapsed), and vice versa.

If the new control value is 1 (expanded), GetResource is called to load the item list resource
containing the chasing arrows and progress bar items.  AppendDITL is then called to append
these items to the end of the dialog's item list.  The constant passed in the third parameter
of this call causes the dialog to be expanded downwards to accommodate the new items. 
SetControlData is then called with the kControlProgressBarIndeterminateTag tag to make the
progress bar an indeterminate progress bar.

Not previously mentioned is the fact that the appended 'DITL' resource contains a static text
item, with no text, the function of which is simply to expand the dialog further downwards to
accommodate a move of the OK push button.  The call to MoveControl moves the OK push button to
a position below the chasing arrows and progress bar.

Finally, SetControlData is called with the kControlStaticTextTextTag tag to change the text in
the static text control adjacent to the disclosure triangle.  Draw1Control re-draws the control
to display the changed text.

If the new disclosure triangle control value is 0 (collapsed), the OK button is moved back to
its previous location, SizeWindow is called to resize the window to its previous size,
SetControlData is called with the kControlStaticTextTextTag tag to change the text in the
static text control adjacent to the disclosure triangle, and Draw1Control re-draws the control
to display the changed text.

doExtractCurrentStatus

doExtractCurrentStatus is called when the Extract push button is hit.  It simply extracts the
values of the various controls, builds up strings based on those values, and draws those
strings in the image well area.

Note in the second last block that the value of the little arrows control represents the
current (simulated) cache size.  The little arrows control value is set within the action
function arrowsActionFunction in the source code file Callbacks.c.

Sliders.c

Sliders.c creates a movable modal dialog in which is demonstrated various slider control
variants and two simple user pane functions.

doSliderUserPane

doSliderUserPane creates the dialog, calls ModalDialog to handle events until the user hits the
OK push button, and then disposes of the dialog.

At the first two lines, if the Bevel Buttons, Image Wells, Picture Controls, and Icon Controls
window is open, it is explicitly deactivated.

The call to GetNewDialog creates the dialog and SetDialogDefaultItem establishes the OK push
button as the default push button.

The next three lines create universal procedure pointers for the application-defined event
filter (callback) function and two application-defined action functions for the live-feedback
slider variants, one for the two at top right of the dialog and one for the two horizontal
sliders.  (The event filter function and the action functions are in the source code file
Callbacks.c.)

The next two blocks creates universal procedure pointers for two user pane functions (one a
draw function and one an activate function), and attach these functions to a user pane located
immediately to the right of the two horizontal sliders.

The next block assigns references to the first four sliders to global variables and call a
function to draw the respective control values in static text items located immediately below
the sliders.

The following four lines assign references to the horizontal sliders to global variables and
assign a value based on the current slider control values to the red and blue fields of two
global variables of type RGBColor.

The call to ShowWindow makes the dialog visible before the ModalDialog loop is entered.  This
loop executes until the OK button is hit, at which time DisposeDialog is called to remove the
dialog and dispose of its associated memory, the previously created universal procedure
pointers are disposed of, and the global variable which flags that the Sliders dialog is open
is assigned false.

doDrawSliderValues

doDrawSliderValue is called by doSliderUserPane to draw the initial control values of the four
top sliders in the static text controls immediately below the sliders.

The first line gets the control's value and converts it to a string.  The next block
determines, on the basis of the received control reference, which is the target static text
item.  SetControlData is then called with the kControlStaticTextTextTag tag to set the text,
and Draw1Control re-draws the static text control.

As will be seen, this function is also called from within the event filter function when a
mouse-down has been detected within the two non-live-scrolling sliders.

userPaneDrawFunction

userPaneDrawFunction will be called whenever an update event is received.  This will occur when
the dialog is opened and, subsequently, when an overlaying window or help balloon is removed
from the area occupied by the user pane (to the immediate right of the horizontal sliders).

The two calls to DrawThemePlacard draw two Appearance Manager placard primitives to the right
of the horizontal sliders.  The global variable gDrawActivated determines whether the primitive
is drawn with an activated or deactivated appearance.

If the global variable gDrawActivated indicates that the interior of the placard should be
drawn, the foreground colour for each interior is set to that stored in global variables and
PaintRect is called to paint the interior in that colour.  (As will be seen, the value stored
in these global variables is changed by the action function called while the mouse button
remains down in the slider's indicators.)

If gDrawActivated indicates that the interior of the placard should be displayed with a
deactivated appearance, the interior is left as drawn by DrawThemePlacard.

userPaneActivateFunction

The kControlWantsActivate feature bit is set in the user pane on creation, that is, the
control's minimum value in the 'CNTL' resource is set to 16.  This ensures that this function
will be called when the dialog receives activate events.

Depending on whether the dialog is about to be activated or deactivated, the global variable
gDrawActivated is set to true or false.  As has been seen, this global variable controls the
way in which the placard primitive and its interior is drawn.

TextBox.c

doTextBox is called when the user chooses TextBoxes from the Demonstration menu.  It opens a
movable modal dialog containing standard and scrolling text box controls.

Callbacks.c

Callbacks.c contains the event filter (callback) function used by all movable modal dialogs and
three action functions, one for the little arrows, one for the vertical live-feedback sliders,
and one for the horizontal live-feedback sliders.

eventFilter

The event filter function eventFilter is identical to the event filter function introduced at
Chapter 8 except that it intercepts mouse-down events in the little arrows and sliders and
informs ModalDialog that it has handled those events.

After the call to SetPortDialogPort, if the Group Boxes, Arrows, and Progress Bar dialog is
currently open, and if the event is a mouse-down event, the location of the mouse-down is
extracted from the where field of the event structure and converted to the local coordinates
required by the following call to FindControl.  If FindControl determines that there is an
enabled control under the mouse cursor, and if that control is the little arrows control,
TrackControl is called to handle all user interaction while the mouse button remains down. 
While the mouse button remains down, TrackControl continually calls the action function pointed
to by the UPP passed in the third parameter.  When the mouse button is released, the function
exits with true being returned to ModalDialog.

If, on the other hand, the Sliders and User Pane Functions dialog is open, and if the event is
a mouse-down event, and if FindControl reports an enabled control, and if that control is one
of the two non-live-feedback sliders, TrackControl is called to handle all user interaction
while the mouse button remains down.  When the mouse button is released, the function
doDrawSliderValues is called to draw the new control value in the static text item below the
slider.  Once again, the function then exits with true being returned to ModalDialog.

If the mouse-down was in one of the two live-feedback sliders at the top right of the dialog,
TrackControl is called with a UPP to the first slider action function passed in the third
parameter.

If the mouse-down was in one of the two horizontal live-feedback sliders, TrackControl is
called with a UPP to the second slider action function passed in the third parameter.

arrowsActionFunction

arrowsActionFunction is the action function for the little arrows.  It is called continually by
TrackControl while the mouse button remains down.

if the mouse cursor is still within the control, GetControlValue is called to get the current
control value.  The function then switches according to the part code.  If the cursor is in the
top arrow, the control's value is increased by 32 unless this would cause the value to exceed
the control's maximum value (set in the 'CNTL' resource to 7680).  If the cursor is in the
bottom arrow, the control's value is decreased by 32 unless this would cause the value to be
lower that the control's minimum value (set in the 'CNTL' resource to 96).

If the control's value was increased or decreased within the switch, SetControlValue is called
to set the new control value, and the final block sets the new text for the Cache size static
text item and re-draws the item.

sliderActionFunction1

sliderActionFunction1 is the action function for the live-feedback sliders at the top right of
the dialog.  It is called continually by TrackControl while the mouse button remains down.

GetControlValue gets the control's current value and NumToString converts it to a string for
display.  The next line gets the reference to the control's owning window required by the call
to GetDialogItemAsControl.  The if block determines which of the two sliders the mouse is down
in.  The last two lines set the text in the appropriate static text control and redraw the
control.

sliderActionFunction2

sliderActionFunction3 is the action function for the horizontal live-feedback sliders.  It is
called continually by TrackControl while the mouse button remains down.

GetControlValue gets the control's current value.  If the slider is the top horizontal slider,
the red field of the RGBColor global variable gRedColor is assigned a new value based on the
control's current value, and the local Rect variable is assigned coordinates based on the
placard at the right of the slider.  If the slider is the bottom horizontal slider, the blue
field of the RGBColor global variable gBlueColor is assigned a new value based on the control's
current value, and the local Rect variable is assigned coordinates based on the placard at the
right of the slider.

Finally, PaintRect is called to paint the interior area of the relevant image well in the new
colour.

SmallControls.c

doSmallControls

doSmallControls is called when the user chooses the Small Controls item in the Demonstration
menu (Mac OS X only).  It opens a floating window in which those controls with small versions
are displayed.

Note that:

o A call to SetControlData with the kControlSizeTag tag is required to make the scroll bars
  small.

o The value passed in the third parameter of the CreateTabsControl call makes the tab control
  small.

o A call to SetControlData with the kControlSizeTag tag is required to make the slider control
  small.

o A call to SetControlData with the kControlSizeTag tag is required to make the radio button
  and checkbox controls small.  In addition, a call to SetControlFontStyle is required to make
  the title small.

o The only way to create a pop-up menu button with both the menu and the title small is to
  create the control from a 'CNTL' resource, specifying the "use window font" variant.  (Note
  that the window font is set to the small system font.)

o The edit text control is made small by, firstly, making the control's rectangle 12 pixels
  high and, secondly, changing the font to the small system font by passing the address of a
  ControlFontStyleRec structure in the sixth parameter of the CreateEditTextControl call.

o The push button is made small by, firstly, making the control's rectangle 17 pixels high and,
  secondly, calling SetControlFontStyle is to make the title small.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

The Legend of Heroes: Trails of Cold Ste...
I adore game series that have connecting lore and stories, which of course means the Legend of Heroes is very dear to me, Trails lore has been building for two decades. Excitedly, the next stage is upon us as Userjoy has announced the upcoming... | Read more »
Go from lowly lizard to wicked Wyvern in...
Do you like questing, and do you like dragons? If not then boy is this not the announcement for you, as Loongcheer Game has unveiled Quest Dragon: Idle Mobile Game. Yes, it is amazing Square Enix hasn’t sued them for copyright infringement, but... | Read more »
Aether Gazer unveils Chapter 16 of its m...
After a bit of maintenance, Aether Gazer has released Chapter 16 of its main storyline, titled Night Parade of the Beasts. This big update brings a new character, a special outfit, some special limited-time events, and, of course, an engaging... | Read more »
Challenge those pesky wyverns to a dance...
After recently having you do battle against your foes by wildly flailing Hello Kitty and friends at them, GungHo Online has whipped out another surprising collaboration for Puzzle & Dragons. It is now time to beat your opponents by cha-cha... | Read more »
Pack a magnifying glass and practice you...
Somehow it has already been a year since Torchlight: Infinite launched, and XD Games is celebrating by blending in what sounds like a truly fantastic new update. Fans of Cthulhu rejoice, as Whispering Mist brings some horror elements, and tests... | Read more »
Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »

Price Scanner via MacPrices.net

Apple is offering significant discounts on 16...
Apple has a full line of 16″ M3 Pro and M3 Max MacBook Pros available, Certified Refurbished, starting at $2119 and ranging up to $600 off MSRP. Each model features a new outer case, shipping is free... Read more
Apple HomePods on sale for $30-$50 off MSRP t...
Best Buy is offering a $30-$50 discount on Apple HomePods this weekend on their online store. The HomePod mini is on sale for $69.99, $30 off MSRP, while Best Buy has the full-size HomePod on sale... Read more
Limited-time sale: 13-inch M3 MacBook Airs fo...
Amazon has the base 13″ M3 MacBook Air (8GB/256GB) in stock and on sale for a limited time for $989 shipped. That’s $110 off MSRP, and it’s the lowest price we’ve seen so far for an M3-powered... Read more
13-inch M2 MacBook Airs in stock today at App...
Apple has 13″ M2 MacBook Airs available for only $849 today in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty is included,... Read more
New today at Apple: Series 9 Watches availabl...
Apple is now offering Certified Refurbished Apple Watch Series 9 models on their online store for up to $80 off MSRP, starting at $339. Each Watch includes Apple’s standard one-year warranty, a new... Read more
The latest Apple iPhone deals from wireless c...
We’ve updated our iPhone Price Tracker with the latest carrier deals on Apple’s iPhone 15 family of smartphones as well as previous models including the iPhone 14, 13, 12, 11, and SE. Use our price... Read more
Boost Mobile will sell you an iPhone 11 for $...
Boost Mobile, an MVNO using AT&T and T-Mobile’s networks, is offering an iPhone 11 for $149.99 when purchased with their $40 Unlimited service plan (12GB of premium data). No trade-in is required... Read more
Free iPhone 15 plus Unlimited service for $60...
Boost Infinite, part of MVNO Boost Mobile using AT&T and T-Mobile’s networks, is offering a free 128GB iPhone 15 for $60 per month including their Unlimited service plan (30GB of premium data).... Read more
$300 off any new iPhone with service at Red P...
Red Pocket Mobile has new Apple iPhones on sale for $300 off MSRP when you switch and open up a new line of service. Red Pocket Mobile is a nationwide MVNO using all the major wireless carrier... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, available for $759 for 8-Core CPU/7-Core GPU/256GB models and $929 for 8-Core CPU/8-Core GPU/512GB models. Apple’s one-year warranty is... Read more

Jobs Board

DMR Technician - *Apple* /iOS Systems - Haml...
…relevant point-of-need technology self-help aids are available as appropriate. ** Apple Systems Administration** **:** Develops solutions for supporting, deploying, Read more
Operating Room Assistant - *Apple* Hill Sur...
Operating Room Assistant - Apple Hill Surgical Center - Day Location: WellSpan Health, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Read more
Solutions Engineer - *Apple* - SHI (United...
**Job Summary** An Apple Solution Engineer's primary role is tosupport SHI customers in their efforts to select, deploy, and manage Apple operating systems and Read more
DMR Technician - *Apple* /iOS Systems - Haml...
…relevant point-of-need technology self-help aids are available as appropriate. ** Apple Systems Administration** **:** Develops solutions for supporting, deploying, Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.