Important: The information in this document is obsolete and should not be used for new development.
Cyberdog Item Opening Process
This section discusses the opening process of a Cyberdog item and how various Cyberdog objects play a role in that process. It begins with a description of how Cyberdog items are manipulated and stored. Then it discusses the opening process, including a description of the roles played by the Cyberdog item, Cyberdog display part, opener part, navigator, and download part. Finally, it describes various scenarios for implementing a Cyberdog item'sOpen
method and a Cyberdog display part'sOpenCyberItem
method.Manipulating and Storing Cyberdog Items
In order to understand the opening process of a Cyberdog item, it is useful to first understand the different ways in which a Cyberdog item is represented and how those representations are manipulated and stored.When displayed as an icon in a window, such as the log, a notebook, or a web page, a Cyberdog item is an object in memory; it is not an OpenDoc part. A user can open a Cyberdog item that is in memory by clicking on its icon. This action results in a call to the Cyberdog item's
Open
method.Cyberdog items implement their opening behavior; in other words, they know how to open themselves. In the simplest cases,
Open
creates a Cyberdog display part and calls itsOpenCyberItem
method.OpenCyberItem
initiates a download of the data referenced by the Cyberdog item and displays the display part. For more information on the objects involved in the opening process, see "Object Roles in the Opening Process" (page 72).When the user drags a Cyberdog item object (from a notebook, for example), the Cyberdog item is stored in the storage unit of the OpenDoc drag-and-drop object as kind
kCyberItemKind
. The destination of the drop determines what happens.
Copying and pasting of Cyberdog items are handled in a similar fashion.
- If the destination of the drop is the desktop or a Finder window, the Cyberdog item is stored as an OpenDoc part whose part kind is
kCyberItemKind
. If the user clicks on that part, OpenDoc creates an opener part (which binds to parts of kindkCyberItemKind
) to open the part.- If the destination of the drop is a container that does not manipulate data of kind
kCyberItemKind
, the container creates an embedded part, clones the contents of the drag-and-drop storage unit into its draft, and embeds the new part at an appropriate location in its content. Because the kind of the storage unit iskCyberItemKind
, OpenDoc creates an opener part to display the part.- If the destination of the drop is a container that does manipulate data of kind
kCyberItemKind
, the container can incorporate the data. For example, the container might display the Cyberdog item as an icon instead of displaying the content the item references.
Object Roles in the Opening Process
"A Cyberdog Example" (page 66) shows how to open a Cyberdog item that references content stored on a Gopher server. Because that Cyberdog item references text, it creates a Cyberdog text display part. The text display part downloads the data and displays it. That example represents the simplest case of opening a Cyberdog item: the Cyberdog item knows the type of the data it references and the text display part opens itself immediately.The primary responsibility for opening a Cyberdog item is shared between the Cyberdog item being opened (the Cyberdog item's
Open
method) and the display part that will display the data referenced by the Cyberdog item (the display part'sOpenCyberItem
method). However, opening a Cyberdog item is more complex in these situations:
The Cyberdog item and the Cyberdog display part may rely on other objects, such as an opener part, a navigator, or a download part, in these more complex opening scenarios.
- The Cyberdog item cannot identify the type of the data it references and thus cannot create a display part immediately.
- The Cyberdog item can identify the type of data it references, but cannot create a Cyberdog display part capable of downloading and displaying that type of data.
- The Cyberdog display part cannot open until all the data it is to display has been downloaded. For example, the Cyberdog QuickTime display part does not open until all of its data has been downloaded.
- The Cyberdog display part is embedded in a navigator.
Role of the Cyberdog Item
A Cyberdog item'sOpen
method is responsible for the following:
Some Cyberdog items (Gopher items, for example) are resolved inherently; they always refer to a single, known type of data. If you are developing a Cyberdog item that is resolved inherently, your Cyberdog item's
- resolving, or determining the type of data it refers to
- creating a Cyberdog display part appropriate for the data type in the appropriate document
- calling the display part's
OpenCyberItem
method
Open
method can be synchronous.Some other Cyberdog items (HTTP items, for example) cannot be resolved without communicating with the server on which the data they reference resides. If you are developing a Cyberdog item that is not resolved inherently, your Cyberdog item's
Open
method must be asynchronous.Role of the Display Part
When a Cyberdog item calls a Cyberdog display part'sOpenCyberItem
method, the display part is responsible for the following:
Some display parts (the Cyberdog HTML display part, for example) display data as it is downloaded; they do not wait to display until all the data has been downloaded. If you want your display part to display before the data referenced by its Cyberdog item has been completely downloaded, the display part's
- It must perform tasks to prepare for displaying the data referenced by its Cyberdog item, such as creating a stream and opening it to initiate the download operation.
- It must call its inherited
OpenCyberItem
method, which displays the display part.
OpenCyberItem
method can be synchronous.Some other display parts (the Cyberdog QuickTime display part, for example) do not display until all of the data they are to display has been downloaded. If you do not want your display part to display until the data referenced by its Cyberdog item has been completely downloaded, the display part's
OpenCyberItem
method must be asynchronous.In addition, a Cyberdog display part decides whether it is to be embedded in a navigator. If your display part is to be embedded in a navigator, you need to modify your
OpenCyberItem
method to obtain a navigator and call itsGoToCyberItem
method.Role of the Opener Part
The primary purpose of the opener part is to bridge the gap between a Cyberdog item stored in an OpenDoc document and the Cyberdog display part that displays the content referenced by the Cyberdog item. To bridge this gap, the opener part does the following:
A secondary purpose of the opener part is to display progress to the user during an asynchronous operation. A Cyberdog item or Cyberdog display part that initiates an asynchronous operation can attach a progress broadcaster to the opener part and use the opener part to display progress.
- It binds to parts of kind
kCyberItemKind
.- It serves as a placeholder in a document until the appropriate display part can be opened. The opener part replaces itself in a document, putting the resulting display part in its stead.
An initial opener part is an opener part created by OpenDoc to bind to a part of kind
kCyberItemKind
. In this situation, the initial opener part is passed as a parameter to the Cyberdog item'sOpen
method. However, before the Cyberdog item can use the initial opener part, the item must first obtain it from the Cyberdog session by calling the session object'sObtainOpener
method; this method returns an obtained opener part.You should always use the opener part returned by
ObtainOpener
and should not assume that it is the same as the initial opener part that you passed in. Once you have obtained an opener part, you should use the opener part's methods to manipulate it. For example, you should not call an obtained opener part'sOpen
method or place the opener part in an embedded frame.You can callObtainOpener
without worrying about whether it has already been called during the opening of a given Cyberdog item; the method can be called more than once.Binding to Stored Cyberdog Items
When a Cyberdog item is stored in a storage unit (for example, when it is stored on the desktop as a reference) its part kind iskCyberItemKind
. If the user later clicks on the Cyberdog item's reference icon on the desktop, OpenDoc attempts to create a part for the storage unit. Because the storage unit contains data of kindkCyberItemKind
, OpenDoc creates an opener part.The opener part reads the Cyberdog item from the storage unit by calling
CyberSession::CreateCyberItemFromSU
. The opener part waits until it is displayed in a frame and then calls the Cyberdog item'sOpen
method, passing itself as the initial opener part.Acting as a Placeholder for Display Parts
If either the Cyberdog item'sOpen
method or the Cyberdog display part'sOpenCyberItem
method is asynchronous, the method must obtain an opener part by callingCyberSession::ObtainOpener
and attach to the opener part a progress broadcaster representing the asynchronous operation. If eitherOpen
orOpenCyberItem
is passed an opener part as a parameter, the method can try to obtain that opener part by passing it as a parameter toObtainOpener
. However,ObtainOpener
may return a different opener part than the one passed to it.The opener part opens in its own window or in an embedded frame and displays progress during the opening process. The opener part is responsible for ensuring that a Cyberdog display part is created in the appropriate document and displayed in the right place on the screen.
- Your Cyberdog item's
Open
method must callCyberSession::CreateCyberPart
to create a display part. This method creates the display part in either an OpenDoc document or the session document, depending on which document contains the opener part.- Unless your display part is to be embedded in a navigator, your part's
OpenCyberItem
method must call its inherited method to display the part. The inheritedOpenCyberItem
method checks whether an opener part is being used. If so, the inherited method calls the opener part'sOpenPart
method;OpenPart
ensures that the display part is displayed in the right place. If not, the inherited method calls the display part'sOpen
method.
Role of the Navigator
A navigator is a special type of opener part;CyberNavigatorExtension
is a subclass ofCyberOpenerPartExtension
. As an opener part, a navigator can be a placeholder in a document during the opening process and can display progress. Unlike other opener parts, a navigator does not replace itself in a document, putting the resulting display part in its stead. Rather, the display part is embedded in the navigator. Also, a navigator does not bind to parts of kindkCyberItemKind.
The calling Cyberdog item may pass a navigator as a parameter to a Cyberdog display part's
OpenCyberItem
method. However, it is up to the display part to decide whether it will be embedded in a navigator.A display part that wants to be embedded in a navigator must obtain a navigator by calling
ObtainOpener
, passingkNavigatorKind
as the part kind of the opener part. The display part should always use the navigator returned byObtainOpener
. If a navigator was passed into theOpenCyberItem
method, the display part can try to obtain that navigator by passing it as a parameter toObtainOpener
. However,ObtainOpener
may not return the same navigator that the display part passed to it. For example, if the user has disabled the Browse in Place menu item in the Navigate menu,ObtainOpener
returns a new navigator.Once the display part has obtained a navigator, the display part should call the navigator's
GoToCyberItem
method, which displays the display part in the navigator.Role of the Download Part
A Cyberdog item callsCyberSession::CreateCyberPart
to create an appropriate Cyberdog display part for the data type referenced by the item. If no Cyberdog display part editor is available for that data type,CreateCyberPart
cannot create a Cyberdog display part. If so, the Cyberdog item can use a download part to download the data referenced by the item, save it to a file, and attempt to open the file in some other way.To create a download part, the Cyberdog item calls
CyberSession::CreatePartInCyberDocument
, passingkDownloadPartKind
as the part kind to be created. The Cyberdog item calls the resulting download part'sOpenCyberItem
method, which takes these actions:
- It obtains an opener part by calling
CyberSession::ObtainOpener
, passingkOpenerPartKind
as the opener part kind.- It downloads the data referenced by the Cyberdog item and saves it to a file.
- It calls the opener part's
OpenFile
method.OpenFile
tries to find a part editor (a non-Cyberdog part editor) that can open files of this type; if it cannot, it asks the Finder to open the file.
Implementing the Opening Methods
Responsibility for opening a Cyberdog item is divided between theOpen
method of the Cyberdog item being opened and theOpenCyberItem
method of the display part that will display the data referenced by the Cyberdog item.Implementing a Cyberdog Item's Open Method
The Cyberdog item'sOpen
method is responsible for determining the type of data the item references, creating an appropriate display part for that type of data, and calling the display part'sOpenCyberItem
method.If you are developing your own Cyberdog item, you must subclass the
CyberItem
class and override your subclass'sOpen
method to implement the item's opening behavior.Open as a Synchronous Method
If a Cyberdog item is inherently resolved, itsOpen
method can be asynchronous. Before returning,Open
calls the Cyberdog display part'sOpenCyberItem
method, which displays the display part. In this case, theOpen
method should perform the following steps:
- If the parameter set contains either an initial or an obtained opener part, retrieve it. For example, the parameter set may contain an opener part if the Cyberdog item is being opened from a storage unit, as discussed in "Binding to Stored Cyberdog Items" (page 75).
if (params) if (!params->GetParameter (ev, kCDInitialOpenerPartKey, &openerPart)) params->GetParameter (ev, kCDObtainedOpenerPartKey, &openerPart);
- Call
CyberSession::GetISOTypeFromMIMEType
to translate the MIME type of the data referenced by the Cyberdog item to a part kind.
ODValueType kind = cyberSession (ev)->GetISOTypeFromMIMEType (ev, someMIMEType);
- Call
CyberSession::CreateCyberPart
to create the part, passing the part kind and the opener part, if any.CreateCyberPart
determines whether to create the new part in the session document or in another OpenDoc document by checking which document the opener part is contained in.
ODPart* part = cyberSession->CreateCyberPart (ev, openerPart, kind, kODNULL);
- If
CreateCyberPart
cannot create a Cyberdog display part for the type of data referenced by the Cyberdog item and the referenced data can be downloaded, callCyberSession::CreatePartInCyberDocument
to create a download part.
if (!part && this->IsDownloadable (ev)) part = cyberSession->CreatePartInCyberDocument (ev, kDownloadPartKind, kODNULL);
- Call the display part's (or the download part's)
OpenCyberItem
method.
CyberPartExtension* CyberPartExt = part->GetExtension (ev, kCyberPartExtension); CyberPartExt->OpenCyberItem (ev, this, openerPart, params); CyberPartExt->Release (ev);Open as an Asynchronous Method
If the Cyberdog item is not inherently resolved, itsOpen
method must be asynchronous. In this case, the Cyberdog item must obtain an opener part to act as a placeholder and to display progress until an appropriate Cyberdog display part can be created. The Cyberdog item defers the call toOpenCyberItem
until the display part is created. In this case,Open
should perform the following steps:
- Determine whether the Cyberdog item has been resolved by calling its
isResolved
method. If the Cyberdog item is resolved, perform steps 1 to 5 described in "Open as a Synchronous Method" (page 77).- If the Cyberdog item has not been resolved, retrieve an initial or obtained opener part, if any, from the parameter set. For example, the parameter set may contain an opener part if the Cyberdog item is being opened from a storage unit, as discussed in "Binding to Stored Cyberdog Items" (page 75).
if (params) if (!params->GetParameter (ev, kCDInitialOpenerPartKey, &openerPart)) params->GetParameter (ev, kCDObtainedOpenerPartKey, &openerPart);
- Call the
CyberSession::ObtainOpener
method to obtain an opener part, passing the opener part retrieved from the parameter set, if any. You should acquire the parameter set before passing it toObtainOpener
. If no parameter set was passed to theOpen
method, you should create one before callingObtainOpener
.
openerPart = cyberSession->ObtainOpener (ev, openerPart, kODNULL, this, params);
- Call the Cyberdog item's
Resolve
method, passing a pointer to a notification function thatResolve
can call when the Cyberdog item is resolved.
this->Resolve (ev, MyCyberItemResolved, params, openerPart);Your Cyberdog item'sResolve
method should initiate whatever process is necessary for its resolution, such as creating and opening a Cyberdog stream. To display progress during the resolution process, theResolve
method should attach a progress broadcaster to the opener part and call the broadcaster's accessor methods to update its progress settings. When theResolve
method has finished trying to resolve the Cyberdog item, it should call the notification function.
Your resolution notification function should check the error code parameter to determine whether the Cyberdog item was resolved successfully. If the Cyberdog item is resolved, the resolution notification function should perform steps 1 to 5 described in "Open as a Synchronous Method" (page 77). The resolution notification function should release the parameter set.
- Note
- Do not call the resolution notification function at interrupt time.
Implementing a Display Part's OpenCyberItem Method
The Cyberdog display part'sOpenCyberItem
method is responsible for downloading and displaying the data referenced by the Cyberdog item. If you are developing your own Cyberdog display part, you must subclassCyberPartExtension
and override your subclass'sOpenCyberItem
method.OpenCyberItem as a Synchronous Method
A Cyberdog display part'sOpenCyberItem
method can be synchronous if the display part can be displayed before all of the data it is to display has been downloaded. In this case,OpenCyberItem
should perform the following steps:
- Call the Cyberdog item's
CreateCyberStream
method to retrieve a stream for downloading the data and call the stream'sOpen
method to initiate the download operation.
fMyStream = fMyItem->CreateCyberStream (ev); fMyStream->Open (ev);
- Retrieve the Cyberdog item's parent item, if any, from the parameter set, and call
CyberSession::AddCyberItemToLog
to add the Cyberdog item to the log.
CyberItem* parent = kODNULL; if (params) params->GetParameter (ev, kCDParentItemKey, &parent); GetCyberSession (ev)->AddCyberItemToLog (ev, parent, fMyItem);
- Call the inherited
OpenCyberItem
method, which displays the display part.
inherited::OpenCyberItem (item, openerPart, params);OpenCyberItem as an Asynchronous Method
If a Cyberdog display part cannot be displayed until all the content referenced by its Cyberdog item has been downloaded, the display part'sOpenCyberItem
method must asynchronous.OpenCyberItem
does not call its inherited method; calling the inherited method is deferred until the data has been downloaded.In this case,
OpenCyberItem
should perform the following steps:
- Retrieve the Cyberdog item's parent item, if any, from the parameter set, and call
CyberSession::AddCyberItemToLog
to add the Cyberdog item to the log.
CyberItem* parent = kODNULL; if (params) params->GetParameter (ev, kCDParentItemKey, &parent); GetCyberSession (ev)->AddCyberItemToLog (ev, parent, fMyItem);
- Call the
CyberSession::ObtainOpener
method to obtain an opener part, which will be used to display progress until the display part can be displayed. You must acquire the parameter set before passing it toObtainOpener
. If no parameter set was passed to theOpen
method, you should create one before callingObtainOpener
.
openerPart = cyberSession->ObtainOpener (ev, openerPart, kODNULL, this, params);
- Call a method that initiates whatever asynchronous process is necessary for the data to be displayed, such as creating and opening a Cyberdog stream. To display progress while the data is downloaded, the method should attach a progress broadcaster to the opener part and call the broadcaster's accessor methods to update its progress settings. When the method is finished downloading the data, it should call the inherited
OpenCyberItem
method.
Embedding a Display Part in a Navigator
A Cyberdog display part determines whether to embed itself in a navigator. If so, the display part must callObtainOpener
to obtain a navigator. In this case,OpenCyberItem
performs the following steps:
- Call the Cyberdog item's
CreateCyberStream
method to retrieve a stream for downloading the data and call the stream'sOpen
method to initiate the download operation.
fMyStream = fMyItem->CreateCyberStream (ev); fMyStream->Open (ev);
- Retrieve the Cyberdog item's parent item, if any, from the parameter set, and call
CyberSession::AddCyberItemToLog
to add the Cyberdog item to the log.
CyberItem* parent = kODNULL; if (params) params->GetParameter (ev, kCDParentItemKey, &parent); GetCyberSession (ev)->AddCyberItemToLog (ev, parent, fMyItem);
- Call the display part's
SetCyberItem
method to store a reference to the Cyberdog item. This method is called by the inheritedOpenCyberItem
method; however, in this case, the inheritedOpenCyberItem
method is not called.
SetCyberItem (item, params);
- Call the
CyberSession::ObtainOpener
method, passingkNavigatorKind
as the opener part kind, to obtain a navigator. You must acquire the parameter set before passing it toObtainOpener
. If no parameter set was passed to theOpen
method, you should create one before callingObtainOpener
.
ODPart* navPart = GetCyberSession()->ObtainOpener (ev, openerPart, kNavigatorKind, item, params);
- Instead of calling the display part's
OpenCyberItem
method, call the navigator'sGoToCyberItem
method, which displays the display part in the navigator.
TempNavigatorExtension navigatorExt (navPart, kCyberNavigatorExtension); navigatorExt->GoToCyberItem (ev, item, this->GetODPart(), params);
- Release the parameter set.
params->Release (ev);
- Note
- The previous scenario assumes that
OpenCyberItem
is synchronous. However, a display part whoseOpenCyberItem
method is asynchronous can also be embedded in a navigator.