Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MenuHandler.c
/* |
File: MenuHandler.c |
Contains: Menu-handling routines |
Written by: Forrest Tanaka |
Copyright: Copyright © 1988-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): |
7/13/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
/******************************************************************************\ |
* Header Files |
\******************************************************************************/ |
#ifndef THINK_C |
#include <Desk.h> |
#include <Errors.h> |
#include <Memory.h> |
#include <Menus.h> |
#include <Resources.h> |
#endif |
#include "ColorReset.h" |
#include "MenuHandler.h" |
#include "PictDocument.h" |
/******************************************************************************\ |
* Constants |
\******************************************************************************/ |
#define rMenuBar 128 /* Resource ID of this applicationÕs MBAR resource */ |
#define kNumMenuGuides (mLastMenu - mApple + 1) /* Number of menu guide recs */ |
/******************************************************************************\ |
* Types |
\******************************************************************************/ |
typedef struct |
{ |
MenuHandle theMenu; /* Handle to this guideÕs menu */ |
long enables; /* Current enable flags */ |
} MenuGuide; |
/******************************************************************************\ |
* Prototypes |
\******************************************************************************/ |
void DoAppleMenu( |
short menuItem); |
void DoFileMenu( |
short menuItem); |
void DoEditMenu( |
short menuItem); |
void DoDisplayMenu( |
short menuItem); |
void ResetMenuItems(void); |
void FixDAMenus(void); |
/******************************************************************************\ |
* Variables |
\******************************************************************************/ |
MenuGuide gMenuGuides[kNumMenuGuides]; /* ApplicationÕs menu guide records */ |
/******************************************************************************\ |
* Public: StartMenus |
* |
* The menu guide array is initialized with the menu handles and enable flags of |
* all menus. |
* |
* If GetNewMBar couldnÕt load the MBAR resource, then it returns nil and the |
* error code is in ResError, and I can deal with the error elegantly. But, if |
* the GetNewMBar couldnÕt load the menus themselves, then itÕll probably crash. |
\******************************************************************************/ |
OSErr StartMenus() |
{ |
Handle menuBar; /* Handle to the menu bar from the MBAR resource */ |
short menuIndex; /* Index into menu guide records */ |
OSErr error; |
/* Load in the menu bar */ |
menuBar = GetNewMBar( rMenuBar ); |
if (menuBar != nil) |
{ |
/* Set it, then dispose of it because SetMenuBar makes a copy */ |
SetMenuBar( menuBar ); |
DisposeHandle( menuBar ); |
/* Add the desk accessories to the Apple menu */ |
AppendResMenu( GetMenuHandle( mApple ), 'DRVR' ); |
/* Initialize the menu guide array */ |
for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++) |
{ |
gMenuGuides[menuIndex].theMenu = GetMenuHandle( menuIndex + mApple ); |
gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex]. |
theMenu).enableFlags; |
} |
/* Draw the menu bar */ |
DrawMenuBar(); |
error = noErr; |
} |
else |
{ |
error = ResError(); |
if (error == noErr) |
error = resNotFound; |
if (error != resNotFound && error != memFullErr) |
error = dsSysErr; |
} |
return error; |
} |
/******************************************************************************\ |
* Public: DoMenuChoice |
* |
* This routine should be self-explanatory. |
\******************************************************************************/ |
void DoMenuChoice( |
long menuChoice) /* Return value from MenuSelect or MenuKey */ |
{ |
short menuNum; /* Menu number of chosen menu */ |
short menuItem; /* Item number of chosen menu item */ |
if (menuChoice != 0) |
{ |
/* Get the chosen menu item and menu number */ |
menuNum = hiWord( menuChoice ); |
menuItem = loWord( menuChoice ); |
/* Dispatch the appropriate menu-handling routine */ |
if (menuNum == mApple) |
DoAppleMenu( menuItem ); |
else if (menuNum == mFile) |
DoFileMenu( menuItem ); |
else if (menuNum == mEdit) |
DoEditMenu( menuItem ); |
else if (menuNum == mDisplay) |
DoDisplayMenu( menuItem ); |
HiliteMenu( 0 ); |
} |
} |
/******************************************************************************\ |
* Private: DoAppleMenu - Handle an Apple menu item choice |
* |
* This routine is called whenever itÕs determined that the chosen menu item was |
* in the Apple menu. If the chosen menu item thatÕs passed in the menuItem |
* parameter wasnÕt the About item, the name of the menu item is retrieved and |
* then OpenDeskAcc is called with this name so that the desk accessory by that |
* name is opened. The Process Manager can launch desk accessories, but |
* OpenDeskAcc should still be used if the user chooses any item in the Apple |
* menu. |
\******************************************************************************/ |
static void DoAppleMenu( |
short menuItem) /* Chosen menu item */ |
{ |
Str255 daName; /* Name of the chosen DA */ |
short refNum; /* Reference number of the DA, ignored */ |
if (menuItem != iAbout) |
{ |
GetMenuItemText( GetMenuHandle( mApple ), menuItem, /*<*/daName ); |
refNum = OpenDeskAcc( daName ); |
} |
} |
/******************************************************************************\ |
* Private: DoFileMenu - Handle a File menu item choice |
* |
* This routine is called whenever itÕs determined that the chosen menu item was |
* in the File menu. The item number of the chosen menu item is passed in the |
* menuItem parameter. |
\******************************************************************************/ |
static void DoFileMenu( |
short menuItem) /* Chosen menu item */ |
{ |
if (menuItem == iOpen) |
(void)DoOpenPictDoc(); |
else if (menuItem == iClose) |
{ |
if (IsPictDocWindow( FrontWindow() )) |
DoClosePictDoc( FrontWindow() ); |
} |
else if (menuItem == iSaveAs) |
{ |
if (IsPictDocWindow( FrontWindow() )) |
DoSaveAsPictDoc( FrontWindow() ); |
} |
else if (menuItem == iQuit) |
DoQuit(); |
} |
/******************************************************************************\ |
* Private: DoEditMenu - Handle a Edit menu item choice |
* |
* This routine is called whenever itÕs determined that the chosen menu item was |
* in the Edit menu. The item number of the chosen menu item is passed in the |
* menuItem parameter. |
\******************************************************************************/ |
static void DoEditMenu( |
short menuItem) /* Chosen menu item */ |
{ |
SystemEdit( menuItem - 1 ); |
} |
/******************************************************************************\ |
* Private: DoEditMenu - Handle a Edit menu item choice |
* |
* This routine is called whenever itÕs determined that the chosen menu item was |
* in the Edit menu. The item number of the chosen menu item is passed in the |
* menuItem parameter. |
\******************************************************************************/ |
static void DoDisplayMenu( |
short menuItem) /* Chosen menu item */ |
{ |
if (menuItem == 1) |
RestoreColorsPalette(); |
else if (menuItem == 2) |
RestoreColorsSlam(); |
} |
/******************************************************************************\ |
* Public: FixMenus |
* |
* FixMenus first disables every available menu item. Then the most basic menu |
* items are enabled. The windowKind field of the front window is then checked. |
* If there is a window open, FixMenus calls a routine thatÕs responsible for |
* that kind of window to enable any menu items that are relevant to that kind of |
* window. |
* |
* If the front window is a modal dialog, then the basic set of menu items are |
* ! enabled, and the entire Apple menu is disabled. |
* |
* After this is done, the menu bar might have to be redrawn to reflect the new |
* conditions. So, FixMenus go through every menu to determine if the state of |
* the entire menu has changed. The MenuGuide records are used to help determine |
* this. If the state of any many has changed, then the menu bar is redrawn. |
\******************************************************************************/ |
void FixMenus() |
{ |
WindowPtr currWindow; /* Pointer to the front-most window */ |
MenuHandle aMenu; /* Handle to menu being enabled */ |
long oldEnables; /* True if 1+ items enabled when FixMenus called */ |
long newEnables; /* True if 1+ items enabled after menus fixed */ |
Boolean mustRedraw; /* True if menu bar has to be redrawn */ |
short numItems; /* Number of items in a menu */ |
short menuIndex; /* Index into menu guide array */ |
/* Start by disabling all menus */ |
ResetMenuItems(); |
/* Front-most window determines most menu enabling/disabling */ |
currWindow = FrontWindow(); |
/* Depending on the type of the front window, enable appropriate items */ |
if (IsDAWindow( currWindow )) |
FixDAMenus(); |
else if (IsPictDocWindow( currWindow )) |
FixPictDocMenus( currWindow ); |
/* Enable some menus */ |
aMenu = GetMenuHandle( mFile ); |
EnableItem( aMenu, iOpen ); |
/* Assume we donÕt have to redraw the menu bar */ |
mustRedraw = false; |
/* Check through every menu to see if there are any enabled items in it */ |
for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++) |
{ |
/* Grab the old and new enable flags excluding flag for entire menu */ |
oldEnables = gMenuGuides[menuIndex].enables & 0xFFFFFFFE; |
newEnables = (**gMenuGuides[menuIndex].theMenu).enableFlags & |
0xFFFFFFFE; |
/* Shift left so that we only see flags for existing items */ |
numItems = CountMItems(gMenuGuides [menuIndex].theMenu); |
oldEnables = oldEnables << (31 - numItems); |
newEnables = newEnables << (31 - numItems); |
/* Determine if the menu bar must be redrawn */ |
if (((oldEnables != 0) && (newEnables == 0)) || numItems == 0) |
{ |
/* Had some items enabled, now has no items enabled, redraw */ |
DisableItem( gMenuGuides[menuIndex].theMenu, 0 ); |
mustRedraw = true; |
} |
else if ((oldEnables == 0) && (newEnables != 0)) |
{ |
/* Had no items enabled, now has some items enabled, redraw */ |
EnableItem( gMenuGuides[menuIndex].theMenu, 0) ; |
mustRedraw = true; |
} |
/* Update our copy of the enable flags */ |
gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex].theMenu). |
enableFlags; |
} |
/* If at least one menu has changed state, must redraw the menu bar */ |
if (mustRedraw) |
DrawMenuBar(); |
} |
/******************************************************************************\ |
* Private: ResetMenuItems - Disable any disableable items and clear marks |
* |
* Disabling all the menu items is done bruteforcedly. It could easily be done |
* by looping through each menu and disabling every item that comes up (disabling |
* the Font menu is done this way), but I thought doing it using the brute-force |
* method was clearer. Then again. . . |
\******************************************************************************/ |
static void ResetMenuItems () |
{ |
MenuHandle aMenu; /* Handle to each menu weÕre disabling */ |
/* Disable items in the File menu */ |
aMenu = GetMenuHandle( mFile ); |
DisableItem( aMenu, iOpen ); |
DisableItem( aMenu, iClose ); |
DisableItem( aMenu, iSaveAs ); |
/* Disable items in the Edit menu */ |
aMenu = GetMenuHandle( mEdit ); |
DisableItem( aMenu, iUndo ); |
DisableItem( aMenu, iCut ); |
DisableItem( aMenu, iCopy ); |
DisableItem( aMenu, iPaste ); |
DisableItem( aMenu, iClear ); |
} |
/******************************************************************************\ |
* Private: FixDAMenus - Enable any menu items relevant for desk accessories |
* |
* Desk accessories can use the Edit menu, so the standard Edit menu items are |
* enabled. |
\******************************************************************************/ |
static void FixDAMenus() |
{ |
MenuHandle aMenu; /* Handle to each menu weÕre enabling */ |
/* Disable items in the Process menu */ |
aMenu = GetMenuHandle( mEdit ); |
EnableItem( aMenu, iUndo ); |
EnableItem( aMenu, iCut ); |
EnableItem( aMenu, iCopy ); |
EnableItem( aMenu, iPaste ); |
EnableItem( aMenu, iClear ); |
} |
/******************************************************************************\ |
* Public: DisableAllMenus |
* |
* |
\******************************************************************************/ |
void DisableAllMenus() |
{ |
short menuIndex; /* Index into menu guide array */ |
/* Check through every menu to see if there are any enabled items in it */ |
for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++) |
DisableItem( gMenuGuides[menuIndex].theMenu, 0 ); |
} |
/******************************************************************************\ |
* Public: RestoreAllMenus |
* |
* |
\******************************************************************************/ |
void ReenableAllMenus() |
{ |
short menuIndex; /* Index into menu guide array */ |
/* Check through every menu to see if there are any enabled items in it */ |
for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++) |
if ( gMenuGuides[menuIndex].enables & 1 ) |
EnableItem( gMenuGuides[menuIndex].theMenu, 0 ); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-12