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.
Source/SR_MacDialog.c
/****************************************************************************** |
** ** |
** Module: SR_MacDialog.c ** |
** ** |
** ** |
** Purpose: Modal dialog routines ** |
** ** |
** ** |
** ** |
** Copyright (C) 1996-1997 Apple Computer, Inc. All rights reserved. ** |
** ** |
** ** |
*****************************************************************************/ |
#include "QD3D.h" |
#include "QD3DExtension.h" |
#if defined(WINDOW_SYSTEM_MACINTOSH) && WINDOW_SYSTEM_MACINTOSH |
#define BUILDING_FOR_SYSTEM7 1 |
#include <assert.h> |
#include <Dialogs.h> |
#include <Sound.h> |
#include <string.h> |
#include <Devices.h> |
#include <ToolUtils.h> |
#include <Aliases.h> |
#include <Resources.h> |
#include <TextUtils.h> |
#include "SR.h" |
#include "SR_MacDialog.h" |
/****************************************************************************** |
** ** |
** Dialog ID's ** |
** ** |
*****************************************************************************/ |
#define SR_DLOG_ID 128 |
#define SR_MOVABLE_DLOG_ID 129 |
#define SR_DLOG_OK 1 |
#define SR_DLOG_CANCEL 2 |
#define SR_DLOG_CHECKBOX 3 |
/****************************************************************************** |
** ** |
** Forward Declarations ** |
** ** |
*****************************************************************************/ |
static TQ3Status SR_ModalDialog( |
TQ3RendererObject renderer, |
TQ3Boolean *canceled, |
void *rendererPrivate); |
static TQ3Status SR_MovableModalDialog( |
TQ3RendererObject renderer, |
TQ3DialogAnchor dialogAnchor, |
TQ3Boolean *canceled, |
void *rendererPrivate); |
static DialogPtr SR_LoadDialog( |
short dlogId, |
void *rendererPrivate); |
static TQ3Status HandleHit( |
DialogPtr dialog, |
short itemHit, |
TQ3Boolean *done, |
TQ3RendererObject renderer, |
TQ3Boolean *canceled, |
void *rendererPrivate); |
static TQ3Boolean HandledEvent( |
EventRecord *event, |
DialogPtr dialog, |
short *itemHit, |
TQ3Boolean *done, |
TQ3RendererObject renderer, |
TQ3Boolean *canceled, |
void *rendererPrivate); |
static void HandleMenuClick( |
long menuItem); |
static void DrawDefaultButtonOutline( |
DialogPtr dialog, |
short item); |
Boolean ModalDialogFilter( |
DialogPtr dialog, |
EventRecord *event, |
short *itemHit); |
void SimulateButtonClick( |
DialogPtr dialog, |
short item); |
/****************************************************************************** |
** ** |
** Globals ** |
** ** |
*****************************************************************************/ |
static ModalFilterUPP SRgModalFilterUPP = NULL; |
/* |
* The next two statics are needed to set and reset the Resource chain prior to |
* calling out to the applications Event handler |
*/ |
static short SRgOldResFile, |
SRgResFile; |
extern AliasHandle SRgAliasHandle; |
/****************************************************************************** |
** ** |
** Naming Routines ** |
** ** |
*****************************************************************************/ |
/*===========================================================================*\ |
* |
* Routine: SR_GetNameString() |
* |
* Comments: |
* |
\*===========================================================================*/ |
TQ3Status SR_GetNameString( |
unsigned char *dataBuffer, |
unsigned long bufferSize, |
unsigned long *actualDataSize) |
{ |
TQ3Status status = kQ3Success; |
Boolean wasChanged; |
FSSpec fileSpec; |
OSErr macErr; |
Str255 tempBuffer; |
/* |
* Get at the resource file for this renderer and open the resource |
* file, locate the renderer name string and close the res file |
* returning the string in the buffer we were passed. |
*/ |
SRgOldResFile = CurResFile(); |
macErr = ResolveAlias(NULL, SRgAliasHandle, &fileSpec, &wasChanged); |
if (macErr == noErr) { |
SRgResFile = FSpOpenResFile(&fileSpec, fsRdPerm); |
if (SRgResFile != -1) { |
*actualDataSize = 0L; |
GetIndString(tempBuffer, SR_NAME_RESOURCE, 1); |
/* trim the buffer if necessary */ |
*actualDataSize = (tempBuffer[0] > bufferSize) ? |
bufferSize : tempBuffer[0]; |
if (dataBuffer != NULL) { |
/* copy from the pascal str returned by the res mgr */ |
memcpy( |
(char *)dataBuffer, |
(char *) &tempBuffer[1], |
*actualDataSize ); |
/* and terminate the string */ |
dataBuffer[*actualDataSize] = '\0'; |
} |
CloseResFile(SRgResFile); |
UseResFile(SRgOldResFile); |
} else { |
Q3XMacintoshError_Post(ResError()); |
status = kQ3Failure; |
} |
} else { |
Q3XMacintoshError_Post(macErr); |
status = kQ3Failure; |
} |
if (status == kQ3Failure || ResError()) { |
*actualDataSize = 0L; |
dataBuffer = NULL; |
} |
return (status); |
} |
/****************************************************************************** |
** ** |
** Dialog Routines ** |
** ** |
*****************************************************************************/ |
/*===========================================================================*\ |
* |
* Routine: SR_MacModalDialog() |
* |
* Comments: |
* |
\*===========================================================================*/ |
TQ3Status SR_MacModalDialog( |
TQ3RendererObject renderer, |
TQ3DialogAnchor dialogAnchor, |
TQ3Boolean *canceled, |
void *rendererPrivate) |
{ |
TQ3Status status; |
Boolean wasChanged; |
FSSpec fileSpec; |
OSErr macErr; |
SRgOldResFile = CurResFile(); |
macErr = ResolveAlias(NULL, SRgAliasHandle, &fileSpec, &wasChanged); |
if (macErr == noErr) { |
SRgResFile = FSpOpenResFile(&fileSpec, fsRdPerm); |
if (SRgResFile != -1) { |
if (dialogAnchor.clientEventHandler == NULL) { |
status = SR_ModalDialog(renderer, canceled, rendererPrivate); |
} else { |
status = SR_MovableModalDialog( |
renderer, |
dialogAnchor, |
canceled, |
rendererPrivate); |
} |
CloseResFile(SRgResFile); |
UseResFile(SRgOldResFile); |
} else { |
Q3XMacintoshError_Post(ResError()); |
return (kQ3Failure); |
} |
} else { |
Q3XMacintoshError_Post(macErr); |
status = kQ3Failure; |
} |
return (status); |
} |
/*===========================================================================*\ |
* |
* Routine: SR_MacModalDialog() |
* |
* Comments: |
* |
\*===========================================================================*/ |
TQ3Status SR_ModalDialog( |
TQ3RendererObject renderer, |
TQ3Boolean *canceled, |
void *rendererPrivate) |
{ |
DialogPtr dialog; |
short itemHit; |
TQ3Boolean done = kQ3False; |
TQ3Status status = kQ3Success; |
if (SRgModalFilterUPP == NULL) { |
SRgModalFilterUPP = NewModalFilterProc(ModalDialogFilter); |
} |
if (SRgModalFilterUPP == NULL) { |
Q3XMacintoshError_Post(MemError()); |
return (kQ3Failure); |
} |
dialog = SR_LoadDialog(SR_DLOG_ID, rendererPrivate); |
if (dialog != NULL) { |
do { |
ModalDialog(SRgModalFilterUPP, &itemHit); |
HandleHit( |
dialog, itemHit, &done, renderer, canceled, rendererPrivate); |
} while (done == kQ3False); |
DisposeDialog(dialog); |
} else { |
Q3XMacintoshError_Post(ResError()); |
status = kQ3Failure; |
} |
return (status); |
} |
/*===========================================================================*\ |
* |
* Routine: ModalDialogFilter() |
* |
* Comments: |
* |
\*===========================================================================*/ |
Boolean ModalDialogFilter( |
DialogPtr dialog, |
EventRecord *event, |
short *itemHit) |
{ |
Boolean handled = kQ3False; |
char key; |
long menuItem; |
switch (event->what) { |
case keyDown: { |
key = (char) (event->message & charCodeMask); |
if (key == '\r' || key == '\3') { |
*itemHit = SR_DLOG_OK; |
handled = kQ3True; |
SimulateButtonClick(dialog, SR_DLOG_OK); |
} else if (key == '\33' || |
((event->modifiers & cmdKey) && key == '.')) { |
*itemHit = SR_DLOG_CANCEL; |
handled = kQ3True; |
SimulateButtonClick(dialog, SR_DLOG_CANCEL); |
} else if (event->modifiers & cmdKey) { |
menuItem = MenuKey(key); |
if (menuItem) { |
HandleMenuClick(menuItem); |
handled = kQ3True; |
} |
} |
break; |
} |
case updateEvt: { |
if ((DialogPtr) (event->message) == dialog) { |
DrawDefaultButtonOutline(dialog, SR_DLOG_OK); |
} |
break; |
} |
} |
return (handled); |
} |
/*===========================================================================*\ |
* |
* Routine: DrawDefaultButtonOutline() |
* |
* Comments: |
* |
\*===========================================================================*/ |
void DrawDefaultButtonOutline( |
DialogPtr dialog, |
short item) |
{ |
short iType; |
Rect iRect; |
Handle iHandle; |
GrafPtr oldPort; |
PenState oldPenState; |
short buttonOval; |
GetDialogItem(dialog, item, &iType, &iHandle, &iRect); |
GetPort(&oldPort); |
SetPort((**((ControlHandle) iHandle)).contrlOwner); |
GetPenState(&oldPenState); |
PenNormal(); |
InsetRect(&iRect, -4, -4); |
FrameRoundRect(&iRect, 16, 16); |
buttonOval = (iRect.bottom - iRect.top) / 2 + 2; |
PenSize(3, 3); |
FrameRoundRect(&iRect, buttonOval, buttonOval); |
SetPenState(&oldPenState); |
SetPort(oldPort); |
} |
/*===========================================================================*\ |
* |
* Routine: SR_MacModalDialog() |
* |
* Comments: |
* |
\*===========================================================================*/ |
TQ3Status SR_MovableModalDialog( |
TQ3RendererObject renderer, |
TQ3DialogAnchor dialogAnchor, |
TQ3Boolean *canceled, |
void *rendererPrivate) |
{ |
DialogPtr dialog, whichDlog; |
short itemHit; |
TQ3Boolean done = kQ3False, handled = kQ3False; |
EventRecord event; |
dialog = SR_LoadDialog(SR_MOVABLE_DLOG_ID, rendererPrivate); |
if (dialog == NULL) { |
Q3XMacintoshError_Post(ResError()); |
return (kQ3Failure); |
} |
do { |
/* |
* If your dialog handles DiskEvents then include it in the EventMask |
* The extra test (event.what == nullEvent) is so we can pass on null |
* events to the app so it can do background processing. |
*/ |
if (WaitNextEvent(everyEvent & ~diskMask, &event, 1, NULL) || |
(event.what == nullEvent)) { |
if (HandledEvent( |
&event, |
dialog, |
&itemHit, |
&done, |
renderer, |
canceled, |
rendererPrivate) == kQ3False) { |
if (IsDialogEvent(&event)) { |
/* |
* This is kind of wierd. If the event is a nullevent |
* then we want to give the dialog and the app a shot at |
* handling it. Hence the next statement. |
*/ |
handled = (TQ3Boolean) (event.what != nullEvent); |
if (DialogSelect(&event, &whichDlog, &itemHit) && |
whichDlog == dialog) { |
HandleHit( |
dialog, |
itemHit, |
&done, |
renderer, |
canceled, |
rendererPrivate); |
} |
} |
if (!handled) { |
/* |
* At this point we have checked for all events |
* that we are interested in. Give the app a shot |
* at the event |
* |
* Restore the old Resource file ordering |
*/ |
UseResFile(SRgOldResFile); |
/* |
* The app's event-handler |
*/ |
(dialogAnchor.clientEventHandler)(&event); |
/* |
* Call me paranoid, but just in case the app |
* opens another resource file |
*/ |
SRgOldResFile = CurResFile(); |
/* |
* Set it back to ours |
*/ |
UseResFile(SRgResFile); |
} |
} |
} |
} while (done == kQ3False); |
DisposeDialog(dialog); |
return (kQ3Success); |
} |
/*===========================================================================*\ |
* |
* Routine: SR_LoadDialog() |
* |
* Comments: |
* |
\*===========================================================================*/ |
DialogPtr SR_LoadDialog( |
short dlogId, |
void *rendererPrivate) |
{ |
short iType, checkBoxVal; |
Rect iRect; |
Handle iHandle; |
DialogPtr dialog; |
dialog = GetNewDialog(dlogId, NULL, (WindowPtr) -1); |
GetDialogItem(dialog, SR_DLOG_CHECKBOX, &iType, &iHandle, &iRect); |
checkBoxVal = ((TSRPrivate *) rendererPrivate)->dummyConfigData; |
SetControlValue((ControlHandle) iHandle, checkBoxVal); |
ShowWindow(dialog); |
return (dialog); |
} |
/*===========================================================================*\ |
* |
* Routine: HandledEvent() |
* |
* Comments: |
* |
\*===========================================================================*/ |
TQ3Boolean HandledEvent( |
EventRecord *event, |
DialogPtr dialog, |
short *itemHit, |
TQ3Boolean *done, |
TQ3RendererObject renderer, |
TQ3Boolean *canceled, |
void *rendererPrivate) |
{ |
short part; |
WindowPtr whichWindow; |
TQ3Boolean handled = kQ3False; |
char key; |
long menuItem; |
switch (event->what) { |
case mouseDown: |
part = FindWindow(event->where, &whichWindow); |
switch (part) { |
case inDrag: { |
handled = kQ3True; |
if (whichWindow == dialog) { |
DragWindow( |
dialog, |
event->where, |
&((*GetGrayRgn())->rgnBBox)); |
} else { |
SysBeep(30); |
} |
break; |
} |
case inContent: |
case inGrow: |
case inGoAway: |
case inZoomIn: |
case inZoomOut: { |
if (whichWindow != dialog) { |
handled = kQ3True; |
SysBeep(30); |
} |
break; |
} |
case inMenuBar: { |
handled = kQ3True; |
menuItem = MenuSelect(event->where); |
HandleMenuClick(menuItem); |
break; |
} |
} |
break; |
case keyDown: { |
key = (char) (event->message & charCodeMask); |
if (key == '\r' || key == '\3') { |
*itemHit = SR_DLOG_OK; |
handled = kQ3True; |
SimulateButtonClick(dialog, SR_DLOG_OK); |
HandleHit( |
dialog, *itemHit, done, renderer, canceled, rendererPrivate); |
} else if (key == '\33' || |
((event->modifiers & cmdKey) && key == '.')) { |
*itemHit = SR_DLOG_CANCEL; |
handled = kQ3True; |
SimulateButtonClick(dialog, SR_DLOG_CANCEL); |
HandleHit( |
dialog, *itemHit, done, renderer, canceled, rendererPrivate); |
} else if (event->modifiers & cmdKey) { |
menuItem = MenuKey(key); |
if (menuItem) { |
HandleMenuClick(menuItem); |
handled = kQ3True; |
} |
} |
break; |
} |
case updateEvt: { |
if ((DialogPtr) (event->message) == dialog) { |
DrawDefaultButtonOutline(dialog, SR_DLOG_OK); |
} |
break; |
} |
} |
return (handled); |
} |
/*===========================================================================*\ |
* |
* Routine: HandleMenuClick() |
* |
* Comments: |
* |
\*===========================================================================*/ |
void HandleMenuClick( |
long menuItem) |
{ |
short item = LoWord(menuItem); |
short menu = HiWord(menuItem); |
MenuHandle menuH; |
Str255 itemText; |
if (menuItem) { |
menuH = GetMenuHandle(menu); |
GetMenuItemText(menuH, item, itemText); |
/* |
* This is ugly. |
* We compare names of the menus because we don't know what the |
* application's Menu IDs are. I am using constant strings this will |
* not work on non English systems. You should proabably load some |
* STR resources and compare against them so that the Renderer can be |
* localized. |
*/ |
if (strncmp((char *) (**menuH).menuData, (char *) "\pEdit", 5) == 0) { |
if (strncmp((char *) itemText, (char *) "\pUndo", 5) == 0) { |
/* |
* Handle Undo if supported |
*/ |
} else if (strncmp((char *) itemText, (char *) "\pCut", 4) == 0) { |
/* |
* Handle Cut if supported - use DialogCut |
*/ |
} else if (strncmp((char *) itemText, (char *) "\pCopy", 5) == 0) { |
/* |
* Handle Copy if supported - use DialogCopy |
*/ |
} else if (strncmp((char *) itemText, (char *) "\pPaste", 6) == 0) { |
/* |
* Handle Paste if supported - use DialogPaste |
*/ |
} else if (strncmp((char *) itemText, (char *) "\pClear", 6) == 0) { |
/* |
* Handle Clear if supported |
*/ |
} else { |
/* |
* Nothing else should be selectable in the Edit Menu |
* The calling application should have disabled all others |
* SysBeep or Alert to notify user of error |
*/ |
SysBeep(30); |
} |
} else if (strncmp( |
(char *) (**menuH).menuData, |
(char *) "\x01\x14", 2) == 0) { |
/* |
* Apple menu was selected. All application specific items |
* in the Apple Menu such as "About..." should have been |
* disabled by the app |
*/ |
OpenDeskAcc(itemText); |
} else { |
/* |
* No other menu should be selectable |
* The calling application should have disabled all others |
* SysBeep or Alert to notify user of error |
*/ |
SysBeep(30); |
} |
HiliteMenu(0); |
} |
} |
/*===========================================================================*\ |
* |
* Routine: HandleHit() |
* |
* Comments: |
* |
\*===========================================================================*/ |
TQ3Status HandleHit( |
DialogPtr dialog, |
short itemHit, |
TQ3Boolean *done, |
TQ3RendererObject renderer, |
TQ3Boolean *canceled, |
void *rendererPrivate) |
{ |
short iType, checkBoxVal; |
Rect iRect; |
Handle iHandle; |
UNUSED(renderer); |
switch (itemHit) { |
case SR_DLOG_OK: |
GetDialogItem(dialog, SR_DLOG_CHECKBOX, &iType, &iHandle, &iRect); |
((TSRPrivate *) rendererPrivate)->dummyConfigData = |
GetControlValue((ControlHandle) iHandle); |
*done = kQ3True; |
*canceled = kQ3False; |
break; |
case SR_DLOG_CANCEL: |
*done = kQ3True; |
*canceled = kQ3True; |
break; |
case SR_DLOG_CHECKBOX: |
GetDialogItem(dialog, SR_DLOG_CHECKBOX, &iType, &iHandle, &iRect); |
checkBoxVal = GetControlValue((ControlHandle) iHandle); |
SetControlValue((ControlHandle) iHandle, !checkBoxVal); |
break; |
} |
return (kQ3Success); |
} |
/*===========================================================================*\ |
* |
* Routine: SimulateButtonClick() |
* |
* Comments: |
* |
\*===========================================================================*/ |
void SimulateButtonClick( |
DialogPtr dialog, |
short item) |
{ |
short iType; |
Rect iRect; |
Handle iHandle; |
long ticks; |
GetDialogItem(dialog, item, &iType, &iHandle, &iRect); |
HiliteControl((ControlHandle) iHandle, kControlButtonPart); |
ticks = TickCount() + 8; |
while (TickCount() < ticks) { |
/* |
* Spin... |
*/ |
} |
HiliteControl((ControlHandle) iHandle, 0); |
} |
#endif /* WINDOW_SYSTEM_MACINTOSH */ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14