Important: The information in this document is obsolete and should not be used for new development.
Implementing Your Cyberdog Display Part Class
This section describes the steps you take to implement a Cyberdog display part class. You take the following steps to create your display part class:
The following sections describe the steps in more detail, using the text-viewer part,
- Define your Cyberdog part class.
- Set up the OpenDoc extension protocol to use your Cyberdog part extension subclass.
- Handle release of the part extension object.
- Initialize objects created in your display part class.
- Use Cyberdog's Document menu.
- Use window-position hints.
- Handle downloading of data.
- Determine the window in which to display the Cyberdog item.
- Handle closing the display part's window.
CybTxtViewer
. The text-viewer part is based on the OpenDoc sample program,SamplePart
. These sections assume that you are working with anODPart
subclass that has already been defined and whose methods have been overridden for some purpose, such as to display text. The chapter does not show, for example, how to implement drawing. For an example of defining an OpenDoc part subclass from theODPart
class, see the OpenDoc Cookbook. For more general information about programming with OpenDoc, see the OpenDoc Programmer's Guide.Modifying Your ODPart Subclass
You can start with your existing subclass ofODPart
and modify it to support the Cyberdog part extension and to handle events that affect Cyberdog-related operations. To modify your part class so that it becomes a Cyberdog display part class, you should modify the class definition to include
Listing 4-6 shows the portion of the part class definition that defines both the new fields and methods and also the methods whose implementation must be modified.
- a pointer to the Cyberdog part extension object
- methods that initialize the Cyberdog display part object and its part extension object
- methods that set up the Cyberdog part extension
- methods that handle releasing the extension when the part is closed
Listing 4-6 The
CybTxtViewer
class definition
class CybTxtViewer { public: CybTxtViewer(); virtual ~CybTxtViewer(); ... // Modified to implement the Cyberdog part extension ODBoolean HasExtension(Environment* ev, ODType name); ODExtension* AcquireExtension(Environment* ev, ODType name); void ReleaseExtension(Environment* ev, ODExtension* extension); // Modified or added to release the part extension void ReleaseAll(Environment* ev); void ReleaseCyberPartExtension(Environment* ev); // Modified to handle closing windows ODBooleanHandleEvent (Environment* ev, ODEventData* event, ODFrame* frame, ODFacet* facet, ODEventInfo* eventInfo); ODBooleanHandleMenuEvent(Environment* ev, ODEventData* event, ODFrame* frame); // Modified to download a Cyberdog item's data void OpenCyberItem (Environment *ev, CyberItem* item, ODPart* openerPart, ParameterSet* openParams); void PollStream(Environment* ev); // Modified to reuse a Cyberdog item's window ODWindow* GetCyberItemWindow(Environment *ev, CyberItem* item); // Modified or added to support window-position hints ODID Open(Environment* ev, ODFrame* frame); ODWindow* CreateWindow (Environment* ev, ODFrame* frame, ODType frameType, WindowProperties* windowProperties, WindowPtr behindThisWindow = (WindowPtr) -1); WindowPtr GetBehindWindow(Environment* ev); WindowProperties* GetDefaultWindowProperties(Environment* ev, ODFrame* frame, Rect* windowRect, CDWindowPositionHint* windowPositionHint = nil); // Modified to support Cyberdog's document menu void CreateMenus(Environment* ev); void CheckMenus(Environment *ev, ODFrame* frame); protected: // Added to initialize Cyberdog and a part extension void Initialize(Environment* ev); private: // A reference to the Cyberdog part extension CyberSample_som_CybTxtViewerCyberExt*fCybTxtViewerCyberExt; Handle fDocMenu;// Cyberdog's Document menu CyberStream* fStream;// Cyberdog stream // The following fields are used with downloading: char* fChars; ODULong fCharsLength; ODULong fCharsAllocLength; }Listing 4-6 defines several fields that maintain references to the Cyberdog part extension (CyberSample_som_CybTxtViewerCyberExt), the Cyberdog Document menu (fDocMenu), and the Cyberdog stream (fStream) used to download the data. Other fields are used to manage the downloading operation. The constructor and theInitialize
method handle initialization of these fields, which are discussed in "Creating and Destroying the Display Part Object" (page 127).The HasExtension, AcquireExtension, and ReleaseExtension methods implement the OpenDoc extension protocol. They are discussed in "Implementing the OpenDoc Extension Protocol" (page 124). The ReleaseAll and ReleaseCyberPartExtension methods handle the release of the extension when the part is deleted. These methods are discussed in "Releasing the Part Extension" (page 126).
The
HandleEvent
method handles polling and the closing of the text-viewer part's window. TheHandleMenuEvent
method also handles the closing of the text-viewer part's window. The methodsOpenCyberItem
andPollStream
initiate downloading from the stream and manage the stream, respectively. For information about setting up a Cyberdog stream, see "Creating a Stream for Downloading" (page 135). For information about using a Cyberdog stream, see "Downloading From the Stream" (page 136). For information about closing the display part's window, see "Closing Your Display Part's Window" (page 140).The
Open
andCreateWindow
methods use window-position hints. These hints are manipulated by theGetBehindWindow
and GetDefaultWindowProperties methods. For more information about using window-position hints, see "Using Window-Position Hints" (page 130).The
CreateMenus
andCheckMenus
methods allow Cyberdog's Document menu to be displayed. For more information about Cyberdog's document menu, see "Supporting Cyberdog's Document Menu" (page 129).Implementing the OpenDoc Extension Protocol
To implement the extension protocol between your Cyberdog display part and your Cyberdog part extension, you override threeODPart
methods in your part class:
These are the same methods that you override to associate an extension with any OpenDoc part. For more information about extending an OpenDoc part, see the OpenDoc Programmer's Guide.
- Override the HasExtension method to return kODTrue if the part has an extension with the name kCyberPartExtension.
- Override the
AcquireExtension
method to return a reference to your Cyberdog part extension object.- Override the ReleaseExtension method to delete the Cyberdog part extension.
Listing 4-7 shows the HasExtension method for the text-viewer part. It returns kODTrue if the extension is kCyberPartExtension; otherwise, it returns kODFalse.
Listing 4-7 The text-viewer part's
HasExtension
method
ODBoolean CybTxtViewer::HasExtension(Environment* ev, ODType name) { ODBooleanresult = kODFalse; if (strcmp(name, kCyberPartExtension) == 0) result = kODTrue; return result; }Listing 4-8 shows theAcquireExtension
method for the text-viewerpart. It sets the fCybTxtViewerCyberExt field and acquires a reference to the extension.
Listing 4-8 The text-viewer part's
AcquireExtension
method
ODExtension* CybTxtViewer::AcquireExtension(Environment* ev, ODType name) { ODExtension* extension = kODNULL; if (strcmp(name, kCyberPartExtension) == 0) { if (fCybTxtViewerCyberExt) { extension = (ODExtension*) fCybTxtViewerCyberExt; extension->Acquire(ev); } } return extension; }Listing 4-9 shows the ReleaseExtension method for the text-viewerpart. It deletes the reference to the extension, if it exists, and sets the fCybTxtViewerCyberExt field to
kODNULL
.Listing 4-9 The text-viewer part's
ReleaseExtension
method
void CybTxtViewer::ReleaseExtension(Environment* ev, ODExtension* extension) { if (extension == (ODExtension*) fCybTxtViewerCyberExt) { delete fCybTxtViewerCyberExt; fCybTxtViewerCyberExt = kODNULL; } }Releasing the Part Extension
When your display part is closed, OpenDoc calls the part'sReleaseAll
method to release all resources that continue to be referenced by the part. You must make sure that your part'sReleaseAll
method releases your Cyberdog part extension object. If your part is the only one that currently references the extension, you can delete the object; otherwise, you should release the part extension and call the extension's BaseRemoved method to notify the extension that the part no longer exists.Listing 4-10 shows only the portion of the text-viewer part's override of the
ReleaseAll
method that relates to releasing the part extension. TheReleaseAll
method calls the ReleaseCyberPartExtension method to do the actual work of releasing the part extension. It also deletes the stream if it exists.Listing 4-10 The text-viewer part's
ReleaseAll
method
void CybTxtViewer::ReleaseAll( Environment* ev ) { ... ReleaseCyberPartExtension(ev); if (fStream) { delete fStream; fStream = kODNULL; } }The ReleaseCyberPartExtension method is defined by the CybTxtViewer class, not by theODPart
class. It exists to separate the work associated with releasing the Cyberdog part extension from the other work being performed (but not shown) in theReleaseAll
method.Listing 4-11 shows the ReleaseCyberPartExtension method. It calls the part extension's Release method, which decrements the part extension's reference count. If the extension is in use by another part and has not been deleted as a result of calling Release, the
BaseRemoved
method is called and the fCybTxtViewerCyberExt field is set to kODNULL.Listing 4-11 Releasing the text viewer's Cyberdog part extension
void CybTxtViewer::ReleaseCyberPartExtension(Environment* ev) { if (fCybTxtViewerCyberExt) { fCybTxtViewerCyberExt->Release(ev); // The part extension may not exist at this point. if(fCybTxtViewerCyberExt) { fCybTxtViewerCyberExt->BaseRemoved(ev); fCybTxtViewerCyberExt = kODNULL; } } }Creating and Destroying the Display Part Object
When a display part object is created, you must initialize its fields. Then the part must take these actions:
The constructor must set its fields to safe values, as shown in Listing 4-12.
- Call the
InitCyberdog
function to initialize Cyberdog.- Create an object from your Cyberdog part extension subclass. The part must then take these two actions:
- Call its ICyberPartExtension method to initialize the extension.
- Establish a reference to your display part object in the Cyberdog part extension.
- Replace the OpenDoc Document menu with Cyberdog's Document menu.
Listing 4-12 The
CybTxtViewer
constructor
CybTxtViewer::CybTxtViewer() { ... fCybTxtViewerCyberExt = kODNULL; fStream = kODNULL; fDocMenu = kODNULL; fCharsLength = 0; fCharsAllocLength = 0; fChars = kODNULL; }You perform initialization in yourInitPart
andInitPartFromStorage
methods. Listing 4-13 shows the text-viewer part'sInitialize
method, which is called from both theInitPart
andInitPartFromStorage
methods (not shown). It initializes Cyberdog, creates and initializes the part extension.Listing 4-13 Initializing the Cyberdog environment
void CybTxtViewer::Initialize( Environment* ev ) { ... // Initialize Cyberdog. ODSession* session = ODGetSession(ev,fSelf); OSErr err = InitCyberdog(ev, session); ... // Create and initialize the Cyberdog part extension. fCybTxtViewerCyberExt = new Apple_som_CybTxtViewerCyberExt; if(fCybTxtViewerCyberExt != kODNULL) { fCybTxtViewerCyberExt->ICyberPartExtension(ev, fSelf); fCybTxtViewerCyberExt->SetBasePart(ev, this); } ... }The destructor must delete any data that has been left in memory and may also need to delete a stream if the display part was terminated while a download operation was in progress. It also must delete the Cyberdog Document menu. Listing 4-14 shows the destructor for the text-viewerpart.
Listing 4-14 The
CybTxtViewer
destructor
CybTxtViewer::~CybTxtViewer() { // Delete downloaded data. if (fChars) ODDisposePtr(fChars); // Delete the stream. if (fStream) delete fStream; // Delete the Cyberdog document menu. if (fDocMenu != nil) DisposeHandle(fDocMenu); }Supporting Cyberdog's Document Menu
Your display part must replace OpenDoc's Document menu with Cyberdog's Document menu. You call the Cyberdog session's InstallCyberDocumentMenu method to install Cyberdog's Document menu. The Document menu is replaced only if the display part is in the Cyberdog session document.For example, the text-viewer part calls the InstallCyberDocumentMenu method from its
CreateMenus
method whenever menus need to be created:
fDocMenu = GetCyberSession(ev)->InstallCyberDocumentMenu (ev, fSelf, fMenuBar);For information about creating menus, see "Displaying Cyberdog Menus" (page 105).When menus need to be recreated, or when the part is destroyed, you should dispose of the Document menu. The text-viewer part disposes the Document menu's handle from its destructor and before recreating menus in its
CheckMenus
method:
if (fDocMenu != nil) { DisposeHandle(fDocMenu); fDocMenu = nil; }
- IMPORTANT
- Do not forget to install the Cyberdog Document menu. The OpenDoc Document menu contains items that are not applicable to a Cyberdog session document, such as the Delete menu item, whose use would have undesirable consequences.
Using Window-Position Hints
A window-position hint provides information to your display part about where to open its window. It specifies the window to be in front of your part's window and the coordinates specifying where to place your part's window.A window-position hint may have been written to the storage unit by an opener part before your display part is opened. For example, the user may start an operation involving your part, such as a download operation, and then activate a different window or open a modal dialog box. When the first operation finishes your part should use the window-position hint instead of opening its window in front of the user's active window.
On opening, your Cyberdog display part should use a window-position hint to place a part's window at the specified position on the screen and behind the specified window. You must read the
CDWindowPositionHint
data structure from storage when opening your display part. You then use the hint when you create the window.Listing 4-15 shows the text-viewer part's
Open
method, which calls the CDGetWindowPositionHint function to retrieve a window-position hint from the storage unit. TheOpen
method then calls the GetBehindWindow method to determine which window to open the text-viewer's window behind. It then calls the GetDefaultWindowProperties, which uses the position hint. Finally, it calls theCreateWindow
method to create the window using the hint.Listing 4-15 The text-viewer part's
Open
method
ODID CybTxtViewer::Open(Environment* ev, ODFrame* frame) { ODID windowID; TempODWindow window(kODNULL); WindowProperties* windowProperties = kODNULL; ODVolatile(windowProperties); WindowPtr behindThisWindow = (WindowPtr)-1; TRY if ( frame == kODNULL ) { CDWindowPositionHint windowPositionHint; CDWindowPositionHint* windowPositionHintPtr; // Retreive the window-position hint from the storage unit. if (CDGetWindowPositionHint(ev, GetODPart(ev)->GetStorageUnit(ev), &windowPositionHint)) windowPositionHintPtr = &windowPositionHint; // Found else windowPositionHintPtr = nil; // No hint in storage unit // Deterimine the window layer to open in. behindThisWindow = GetBehindWindow (ev, windowPositionHintPtr); // Calculate the bounding rectangle for a new window. Rect windowRect = this->CalcPartWindowSize(ev, kODNULL); // Get the default settings for a document window. windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect, windowPositionHintPtr); // Create a window and register it with OpenDoc. window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties, behindThisWindow); } ... // Create the window's root facet. window->Open(ev); // Make the window visible. window->Show(ev); // Activate and select the window if it is in front. if (behindThisWindow == (WindowPtr)-1) window->Select(ev); ... windowID = (window ? window->GetID(ev) : kODNULLID); CATCH_ALL ... RERAISE; ENDTRY return windowID; }Listing 4-16 shows the text-viewer part's CDGetWindowPositionHint method, which reads the window-position hint from the storage unit.Listing 4-16 Reading the window-position hint from storage
ODBoolean CDGetWindowPositionHint(Environment* ev, ODStorageUnit* su, CDWindowPositionHint *windowPositionHint) { if (ODSUExistsThenFocus(ev, su, kCDWindowPositionHintProperty, kCDWindowPositionHintValue)) { StorageUnitGetValue(su, ev, sizeof(CDWindowPositionHint), (ODValue)windowPositionHint); return kODTrue; } else return kODFalse; }The text-viewer part's GetBehindWindow method, shown in Listing 4-17, returns the window to open behind, which is the window specified in the window-position hint, if available. Otherwise, the method ensures that the window appears behind any modal windows.Listing 4-17 Using the window-position layer hint
WindowPtr CybTxtViewer::GetBehindWindow(Environment* ev, CDWindowPositionHint* windowPositionHint) { WindowPtr window = nil; // Get the window indicated in the window-position hint. if (windowPositionHint) { window = windowPositionHint->behindWindow; } else // If no hint, make sure the window goes behind any modal windows. { // Find last modal window in the window list. WindowPtr aWindow = FrontWindow(); while (aWindow && WindowIsModal(aWindow)) { window = aWindow; aWindow = (WindowPtr) GetNextWindow(aWindow); } } if (!window) // No hint or modal dialog box; open in front window = (WindowPtr) -1; return window; }Listing 4-18 shows the text-viewer part's GetDefaultWindowProperties method, which uses the window-position coordinates to position the window.Listing 4-18 Using the window-position coordinate hint
WindowProperties* CybTxtViewer::GetDefaultWindowProperties(Environment* ev, ODFrame* sourceFrame, Rect* windowRect, CDWindowPositionHint* windowPositionHint) { WindowProperties* windowProperties = new WindowProperties; TRY // Position the window if ( sourceFrame ) // Use the source frame if one exists. this->CalcPartWindowPosition(ev, sourceFrame, windowRect); else if ( windowPositionHint ) // Otherwise, use the window-position hint, if one exists. OffsetRect (windowRect, windowPositionHint->windowPosition.h, windowPositionHint->windowPosition.v); else // If none, place the window at the top left of the desktop. OffsetRect(windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight); ... CATCH_ALL ODDeleteObject(windowProperties); RERAISE; ENDTRY return windowProperties; }The window layer (behindThisWindow) and coordinates (in windowProperties) are used when creating the window, as shown in the following call to theNewCWindow
function from theCreateWindow
method (not shown):
platformWindow = NewCWindow((Ptr)ODNewPtr(sizeof(WindowRecord)), &(windowProperties->boundsRect), windowProperties->title, kODFalse, /* visible */ windowProperties->procID, behindThisWindow, windowProperties->hasCloseBox, windowProperties->refCon);Creating a Stream for Downloading
When a Cyberdog item is opened, Cyberdog calls your part extension'sOpenCyberItem
method. This is the most convenient place for you to specify tasks that need to be performed in conjunction with opening the Cyberdog item.In the case of the text-viewer sample, the part extension's
OpenCyberItem
method--see Listing 4-4 (page 119)--calls the text viewer part'sOpenCyberItem
method to do the work of creating a stream and to use it for downloading data. The text-viewer part'sOpenCyberItem
method also registers the item in the log. Listing 4-19 shows the text-viewer part's method.Listing 4-19 The
OpenCyberItem
method of the text-viewer part
void CybTxtViewer::OpenCyberItem(Environment *ev, CyberItem* item, ODPart* openerPart, ParameterSet* openParams) { // Create a stream for the download operation. fStream = item->CreateCyberStream(ev); // Open the stream, which starts the download operation. fStream->Open(ev); // Get the Cyberdog item's parent for the log. CyberItem* parent = kODNULL; if(openParams) openParams->GetParameter(ev, kCDParentItemKey, &parent); // Add the Cyberdog item to the log. GetCyberSession(ev)->AddCyberItemToLog(ev, parent, item); }The method creates the Cyberdog stream by calling the Cyberdog item's CreateCyberStream method. It then calls the stream'sOpen
method to initiate downloading. Finally, it calls the session's AddCyberItemToLog method to add the item to the log.Downloading From the Stream
When downloading, you must periodically check whether the stream contains any data and, if so, display the data. You can, for example, check the status of downloading from the stream during idle time. You should try not to do too much work during idle time; otherwise, the system will be perceived as unresponsive. You must balance the work so as to avoid this perception yet obtain enough data from the stream on each poll to complete the download operation in a reasonable time. You take these steps to manipulate the stream:
Listing 4-20 shows the text-viewer part's
- Call the stream's GetStreamStatus method to determine whether new data has arrived.
- When data is present, call the stream's
GetBuffer
method to obtain the data.- Copy the data to your display part's storage.
- Call the stream's
ReleaseBuffer
method to release the buffer after the data has been copied.- Repeat steps 1 through 4 until enough data has been copied or until there is no more data to download.
- Draw the data; for example, by notifying OpenDoc that the data needs to be drawn or by drawing it yourself.
- When the download operation is complete, delete the stream.
HandleEvent
method. It calls thePollStream
method when a null event is received.Listing 4-20 The text-viewer part's
HandleEvent
method
ODBoolean CybTxtViewer::HandleEvent( Environment*ev, ODEventData*event, ODFrame* frame, ODFacet* facet, ODEventInfo*eventInfo ) { ODBooleaneventHandled = kODFalse; switch ( event->what ) { ... case kODEvtNull: if (fStream) PollStream(ev); break; ... default: break; } return eventHandled; }ThePollStream
method does the work associated with managing the stream. It checks whether any data is available to download from the stream. If so, thePollStream
method copies the data into a buffer and invalidates the screen so that OpenDoc displays the data when the screen is redrawn. When downloading ends or an error occurs, the stream is deleted. Listing 4-21 shows these actions.Listing 4-21 Handling downloaded data
void CybTxtViewer::PollStream(Environment* ev) { StreamStatus status; ODBoolean gotData = kODFalse; Size bytesThisPoll = 0; if (fStream == kODNULL) return; while (bytesThisPoll < kBytesPerPoll) { status = fStream->GetStreamStatus(ev); // Exit the loop if no data is available. if (!(status & kCDDataAvailable)) break; // Data is available. Get the buffer; copy it to the data area. char* buffer; Size size; fStream->GetBuffer(ev, &buffer, &size); if (buffer) { Size newLength = fCharsLength + size; if (newLength > fCharsAllocLength) newLength = fCharsAllocLength; if (newLength > fCharsLength) { ODBlockMove(buffer, fChars+fCharsLength, newLength - fCharsLength); fCharsLength = newLength; } gotData = kODTrue; bytesThisPoll += size; fStream->ReleaseBuffer(ev, buffer); } } // Check status. status = fStream->GetStreamStatus(ev); // Downloading is complete or an error occurred. if ((status & kCDDownloadComplete) || (status & kCDErrorOccurred) || (status & kCDAbortComplete)) { delete fStream; fStream = kODNULL; } if (gotData) ForceRedraw(ev); }During each call toPollStream
, at most kBytesPerPoll (defined as 8,192 bytes) is copied from the stream into thefchars
data structure. The text-viewer part defines the kBytesPerPoll constant, not Cyberdog.The ForceRedraw method is simply a method that invalidates the area in which the data in the
fchars
structure is to be displayed. OpenDoc redraws the invalidated area in the usual way.Locating the Cyberdog Item's Window
Cyberdog calls the part extension's GetCyberItemWindow method to locate a window that currently displays the specified Cyberdog item. If you do not override this method, the default GetCyberItemWindow method returns kODNULL and Cyberdog opens a new window in which to display the Cyberdog item's data. Your override can return a window that already displays the Cyberdog item's data. In this case, the window you return will be opened when the Cyberdog item is opened.In this example, the text-viewer part extension's GetCyberItemWindow method calls the text-viewer part's GetCyberItemWindow method to do the actual work. See "Overriding Cyberdog Part Extension Methods" (page 119) for information about the part extension's GetCyberItemWindow method.
Listing 4-22 shows the text-viewer part's GetCyberItemWindow method. The method returns a reference to a window if the window is already displaying the same Cyberdog item. The Cyberdog part extension's CanShowCyberItem method returns whether or not the Cyberdog item is displayed. If the Cyberdog item to be opened is not currently displayed, the method returns kODNULL. In response, Cyberdog opens a new window for the item.
Listing 4-22 The
GetCyberItemWindow
method of the text-viewer part
ODWindow* CybTxtViewer::GetCyberItemWindow (Environment *ev, CyberItem* item) { ODWindow* window = kODNULL; // Determine whether the part already displays the specified // Cyberdog item. if ( fCybTxtViewerCyberExt->CanShowCyberItem(ev, item) ) { // Iterate over the list of frames, looking for a root frame. // If a root frame is found, return its window. if(fDisplayFrames) { CListIterator fiter(fDisplayFrames); for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First(); fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() ) { if ( proxy->FrameIsLoaded(ev) ) { ODFrame* odFrame = proxy->GetFrame(ev); if(odFrame->IsRoot(ev)) { TempODWindow window = odFrame->AcquireWindow(ev); return window; } } } } } return kODNULL; }Closing Your Display Part's Window
When a user attempts to close a display part's window, your part must intercept this command and allow Cyberdog to close the window. This action is necessary because OpenDoc normally closes the Cyberdog session document when it closes the last open window and, thus, would require a new Cyberdog session document to be created the next time Cyberdog is used. Allowing Cyberdog to close the window avoids creating unnecessary sessions and session documents.Take these steps to close your part's window:
In the text-viewer part, two methods handle the closing of the part's window. The HandleEvent method closes the window after a click in the window's close box. The HandleMenuEvent method closes the window in response to a Close command. Both methods close the window in the same way.
- Obtain a reference to the Cyberdog session by calling the GetCyberSession function.
- Close the window by calling the Cyberdog session's CloseCyberDraftWindow method. The parameter to the CloseCyberDraftWindow method is a pointer to your part.
- Close the window in the normal way if the CloseCyberDraftWindow method returns kODFalse, indicating that the window was not in the Cyberdog session document.
Listing 4-23 shows the HandleEvent method.
Listing 4-23 The
HandleEvent
method of the text-viewer part
ODBoolean CybTxtViewer::HandleEvent( Environment*ev, ODEventData*event, ODFrame* frame, ODFacet* facet, ODEventInfo*eventInfo ) { ODBooleaneventHandled = kODFalse; switch ( event->what ) { ... case kODEvtWindow: if (event->message == inGoAway) { eventHandled = GetCyberSession(ev)->CloseCyberDraftWindow(ev, fSelf); } break; ... default: break; } return eventHandled; }Listing 4-24 shows the HandleMenuEvent method, which closes the window in response to a menu event.Listing 4-24 The
HandleMenuEvent
method of the text-viewer part
ODBoolean CybTxtViewer::HandleMenuEvent( Environment*ev, ODEventData*event, ODFrame* frame ) { ODULong menuResult = event->message; ODUShort menu = HiWord(menuResult); ODUShort item = LoWord(menuResult); ODBooleanhandled = kODTrue; ODULongcommandID; ... switch (commandID) ) { ... case kODCommandClose: handled = GetCyberSession(ev)->CloseCyberDraftWindow(ev, fSelf); break; ... default: handled = kODFalse; } return handled; }