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.
Sources/Application.cp
/* |
File: Application.cp |
Contains: TApplication is an abstract base class, TBKApplication is a background only application class, |
TGUIApplication is a window-based user application class. TQTApplication is a QuickTime aware application |
class, TGXApplication is a Quick GX aware application class. Finally TQTAndGXApplication |
handles both QX and QT application work. |
Application.cp contains the needed member functions for the classes defined above. |
Written by: |
Copyright: Copyright © 1992-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/18/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
// INCLUDE FILES |
#ifndef _APPLICATION_ |
#include "Application.h" |
#endif |
// GLOBAL DATA AND FUNCTIONS |
TApplication* gApplication; // universal ptr to the framework |
const short kDefaultNumMasters = 8; // number of master pointers |
const OSType kAEResource = 'aedt'; // our AE binding resource |
pascal OSErr AEDispatcher(AppleEvent* in, |
AppleEvent* out, |
long Command); // AE Dispatcher |
// Global Functions |
pascal OSErr AEDispatcher(AppleEvent* in, |
AppleEvent* out, |
long Command) |
{ |
gApplication->DispatchAppleEvents(in, out, Command);// dispatch event back to the framework |
return noErr; |
} |
// _________________________________________________________________________________________________________ // |
// TApplication class member function implementations. |
// CONSTRUCTORS & DESTRUCTORS |
#pragma segment Application |
TApplication::TApplication() |
// Default constructor -- put together the basic environment (non-UI model). |
{ |
gApplication = this; // hook ptr to the global pointer |
// Default base class constructor, define fields to known initial values. |
this->SetState(TApplication::kInit); // set out first state |
fSleepRegion = ::NewRgn(); // define default sleep region for WaitNextEvent (NULL) |
fSleepValue = TApplication::kBackgroundSleepValue;// default sleep value (ticks) |
fEventMask = everyEvent; // default setting |
fMoreMasters = kDefaultNumMasters; // amount of more master calls |
this->InitializeMemory(); // initialize memory |
this->InstallAEHandler(); // install our AE handler |
} |
#pragma segment Application |
TApplication::~TApplication() |
// Default destructor -- empty for the time being. |
{ |
} |
#pragma segment Application |
void TApplication::DoNextEvent() |
// Handle incoming events |
{ |
if (!::WaitNextEvent(fEventMask, &fEventRecord, fSleepValue, fSleepRegion)) |
fEventRecord.what = nullEvent; // security issue |
} |
#pragma segment Application |
void TApplication::DoHighLevelEvent() |
// Handle high level events. |
{ |
fError = ::AEProcessAppleEvent(&fEventRecord);// handle primarly AEs |
VASSERT(fError == noErr, ("Problems with AEProcessAppleEvent", fError)); |
} |
#pragma segment Application |
void TApplication::Start() |
// Start the application and let it run until we change the state to Quit. |
{ |
this->SetState(TApplication::kRun); // set TApplication to run state |
while (fState != TApplication::kQuit) |
this->DoEventLoop(); |
this->Quit(); // out from the state, we will quit |
} |
#pragma segment Application |
void TApplication::Quit() |
// Quit the application, do any possible cleanup. |
{ |
} |
// CORE AE HANDLER METHODS |
#pragma segment Application |
void TApplication::InstallAEHandler() |
// Install our core Apple Event Handler that will dispatch the AEs back to the framework. |
{ |
Handle aedtResource = NULL; |
SignedByte state; |
Size tableSize; |
AEEventTablePtr tablePtr; |
short numEntries = ::Count1Resources(kAEResource);// find out how many entries in the table |
fError = ResError(); |
VASSERT(fError == noErr, ("Problems with Count1Resources = %d", fError)); |
if(numEntries != 0) // we had 'aedt' resources |
{ |
for (short i = 1; i <= numEntries; ++i) // loop through the resources |
{ |
aedtResource = ::Get1IndResource('aedt', i);// get resource |
fError = ResError(); |
VASSERT(fError == noErr, ("Problems with Get1IndResource = %d", fError)); |
state = ::HGetState(aedtResource); // get the flags from the handle |
::HLockHi(aedtResource); // and lock the handle high in memory |
tableSize = GetHandleSize(aedtResource);// get the size of the resource |
fError = MemError(); |
VASSERT(fError == noErr, ("Problems with GetHandleSize = %d", fError)); |
short elements = (short)(tableSize / sizeof(AEEventTable));// get N of elements in resource |
tablePtr = (AEEventTablePtr) * aedtResource;// get ptr to the element |
// ¥¥¥ Add the information into our fCommandTable as well for future lookups |
for (short j = 0; j < elements; j++) // go through the elements |
{ |
fError = ::AEInstallEventHandler(tablePtr->theClass, tablePtr->theID, NewAEEventHandlerProc(AEDispatcher), tablePtr->theValue, false); |
VASSERT(fError == noErr, ("Problems with AEInstallEventHandler = %d", fError)); |
++tablePtr; |
} |
::HSetState(aedtResource, state); // restore state |
::ReleaseResource(aedtResource); // release the resource |
} |
} |
} |
#pragma segment Application |
void TApplication::DispatchAppleEvents(AppleEvent* in, |
AppleEvent* out, |
long command) |
// Dispatch to the right Handler based on the command in the AE (refCon). |
{ |
switch (command) |
{ |
case cQuitCommand: // a quit AE |
this->HandleQuit(in, out, command); |
break; |
case cNewCommand: // a new AE |
this->HandleOpen(in, out, command); |
break; |
case cOpenCommand: // an open document AE |
this->HandleOpenDocuments(in, out, command); |
break; |
case cPrintCommand: // a print AE |
this->HandlePrint(in, out, command); |
break; |
default: // hmm, something else thenÉ |
ASSERT(false, "\pProblem: We are dealing with an AE command that we have no handler for"); |
break; |
} |
} |
#pragma segment Application |
OSErr TApplication::HandleQuit(AppleEvent* /*in*/, |
AppleEvent* /*out*/, |
long /*refCon*/) |
// Our General Quit Handler. Set state to Quit and return. |
{ |
this->SetState(TApplication::kQuit); // set state to Quit |
return noErr; // need to have this due to AEHandler prototype |
} |
#pragma segment Application |
OSErr TApplication::HandleOpen(AppleEvent* /*in*/, |
AppleEvent* /*out*/, |
long /*refCon*/) |
{ |
return errAEEventNotHandled; // need to have this due to AEHandler prototype |
} |
#pragma segment Application |
OSErr TApplication::HandleOpenDocuments(AppleEvent*/*in*/ , |
AppleEvent*/*out*/ , |
long /*refCon*/) |
{ |
return errAEEventNotHandled; // need to have this due to AEHandler prototype |
} |
#pragma segment Application |
OSErr TApplication::HandlePrint(AppleEvent* /*in*/, |
AppleEvent* /*out*/, |
long /*refCon*/) |
{ |
return errAEEventNotHandled; // need to have this due to AEHandler prototype |
} |
// STATE CHANGE METHODS |
#pragma segment Application |
void TApplication::SetState(TApplication::EState theState) |
{ |
fState = theState; |
} |
// MAIN INTERFACE |
#pragma segment Application |
void TApplication::InitializeMemory() |
// Initialize issues dealing with memory use. |
{ |
::MaxApplZone(); // increase the zone |
for (short i = 0; i < fMoreMasters; i++) // bounce up the amount of master pointers |
::MoreMasters(); |
fError = MemError(); |
VASSERT(fError == noErr, ("Problems with MoreMasters = %d", fError)); |
} |
// _________________________________________________________________________________________________________ // |
// TBKApplication class member function implementations |
// CONSTRUCTORS & DESTRUCTORS |
#pragma segment Application |
TBKApplication::TBKApplication() |
{ |
} |
#pragma segment Application |
TBKApplication::~TBKApplication() |
{ |
} |
// _________________________________________________________________________________________________________ // |
// TGUIApplication class member function implementations |
// CONSTRUCTORS & DESTRUCTORS |
#pragma segment Application |
TGUIApplication::TGUIApplication() |
// Initialize the UI toolbox side. |
{ |
this->InitializeToolbox(); // Initialize toolbox |
TMenubar myMenubar; // handle my menu bar initialization |
fCursHandle = ::GetCursor(watchCursor); // get the watch cursor resource |
::SetCursor(*fCursHandle); // change the cursor to the watch one |
} |
#pragma segment Application |
TGUIApplication::~TGUIApplication() |
// Default destructor -- empty for the time being. |
{ |
} |
#pragma segment Application |
void TGUIApplication::InitializeToolbox() |
// Initialize the toolbox requirements for a standard window based application. |
{ |
::InitGraf(&qd.thePort); |
::InitFonts(); |
::InitWindows(); |
// _DON'T_ flush disk-inserted or os events or you'll be sorry! |
::FlushEvents(everyEvent - diskMask - osMask, 0); |
// The following toolbox init calls are slightly overhead, but that's fine |
::InitMenus(); |
::TEInit(); |
::InitDialogs(NULL); |
::InitCursor(); |
} |
// MAIN INTERFACE |
#pragma segment Application |
void TGUIApplication::Start() |
// Start the event loop handling. |
{ |
::SetCursor(&qd.arrow); // OK, scursor back to to the arrow one |
TApplication::Start(); // call the inherited Start |
} |
// EVENT HANDLING MEMBER FUNCTIONS |
#pragma segment Application |
void TGUIApplication::DoEventLoop() |
// This is the big event loop swith statement function. |
{ |
this->DoNextEvent(); // get the next event record |
// This is the big switch statement, switch on events received |
switch (fEventRecord.what) |
{ |
case nullEvent: // we got a periodic null event |
this->DoIdle(); // call idle handler |
break; |
case updateEvt: // we got an update event |
this->DoWindowUpdate(); // call the window update member function |
break; |
case diskEvt: // we got a disk insertion event (most likely formatting) |
this->DoDiskEvent(); |
break; |
case mouseDown: // we got a mouse down event |
// get the window where the mouse down happened, and do an action based on this |
switch (::FindWindow(fEventRecord.where, &fCurrentWindow)) |
{ |
case inSysWindow: // It's a DA window, provide time for that. |
this->DoSystemTime(); |
break; |
case inDrag: // Move the window to a specific target. |
this->DoDragWindow(); |
break; |
case inGoAway: // Close the window. |
this->DoGoAwayWindow(); // do window close events |
// ¥¥¥ Future, Send a Close command |
break; |
case inContent: // handle click inside the window |
this->DoInWindowContent(); |
break; |
case inMenuBar: // handle menu bar clicks |
this->DoMenuCommand(); |
break; |
default: // ignore any other sane events for the time being |
break; |
} |
case app4Evt: // we got a Multifinder event |
switch ((unsigned long)fEventRecord.message >> TApplication::kHighByte) |
{ |
case TApplication::kSuspendResumeMessage:// suspend or deactivate message |
if ((fEventRecord.message & TApplication::kResumeMask) == 0) |
fSleepValue = TApplication::kBackgroundSleepValue; |
else // resume or activate message |
fSleepValue = TApplication::kForgroundSleepValue; |
break; |
} |
break; |
case kHighLevelEvent: |
this->DoHighLevelEvent(); // handle our high level events (as AEs) |
break; |
default: |
break; |
} |
} |
#pragma segment Application |
void TGUIApplication::DoIdle() |
// Handle idle time |
{ |
} |
#pragma segment Application |
void TGUIApplication::DoSystemTime() |
// Handle DAs |
{ |
::SystemClick(&fEventRecord, fCurrentWindow); |
} |
#pragma segment Application |
void TGUIApplication::DoDiskEvent() |
// Handle disk events (formatting, floppies inserted and so on). |
{ |
Point dlogPoint; |
const short kDILeft = 40; |
const short kDITop = 40; |
if (HiWrd(fEventRecord.message) != noErr) // if no error indication |
{ |
::SetPt(&dlogPoint, kDILeft, kDITop); // define the dlog box rect |
fError = ::DIBadMount(dlogPoint, fEventRecord.message);// turn it over to the system |
VASSERT(fError == noErr, ("Problems with DIBadMount = %d ", fError)); |
} |
} |
#pragma segment Application |
void TGUIApplication::DispatchAppleEvents(AppleEvent* in, AppleEvent* out, long command) |
// Take care of the GUI related Apple Events, and dispatch the rest to the TApplication level |
{ |
switch(command) |
{ |
case cAboutCommand: // Send an AE telling the system to display the About box |
this->DoAboutBox(); |
break; |
default: |
TApplication::DispatchAppleEvents(in, out, command); |
break; |
} |
} |
#pragma segment Application |
void TGUIApplication::DoWindowUpdate() |
// Handle window update events. |
{ |
::BeginUpdate((WindowPtr)fEventRecord.message); |
::SetPort((WindowPtr)fEventRecord.message); // set port to the right grafport |
this->Draw(); // call the window drawing part |
::EndUpdate((WindowPtr)fEventRecord.message); |
} |
#pragma segment Application |
void TGUIApplication::DoDragWindow() |
// Handle the inDrag event. |
{ |
::DragWindow(fCurrentWindow, fEventRecord.where, &qd.screenBits.bounds); |
} |
#pragma segment Application |
void TGUIApplication::DoGoAwayWindow() |
// Handle dogoAway events. |
{ |
::TrackGoAway(fCurrentWindow, fEventRecord.where); |
} |
#pragma segment Application |
void TGUIApplication::DoInWindowContent() |
// Handle inWindow events. |
{ |
if (fCurrentWindow != ::FrontWindow()) |
::SelectWindow(fCurrentWindow); // make the window the foremost one |
else |
this->DoClick(); // handle the click inside the foremost window |
} |
// MENU EVENTS |
#pragma segment Application |
void TGUIApplication::DoMenuCommand() |
// Handle menu mouse events. |
{ |
long aCommandNumber; |
this->AdjustUserInterface(); // first, make sure the menu entries are enabled/disabled |
fMenuResult = ::MenuSelect(fEventRecord.where);// get the selected menu (longword) |
aCommandNumber = this->CalculateMenuCommand(fMenuResult); // calculate our command number |
// We will handle the most typical menu entries here (Apple, Edit, File) |
// and call DoCommand() with the rest of the possible commands. |
this->DoInternalMenus(aCommandNumber); // handle internal menus (Apple) |
this->DoCommand(aCommandNumber); // handle external commands/menus |
::HiliteMenu(0); // unhighlight what MenuSelect hilited and return |
} |
#pragma segment Application |
long TGUIApplication::CalculateMenuCommand(long menuEntry) |
// Calculate the command number based on the algorithm where the menu entry |
// is either a two-digit or a three-digit number, and where the first number |
// is the menu number. |
{ |
long command; |
if (LoWrd(menuEntry) > 9) // use algorithm 2 |
{ |
command = (HiWrd(menuEntry) * 100) + LoWrd(menuEntry); |
} |
else // use algorithm 1 |
command = (HiWrd(menuEntry) * 10) + LoWrd(menuEntry); |
return command; |
} |
#pragma segment Application |
void TGUIApplication::DoInternalMenus(long command) |
// Handle our internal menus, Apple, DAs and so on. |
{ |
Str255 daName; // our DA name |
short daRefNum; // our DA refnum |
switch (command) |
{ |
case cAboutCommand: // our About box? |
fMessenger.Send(kCoreEventClass, kAEAbout); |
break; |
default: |
if( HiWrd(fMenuResult) == mApple) // we have a DA? |
{ |
::GetMenuItemText(GetMenuHandle(mApple), (short)LoWrd(fMenuResult), daName); |
daRefNum = ::OpenDeskAcc(daName); |
} |
break; |
} |
} |
#pragma segment Application |
void TGUIApplication::DoCommand(long command) |
// Handle the default framework menus, post AE commands. |
{ |
switch(command) |
{ |
case cQuitCommand: |
fMessenger.Send(kCoreEventClass, kAEQuitApplication); |
break; |
default: |
TApplication::DoCommand(command); // let the underlying framework take a short |
break; |
} |
} |
// AE HANDLING OVERRIDES |
#pragma segment Application |
OSErr TGUIApplication::HandleOpen(AppleEvent* /*in*/, |
AppleEvent* /*out*/, |
long /*refCon*/) |
{ |
this->DoCreateDocument(); // Default behavior -- open one window ('document'). |
return noErr; // need to have this due to AEHandler prototype |
} |
// DOCUMENT CREATION MEMBER FUNCTIONS |
#pragma segment Application |
void TGUIApplication::DoCreateDocument() |
// Create initially one window. |
{ |
TWindow * aWindow = new TWindow; |
ASSERT(aWindow != NULL, "\pWe didn't create a TWindow"); |
if(aWindow != NULL) |
this->AddDocument(aWindow); |
} |
#pragma segment Application |
void TGUIApplication::AddDocument(TWindow* theDocument) |
// Add the document (Window) to an internal list of documents. |
{ |
fDocument = theDocument; |
} |
#pragma segment Application |
void TGUIApplication::DoCreateDocument(short windowID) |
// Create initially one window. |
{ |
TWindow * aWindow = new TWindow(windowID); |
ASSERT(aWindow != NULL, "\pWe didn't create a TWindow"); |
if(aWindow != NULL) |
this->AddDocument(aWindow); |
} |
#pragma segment Application |
void TGUIApplication::Draw() |
// Define drawing instructions inside this method. Default dispatch |
// and draw the currently active document (window). |
{ |
fDocument->Draw(); |
} |
#pragma segment Application |
void TGUIApplication::DoClick() |
// Handle a click inside a window, empty for the moment (need to override this one) |
{ |
} |
#pragma segment Application |
void TGUIApplication::DoAboutBox() |
// Present our default about box, override for a better one! |
{ |
ASSERT(false, "\pThis is the Gamura framework! Override for a better about box"); |
} |
#pragma segment Application |
void TGUIApplication::DoHelp() |
// This is the hook for a possible help system (something outside the help balloons) |
{ |
ASSERT(false, "\pYou triggered the help system, override for a real one!"); |
} |
// _________________________________________________________________________________________________________ // |
// TQTApplication class member function implementations |
// CONSTRUCTORS & DESTRUCTORS |
#pragma segment Application |
TQTApplication::TQTApplication() |
// Initialize the QT specific parts. |
{ |
} |
#pragma segment Application |
TQTApplication::~TQTApplication() |
// Do any possible epilogue cleanup. |
{ |
} |
// _________________________________________________________________________________________________________ // |
// TGXApplication class member function implementations |
// CONSTRUCTORS & DESTRUCTORS |
#pragma segment Application |
TGXApplication::TGXApplication() |
// Initialize the GX specific parts |
{ |
} |
#pragma segment Application |
TGXApplication::~TGXApplication() |
// Do any possible epilogue cleanup. |
{ |
} |
// _________________________________________________________________________________________________________ // |
// TQTAndGXApplication class member function implementations |
// CONSTRUCTORS & DESTRUCTORS |
#pragma segment Application |
TQTAndGXApplication::TQTAndGXApplication() |
// Initialize the QT and GX specific parts. |
{ |
} |
#pragma segment Application |
TQTAndGXApplication::~TQTAndGXApplication() |
// Do any possible epilogue cleanup. |
{ |
} |
// _________________________________________________________________________________________________________ // |
/* Change History (most recent last): |
No Init. Date Comment |
1 khs 11/6/92 New file |
2 khs 1/14/93 Cleanup |
*/ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14