PlotIcons.c

/*
    File:       PlotIcons.c
 
    Contains:   snippet to demonstrate the use of the system 7 icon utilities
                and the system 7 popup control cdef in a program using modal dialogs
    
                This shows: how to use the sys 7.0 popup
                and how to plot Icons from Icon families.
 
    Written by: Nick Thompson   
 
    Copyright:  Copyright © 1994-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/6/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                5/11/94     nt              updated to use std file icons, in another dialog box
                8/96                        old routines names changed; Str255 theItem, OSErr
                                            theErr and short userSelection removed from 
                                            DoStdFileIconsDialog; line 266 - NewModalFilterProc 
                                            added; fixed return value for OurFilter to eliminate
                                            compiler warnings
 
*/
#include <Menus.h>
#include <Fonts.h>
#include <Dialogs.h>
#include <icons.h>
 
// prototypes
pascal Boolean OurFilter(DialogPtr dlg, EventRecord *event, short *itemHit) ;
void DoStdFileIconsDialog(void);
void UpdateIconsDialog( DialogPtr thePopupDialog );
void    FlashDialogItem(DialogPtr dlg, short itemToFlash);
 
// constants used in the dialog filter proc
const char kEnter   = 0x03 ;
const char kReturn  = 0x0D ;
const char kEscape  = 0x1B ;
const char kPeriod  = '.' ;
 
 
// constants for our dialog IDs these are used in the filterproc to do the "right thing"
// by calling the appropriate redrawing code
 
const long  kIconsDialog        = 1000 ;
const long  kStdFileIconsDialog = 1001 ;
 
 
// constants for items in the dialog
enum {
    kThePopupMenu = 4 ,     // popup menu is the fourth item in the dialog
    kUserTextArea = 5 ,     // this is a rect for us to write a string with the user selection
    kLargeIconArea = 8 ,    // rect to draw the lg icon into
    kSmallIconArea = 9 ,    // rect to draw the small icon
    kMoreIconBtn = 10       // we want to see the std file icon dialog
} ;
 
// table to tie up the menu selection with the 
// actual icon IDs defined in Icons.h
// These are documented in the resource manager chapter
// of Inside Macintosh: More Toolbox Essentials, Page 1-130 onwards.
 
long    resIDTable[] = {
        0,                                  /* Dummy for start of the array */
        genericDocumentIconResource,        /* [1]  "Generic Document" */
        genericApplicationIconResource,     /* [2]  "Generic Application" */
        genericDeskAccessoryIconResource,   /* [3]  "Generic Desk Accessory" */
        genericEditionFileIconResource,     /* [4]  "Generic Edition File" */
        genericStationeryIconResource,      /* [5]  "Generic Stationary" */
        genericPreferencesIconResource,     /* [6]  "Generic Preferences" */
        genericQueryDocumentIconResource,   /* [7]  "Generic Query Document" */
        genericExtensionIconResource,       /* [8]  "Generic Extension" */
        genericFolderIconResource,          /* [9]  "Generic Folder" */
        privateFolderIconResource,          /* [10]  "Private Folder" */
        ownedFolderIconResource,            /* [11]  "Owned Folder" */
        dropFolderIconResource,             /* [12]  "Drop Folder" */
        sharedFolderIconResource,           /* [13]  "Shared Folder" */
        mountedFolderIconResource,          /* [14]  "Mounted Folder" */
        systemFolderIconResource,           /* [15]  "System Folder" */
        appleMenuFolderIconResource,        /* [16]  "Apple Menu Folder" */
        startupFolderIconResource,          /* [17]  "Startup Items Folder" */
        controlPanelFolderIconResource,     /* [18]  "Control Panels" */
        printMonitorFolderIconResource,     /* [19]  "Printmonitor Folder" */
        preferencesFolderIconResource,      /* [20]  "Preferences Folder" */
        extensionsFolderIconResource,       /* [21]  "Extensions" */
        -3968,                              /* [22]  "Fonts" */
        floppyIconResource,                 /* [23]  "Floppy Icon" */
        trashIconResource,                  /* [24]  "Trash Icon" */
        fullTrashIconResource               /* [25]  "Full Trash Icon" */
} ;
 
long    stdFileResTablep[] = {
        1,
        2,
        3,
        4,
        5
} ;
 
 
 
// Structure for the private data for a popup control.
// This structure is documented on page 5-77 
// Inside Macintosh: Macintosh Toolbox Essentials
 
typedef struct popupPrivateData {
    MenuHandle  mHandle;    // the popup menu handle 
    short       mID;        // the popup menu ID 
    // after these two public fields is the mPrivate private data, 
    // which may be any old size and should not be messed with 
}   popupPrivateData;
 
 
void DoIconsDialog(void) ;
 
 
void main(void) {
 
    // initialize the toolbox
    InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus();
    TEInit(); InitDialogs(nil); InitCursor(); FlushEvents(everyEvent,0);
    
    
    DoIconsDialog() ;
}
 
 
void DoStdFileIconsDialog(void) 
{
    popupPrivateData    **myPopupPrivateDataPtr ;
    
    short               iKind;
    Handle              iHandle;
    Rect                iRect;
    
    MenuHandle          thePopupMenuHdl ;
    
    DialogPtr           thePopupDialog ;
    short               itemHit ;
    GrafPtr             savedPort ;
    
    short               index ;
 
    thePopupDialog = GetNewDialog ( 129, nil, (WindowPtr)-1 );
    SetWRefCon((WindowPtr)thePopupDialog, kStdFileIconsDialog ) ;
    GetPort( &savedPort ) ;
    SetPort( thePopupDialog ) ;
 
 
    // get a reference to the popup control, this is item 4 in the dialog
    // we need to get the menuhandle associated with the control, it is in the private
    // control data field, as documented in Inside Macintosh: Toolbox page 5-77
    
    // get the control handle for the popup         
    GetDialogItem ( thePopupDialog, kThePopupMenu, &iKind, &iHandle, &iRect) ;
    
    // extract from the control the menuhandle
    myPopupPrivateDataPtr = (popupPrivateData **)(**(ControlHandle)iHandle).contrlData ; 
    thePopupMenuHdl = (**myPopupPrivateDataPtr).mHandle ;
    
    // set up the Icons - we have 5 items here
    for( index = 0; index < 5; index++ ) 
        SetItemIcon( thePopupMenuHdl, index + 1, stdFileResTablep[index]) ;
    do {
    
        ModalDialog ( NewModalFilterProc(OurFilter), &itemHit );
        
        switch ( itemHit ) {
        
            default :
                break ;     
        }
        
    } while( itemHit != ok ) ;
    
    DisposeDialog ( thePopupDialog );
    SetPort( savedPort ) ;
 
}
 
 
 
// this function ensures that the correct Icons are drawn in the dialog
// corresponding with the current user selection.
 
void UpdateIconsDialog( DialogPtr thePopupDialog )  // dialog pointer for the popup dialog
{
    popupPrivateData    **myPopupPrivateDataPtr ;
    
    short               iKind;
    Handle              iHandle;
    Rect                iRect;
    
    MenuHandle          thePopupMenuHdl ;
    Str255              theItem ;
 
    OSErr               theErr ;
    
    
    short               userSelection ;         // the current menu selection
    
    // the user choose the popup.  The item number selected will be the control value
    // we need to get the menuhandle associated with the control, it is in the private
    // control data field, as documented in Inside Macintosh: Toolbox page 5-77
    
    // get the control handle for the popup         
    GetDialogItem ( thePopupDialog, kThePopupMenu, &iKind, &iHandle, &iRect) ;
    
    // extract from the control the menuhandle
    myPopupPrivateDataPtr = (popupPrivateData **)(**(ControlHandle)iHandle).contrlData ; 
    thePopupMenuHdl = (**myPopupPrivateDataPtr).mHandle ;
 
    // get the string associated with the users selection
    userSelection = GetControlValue((ControlHandle)iHandle) ;
    GetMenuItemText ( thePopupMenuHdl, userSelection, theItem );
    
    // get the rect we are drawing in
    GetDialogItem ( thePopupDialog, kUserTextArea, &iKind, &iHandle, &iRect) ;
    
    // erase the area to draw in
    EraseRect( &iRect ) ;
                
    // and draw the current user selection
    MoveTo(iRect.left + 1, iRect.bottom - 6) ;
    DrawString( theItem ) ;
    
    // now plot the Icons.  The id of the item selected in
    // the menu will be in userSelection.
    
    // first draw the large icon
    
    // get the rect we are drawing in
    GetDialogItem ( thePopupDialog, kLargeIconArea, &iKind, &iHandle, &iRect) ;
 
    // erase the area to draw in
    EraseRect( &iRect ) ;
 
    theErr = PlotIconID( &iRect, atVerticalCenter, ttNone, resIDTable[ userSelection ] ) ;
    
    // now draw the small icon
    
    // get the rect we are drawing in
    GetDialogItem ( thePopupDialog, kSmallIconArea, &iKind, &iHandle, &iRect) ;
 
    // erase the area to draw in
    EraseRect( &iRect ) ;
 
    theErr = PlotIconID( &iRect, atVerticalCenter, ttNone, resIDTable[ userSelection ] ) ;
 
 
 
}
 
 
void DoIconsDialog(void) 
{
    DialogPtr           thePopupDialog ;
    short               itemHit ;
    GrafPtr             savedPort ;
    ModalFilterUPP      modalFilterUPP;
 
    modalFilterUPP = NewModalFilterProc(OurFilter);
    if (modalFilterUPP)
    {
        thePopupDialog = GetNewDialog ( 128, nil, (WindowPtr)-1 );
        if (thePopupDialog)
        {
            SetWRefCon((WindowPtr)thePopupDialog, kIconsDialog ) ;
            GetPort( &savedPort ) ;
            SetPort( thePopupDialog ) ;
            UpdateIconsDialog( thePopupDialog ) ;
 
 
            // get a reference to the popup control, this is item 4 in the dialog
            
            do {
            
                ModalDialog ( modalFilterUPP, &itemHit );
                
                switch ( itemHit ) {
                
                    case kThePopupMenu :
                    
                        UpdateIconsDialog( thePopupDialog ) ;
                        // reset itemHit to something else or we'll continually redraw
                        itemHit = 0 ;
                        break ;
                        
                    case kMoreIconBtn :
                        
                        SetPort( savedPort ) ;
                        DoStdFileIconsDialog() ;
                        SetPort( thePopupDialog ) ;
                        break ;
                
                }
                
            } while( itemHit != ok ) ;
            
            DisposeDialog ( thePopupDialog );
            SetPort( savedPort ) ;
        }
        DisposeRoutineDescriptor (modalFilterUPP);
    }
}
 
 
void    FlashDialogItem(DialogPtr dlg, short itemToFlash)
{
    short   iKind;
    Handle  iHandle;
    Rect    iRect;
    unsigned long   ignored;
 
    GetDialogItem(dlg, itemToFlash, &iKind, &iHandle, &iRect);
    HiliteControl((ControlHandle) iHandle, 1);
    Delay(8, &ignored);
    HiliteControl((ControlHandle) iHandle, 0);
}
 
 
 
 
pascal Boolean OurFilter(DialogPtr dlg, EventRecord *event, short *itemHit)
{
    Boolean result = false;
    short   iKind;
    Handle  iHandle;
    Rect    iRect;
    char    key;
    short   radius;
 
    switch (event->what) {
 
        case keyDown:
        case autoKey:
            key = event->message & charCodeMask;
            if (event->modifiers & cmdKey) {        /* Command key down */
                if (key == kPeriod) {
                    *itemHit = ok;
                    FlashDialogItem(dlg, *itemHit);
                }
                result = true;          /* This says we handle ALL command keys */
            } else {
                if ((key == kReturn) || (key == kEnter)) {
                    *itemHit = ok;
                    FlashDialogItem(dlg, *itemHit);
                    result = true;
                }
                else if (key == kEscape) {
                    *itemHit = ok;
                    FlashDialogItem(dlg, *itemHit);
                    result = true;
                }
            }
            break;
 
        case updateEvt:
            SetPort(dlg);
                
            GetDialogItem(dlg, ok, &iKind, &iHandle, &iRect);           
            InsetRect(&iRect, -4, -4);
            radius = (iRect.bottom - iRect.top) / 2;
            if (radius < 16)
                radius = 16;
                
            PenSize(3,3);
            FrameRoundRect(&iRect, radius, radius);
            PenNormal();
            
            if( GetWRefCon((WindowPtr)dlg ) == kIconsDialog ) 
                UpdateIconsDialog( dlg ) ;
            break;
    }
 
    return result;
}