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.
BigEasy/BigEasyDialogs.c
/* |
File: BigEasyDialogs.c |
Contains: xxx put contents here xxx |
Written by: xxx put writers here xxx |
Copyright: © 1992, 1994 by Apple Computer, Inc., all rights reserved. |
Change History (most recent first): |
<8> 5/27/94 dvb This&that |
<5+> 5/5/93 dvb Fields & controls. |
<5> 5/5/93 dvb |
<4> 1/7/93 dvb Improve number-dialog with +/- keys. Make it compile under mpw. |
<3> 4/13/92 dvb Allow windows to idle behind dialogue. Pass activate/deactivates |
to back windows. |
<2> 4/3/92 dvb New calls for getting text & numbers. |
<1> 1/20/92 dvb first checked in |
*/ |
/* file: BigEasyDialogs.c |
* |
* Started 2 Jan 1992, more or less. |
* |
*/ |
/*-------------------------- |
Inclusions |
--------------------------*/ |
#include <Windows.h> |
#include <Dialogs.h> |
#include <Controls.h> |
#include <OSUtils.h> |
#include <ToolUtils.h> |
#include <Resources.h> |
#include <TextEdit.h> |
#include <Memory.h> |
#include <BDC.h> |
#include <Packages.h> |
#include <Icons.h> |
#include "BigEasyDialogs.h" |
#include "BigEasyTextish.h" |
#include "BigEasy2.h" |
/*-------------------------- |
Constants |
--------------------------*/ |
#define kButtonHeight 20 |
#define kButtonWindowMargin 10 |
#define kButtonTextMargin 20 |
#define kOSEvent app4Evt /* event used by MultiFinder */ |
#define kSuspendResumeMessage 1 /* high byte of suspend/resume event message */ |
/*-------------------------- |
Local Data |
--------------------------*/ |
typedef struct |
{ |
StringPtr header; |
StringPtr body; |
short iconID; |
} EasyDialogMessageStuff; |
static EasyDialogButtonList dOkayCancelButtonList = |
{ |
2,0,1, |
"\pOkay",0, |
"\pCancel",0 |
}; |
static EasyDialogButtonList dSaveDiscardCancelButtonList = |
{ |
3,0,2, |
"\pSave",0, |
"\pDiscard",'D', |
"\pCancel",0 |
}; |
static Boolean gNumbers = false; /* true if we're getting a number string */ |
/*-------------------------- |
Local Prototypes |
--------------------------*/ |
static void EasyDialogMessageUpdateProc(long refcon,const Rect *updateRect); |
static void BlinkButton(ControlHandle buttonControl); |
static void BlinkItem(DialogPtr theDialog,short item); |
static pascal Boolean MyModalFilterProc(DialogPtr theDialog, |
EventRecord *theEvent, short *itemHit); |
static pascal Boolean MyFieldModalFilterProc(DialogPtr theDialog, |
EventRecord *theEvent,short *itemHit); |
/*-------------------------- |
Roughage |
--------------------------*/ |
long EasyDialog(Rect *windowRect, |
beDialogUpdate updateProc, |
beDialogKey keyProc, |
beDialogClick clickProc, |
beDialogIdle idleProc, |
EasyDialogButtonList *buttonList, |
long refcon) |
{ |
WindowPtr w; |
Rect r,s,updateRect; |
short i; |
short biggestButton,x; |
ControlHandle ch[20]; |
Rect defaultButtonRect; |
EventRecord er; |
Boolean done; |
long saveMenus; |
long result; |
long eventCount; |
#pragma unused (clickProc) |
HiliteMenu(0); |
r = *windowRect; |
if(r.left <= 0) |
{ |
s = qd.screenBits.bounds; |
OffsetRect(&r, |
(s.left + s.right - r.left - r.right)/2, |
(s.top + s.bottom - r.top - r.bottom)/2); |
} |
saveMenus = DisableAllMenus(); |
i = gSystemVersion > 0x700 ? movableDBoxProc : dBoxProc; |
if(gHasColor) |
w = NewCWindow(0,&r,"\p",true,i,(WindowPtr)-1,false,0); |
else |
w = NewWindow(0,&r,"\p",true,i,(WindowPtr)-1,false,0); |
SetPort(w); |
r.right -= r.left; |
r.bottom -= r.top; |
r.left = r.top = 0; |
updateRect = r; |
updateRect.bottom -= 2*kButtonWindowMargin + kButtonHeight; |
if((long)buttonList <= 0) |
{ |
if(buttonList == kEasyDialogSaveDiscardCancel) |
buttonList = &dSaveDiscardCancelButtonList; |
else |
{ |
if(buttonList == kEasyDialogOkayCancel) |
{ |
dOkayCancelButtonList.count = 2; |
dOkayCancelButtonList.defaultButton = 0; |
dOkayCancelButtonList.cancelButton = 1; |
} |
else if(buttonList == kEasyDialogCancelOkay) |
{ |
dOkayCancelButtonList.count = 2; |
dOkayCancelButtonList.defaultButton = 1; |
dOkayCancelButtonList.cancelButton = 1; |
} |
else |
{ |
dOkayCancelButtonList.count = 1; |
dOkayCancelButtonList.defaultButton = 0; |
dOkayCancelButtonList.cancelButton = -1; |
} |
buttonList = &dOkayCancelButtonList; |
} |
} |
if(buttonList->defaultButton >= buttonList->count) |
buttonList->defaultButton = -1; |
if(buttonList->cancelButton >= buttonList->count) |
buttonList->cancelButton = -1; |
TextFont(0); |
TextSize(12); |
biggestButton = 0; |
for(i = 0; i<buttonList->count; i++) |
{ |
x = StringWidth(buttonList->button[i].name); |
if(x > biggestButton) |
biggestButton = x; |
} |
biggestButton += kButtonTextMargin; |
s.left = kButtonWindowMargin; |
s.bottom = r.bottom - kButtonWindowMargin; |
s.right = s.left + biggestButton; |
s.top = s.bottom - kButtonHeight; |
biggestButton += kButtonWindowMargin; |
for(i = 0; i<buttonList->count; i++) |
{ |
ch[i] = NewControl(w,&s,buttonList->button[i].name,true,0,0,1,pushButProc,i); |
if(i == buttonList->defaultButton) |
{ |
defaultButtonRect = s; |
InsetRect(&defaultButtonRect,-4,-4); |
} |
OffsetRect(&s,biggestButton,0); |
} |
done = false; |
while(!done) |
{ |
if(eventCount ++ & 1) |
{ |
if(idleProc) |
(*idleProc)(refcon); |
IdleWindow(-1); |
} |
WaitNextEvent(0xffff,&er,0,nil); |
switch (er.what) |
{ |
case 0: |
break; |
case mouseDown: |
{ |
WindowPtr clickWindow; |
short part; |
ControlHandle whichControl; |
part = FindWindow (er.where, &clickWindow); |
if(part == inMenuBar) |
{ |
long p; |
p = MenuSelect(er.where); |
} |
else if(part == inDrag |
&& (clickWindow == w || er.modifiers & cmdKey)) |
DragWindow(clickWindow,er.where,&gBigRect); |
else if(part != inContent || clickWindow != w) |
SysBeep(1); |
else |
{ |
GlobalToLocal(&er.where); |
FindControl(er.where,w,&whichControl); |
if(whichControl) |
{ |
if(TrackControl(whichControl,er.where,nil)) |
{ |
done = true; |
result = GetCRefCon(whichControl); |
} |
} |
} |
} |
break; |
case activateEvt: |
activateEvent: |
HandleActivateEvent(&er); |
InitCursor(); |
break; |
case updateEvt: |
if(er.message != (long)w) |
{ |
HandleUpdateEvent(&er); |
SetPort(w); |
} |
else |
{ |
BeginUpdate(w); |
DrawControls(w); |
if(buttonList->defaultButton >= 0) |
{ |
PenSize(3,3); |
FrameRoundRect(&defaultButtonRect,16,16); |
PenNormal(); |
} |
PenPat(&qd.gray); |
MoveTo(updateRect.left + kButtonWindowMargin,updateRect.bottom); |
LineTo(updateRect.right - kButtonWindowMargin,updateRect.bottom); |
PenNormal(); |
if(updateProc) |
(*updateProc)(refcon,&updateRect); |
EndUpdate(w); |
} |
break; |
case keyDown: |
{ |
er.message &= 0x000000ff; |
if( (er.message == 13 || er.message == 3) |
&& buttonList->defaultButton >= 0) /* enter or return */ |
{ |
BlinkButton(ch[buttonList->defaultButton]); |
done = true; |
result = buttonList->defaultButton; |
} |
else if( ((er.message == '.' && (er.modifiers & cmdKey)) || er.message == 27) |
&& buttonList->cancelButton >= 0) /* esc or cmd-. */ |
{ |
BlinkButton(ch[buttonList->cancelButton]); |
done = true; |
result = buttonList->cancelButton; |
} |
else if (er.modifiers & cmdKey) /* a key-equiv? */ |
{ |
short capKey; |
capKey = er.message; |
if(capKey >= 'a' && capKey <= 'z') |
capKey += 'A' - 'a'; |
for(i = 0; i < buttonList->count; i++) |
if(capKey == buttonList->button[i].key) |
{ |
BlinkButton(ch[i]); |
done = true; |
result = i; |
} |
} |
} |
if(!done) /* someone snatch the key? */ |
if(keyProc) |
(*keyProc)(refcon,er.message,er.modifiers); |
break; |
case kOSEvent: |
if( (er.message>>24) == kSuspendResumeMessage) |
goto activateEvent; |
break; |
} /* switch */ |
} /* while !done */ |
DisposeWindow(w); |
EnableAllMenus(saveMenus); |
return result; |
} |
short EasyDialogMessage(short iconID, |
StringPtr header,StringPtr body, |
EasyDialogButtonList *buttonList) |
{ |
EasyDialogMessageStuff stuff; |
Rect r; |
short result; |
stuff.header = header; |
stuff.body = body; |
stuff.iconID = iconID; |
r.left = r.top = 0; |
r.right = 420; |
r.bottom = 170; |
result = EasyDialog(&r,EasyDialogMessageUpdateProc,nil,nil,nil,buttonList,(long)&stuff); |
return result; |
} |
void EasyDialogMessageUpdateProc(long refcon,const Rect *updateRect) |
{ |
EasyDialogMessageStuff *stuff; |
Rect r; |
Handle theIcon; |
stuff = (EasyDialogMessageStuff *) refcon; |
r.left = r.top = kButtonWindowMargin; |
r.bottom = r.top + 32; |
if(stuff->iconID != -1) |
{ |
r.right = r.left + 32; |
r.top = kButtonWindowMargin; |
theIcon = GetIcon(stuff->iconID); |
if(theIcon) |
{ |
PlotIcon(&r,theIcon); |
ReleaseResource(theIcon); |
} |
else |
PlotIconID(&r,atAbsoluteCenter,0,stuff->iconID); |
} |
r.left += 32 + kButtonWindowMargin; |
r.right = updateRect->right - kButtonWindowMargin; |
if(stuff->header) |
TextBox(stuff->header+1,stuff->header[0],&r,teJustLeft); |
r.top = r.bottom + kButtonWindowMargin; |
r.left = kButtonWindowMargin; |
r.bottom = updateRect->bottom - kButtonWindowMargin; |
if(stuff->body) |
TextBox(stuff->body+1,stuff->body[0],&r,teJustLeft); |
} |
void BlinkButton(ControlHandle buttonControl) |
{ |
long dummy; |
HiliteControl(buttonControl,1); |
Delay(7,&dummy); |
HiliteControl(buttonControl,0); |
} |
Boolean EasyDialogGetString(const StringPtr dialogTitle, |
const StringPtr dialogPrompt, |
StringPtr inOutString,short maxInOutStringLength) |
/* |
* The scary thing about this routine is that |
* it requires two resources: DLOG 128 and 129. |
* 128 should use a modal alert-type window, |
* and 129, a moveable-modal. |
* |
* The items should be: |
* 1 - Okay |
* 2 - Cancel |
* 3 - Title static text = "^0" |
* 4 - Prompt static text = "^1" |
* 5 - Edit text field for entry |
*/ |
{ |
DialogPtr dp; |
short hit; |
short itemType; |
Rect itemRect; |
Handle itemHandle; |
Boolean result; |
Str255 outString; |
ParamText(dialogTitle,dialogPrompt,0,0); |
dp = GetNewDialog(128,0,(WindowPtr)-1); //!!! should have two kinds |
if(!dp) |
{ |
SysBeep(2); |
return false; |
} |
GetDItem(dp,5,&itemType,&itemHandle,&itemRect); |
SetIText(itemHandle,inOutString); |
SelIText(dp,5,0,32767); |
ModalDialog(MyModalFilterProc,&hit); |
(0,&hit); |
if(hit == 1) /* Okay */ |
{ |
GetIText(itemHandle,outString); |
if(outString[0] > maxInOutStringLength) |
outString[0] = maxInOutStringLength; |
BlockMove(outString,inOutString,maxInOutStringLength+1); |
result = true; |
} |
else |
result = false; |
DisposeDialog(dp); |
return result; |
} |
void BlinkItem(DialogPtr theDialog,short item) |
{ |
ControlHandle button; |
short itemType; |
Rect itemRect; |
GetDItem(theDialog,item,&itemType,(void *)&button,&itemRect); |
BlinkButton(button); |
} |
pascal Boolean MyModalFilterProc(DialogPtr theDialog, |
EventRecord *theEvent,short *itemHit) |
{ |
short key; |
Boolean result; |
short itemType; |
Rect itemRect; |
Handle itemHandle; |
short bump; |
Str255 str; |
long x; |
IdleWindow(-1); |
result = false; |
switch(theEvent->what) |
{ |
case keyDown: |
case autoKey: |
key = theEvent->message & 0xFF; |
if(key == 27 || (key == '.' && (theEvent->modifiers & cmdKey))) |
{ |
result = true; |
*itemHit = 2; |
BlinkItem(theDialog,2); |
} |
else if(key == 3 || key == 13) |
{ |
result = true; |
*itemHit = 1; |
BlinkItem(theDialog,1); |
} |
else if((key =='a' || key == 'A') && (theEvent->modifiers &cmdKey)) |
{ |
SelIText(theDialog,5,0,32767); |
theEvent->what = 0; |
} |
else if(gNumbers && (key == '+' || key == '=') |
&& (theEvent->modifiers & cmdKey)) |
{ |
bump = 1; |
bumpString: |
if(theEvent->modifiers & shiftKey) |
bump *= 10; |
GetDItem(theDialog,5,&itemType,&itemHandle,&itemRect); |
GetIText(itemHandle,str); |
StringToNum(str,&x); |
x += bump; |
NumToString(x,str); |
SetIText(itemHandle,str); |
SelIText(theDialog,5,0,32767); |
theEvent->what = 0; |
} |
else if(gNumbers && (key == '-' || key == '_') |
&& (theEvent->modifiers & cmdKey)) |
{ |
bump = -1; |
goto bumpString; |
} |
break; |
case updateEvt: |
if(theEvent->message != (long)theDialog) |
HandleUpdateEvent(theEvent); |
else |
{ |
GrafPort *oldPort; |
GetPort(&oldPort); |
SetPort(theDialog); |
GetDItem(theDialog,1,&itemType,&itemHandle,&itemRect); |
InsetRect(&itemRect,-4,-4); |
PenSize(3,3); |
FrameRoundRect(&itemRect,16,16); |
PenNormal(); |
SetPort(oldPort); |
} |
break; |
case mouseDown: |
{ |
WindowPtr clickWindow; |
short part; |
part = FindWindow (theEvent->where, &clickWindow); |
if(part == inDrag |
&& (clickWindow == theDialog || theEvent->modifiers & cmdKey)) |
{ |
theEvent->what = 0; |
DragWindow(clickWindow,theEvent->where,&gBigRect); |
} |
} |
break; |
} |
goHome: |
return result; |
} |
Boolean EasyDialogGetNumber(const StringPtr dialogTitle, |
const StringPtr dialogPrompt, |
long *inOutNumber) |
{ |
Str255 numString; |
Boolean result; |
NumToString(*inOutNumber,numString); |
gNumbers = true; |
result = EasyDialogGetString(dialogTitle,dialogPrompt,numString,31); |
gNumbers = false; |
if(result) |
StringToNum(numString,inOutNumber); |
return result; |
} |
static EasyFieldList *fieldList; |
Boolean EasyFieldDialog(short dialogID,EasyFieldList *fieldList,void *data, |
StringPtr dialogTitle) |
{ |
DialogPtr dp; |
short hit; |
short itemType; |
Rect itemRect; |
Handle itemHandle; |
Boolean result; |
Str255 aString; |
EasyField *field; |
long *w; |
short j,x; |
short firstTextItem; |
result = true; |
dp = GetNewDialog(dialogID,0,(WindowPtr)-1); |
if(!dp) |
{ |
SysBeep(2); |
return false; |
} |
if(dialogTitle) |
SetWTitle(dp,dialogTitle); |
w = data; |
field = fieldList->field; |
firstTextItem = 0; |
while(field->itemNumber) |
{ |
switch(field->itemType) |
{ |
case easyRadioGroup: |
for(j = 0; j < field->itemCount; j++) |
{ |
GetDItem(dp,field->itemNumber + j, |
&itemType,&itemHandle,&itemRect); |
if(itemType == ctrlItem + radCtrl) |
SetCtlValue((ControlHandle)itemHandle, |
j+1 == *w ? 1 : 0); |
} |
w++; |
break; |
case easyCheckbox: |
GetDItem(dp,field->itemNumber, |
&itemType,&itemHandle,&itemRect); |
if(itemType == ctrlItem + chkCtrl) |
SetCtlValue((ControlHandle)itemHandle, *w); |
w++; |
break; |
case easyTextNumber: |
FixedPointToPString(*w,field->general ? 4 : 0,field->general,aString); |
GetDItem(dp,field->itemNumber, |
&itemType,&itemHandle,&itemRect); |
if(itemType == editText) |
SetIText(itemHandle,aString); |
if(!firstTextItem) |
{ |
SelIText(dp,field->itemNumber,0,32767); |
firstTextItem = field->itemNumber; |
} |
w++; |
break; |
case easyTextString: |
GetDItem(dp,field->itemNumber, |
&itemType,&itemHandle,&itemRect); |
if(itemType == editText) |
SetIText(itemHandle,(StringPtr)w); |
if(!firstTextItem) |
{ |
SelIText(dp,field->itemNumber,0,32767); |
firstTextItem = field->itemNumber; |
} |
w += 64; |
break; |
default: |
break; |
} |
field++; |
} |
ShowWindow(dp); |
do |
{ |
ModalDialog(MyModalFilterProc,&hit); |
field = fieldList->field; |
while(field->itemNumber) |
{ |
if(field->itemNumber <= hit |
&& hit < field->itemNumber+field->itemCount) |
{ |
switch(field->itemType) |
{ |
case easyRadioGroup: |
for(j = 0; j < field->itemCount; j++) |
{ |
GetDItem(dp,field->itemNumber + j, |
&itemType,&itemHandle,&itemRect); |
if(itemType == ctrlItem + radCtrl) |
SetCtlValue((ControlHandle)itemHandle, |
j+field->itemNumber == hit ? 1 : 0); |
} |
break; |
case easyCheckbox: |
GetDItem(dp,hit, |
&itemType,&itemHandle,&itemRect); |
if(itemType == ctrlItem + chkCtrl) |
SetCtlValue((ControlHandle)itemHandle, |
!GetCtlValue((ControlHandle)itemHandle)); |
break; |
} |
goto didHit; |
} |
field++; |
} |
didHit: |
if(hit == 1 || hit == fieldList->cancelButton) |
goto doneDialog; |
} while(1); |
doneDialog: |
if(hit != 1) /* Okay */ |
result = false; |
if(result) |
{ |
w = data; |
field = fieldList->field; |
while(field->itemNumber) |
{ |
switch(field->itemType) |
{ |
case easyRadioGroup: |
for(j = 0; j < field->itemCount; j++) |
{ |
GetDItem(dp,field->itemNumber + j, |
&itemType,&itemHandle,&itemRect); |
if(itemType == ctrlItem + radCtrl) |
{ |
x = GetCtlValue((ControlHandle)itemHandle); |
if(x) |
*w = j+1; |
} |
} |
w++; |
break; |
case easyCheckbox: |
GetDItem(dp,field->itemNumber, |
&itemType,&itemHandle,&itemRect); |
if(itemType == ctrlItem + chkCtrl) |
*w = GetCtlValue((ControlHandle)itemHandle); |
w++; |
break; |
case easyTextNumber: |
GetDItem(dp,field->itemNumber, |
&itemType,&itemHandle,&itemRect); |
if(itemType == editText) |
{ |
GetIText(itemHandle,aString); |
PStringToFixedPoint(aString, |
field->general ? 5 : 0,field->general,w); |
} |
w++; |
break; |
case easyTextString: |
GetDItem(dp,field->itemNumber, |
&itemType,&itemHandle,&itemRect); |
if(itemType == editText) |
GetIText(itemHandle,(StringPtr)w); |
w += 64; |
break; |
default: |
break; |
} |
field++; |
} |
} |
DisposeDialog(dp); |
return result; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-19