Important: The information in this document is obsolete and should not be used for new development.
Manipulating a Cyberdog Item
To use a Cyberdog item, your part must be able to create and open one. If you want a Cyberdog item to persist between sessions, you must support reading and writing Cyberdog items. To support data interchange of Cyberdog items, your part should support drag and drop.The button part manipulates Cyberdog items in the following ways, as described in the following sections:
- It creates a Cyberdog item from a URL.
- It reads a Cyberdog item from a storage unit and writes an item to the unit.
- It opens a Cyberdog item.
- It handles drag and drop of a Cyberdog item.
Creating a Cyberdog Item From a URL
To create a Cyberdog item from a URL, you must first obtain a reference to the Cyberdog session by calling the GetCyberSession function. You then can create a Cyberdog item from the URL text by calling the Cyberdog session's CreateCyberItemFromURL method. Optionally, you can set the default name of the Cyberdog item.Listing 3-5 shows how the button part creates a Cyberdog item when the part is first opened. The default URL text, which is stored in the part's resource fork, is used to create the item and to set the item's display name.
Listing 3-5 The button part's
InitPart
method
void CybTxtBtn::InitPart( Environment* ev, ODStorageUnit* storageUnit, ODPart* partWrapper ) { TRY fSelf = partWrapper; fReadOnlyStorage = kODFalse; // Call the common initialization code to initialize Cyberdog. this->Initialize(ev, storageUnit); // Use CUsingLibraryResources to access part's resource fork. { CUsingLibraryResources fil; Str255defaultURL; // Get the default string from the resource fork. ::GetIndString( defaultURL, kMenuStringResID, kDefaultContent1ID); if (defaultURL[0] == 0) DebugStr("\p InitPart -- couldn't get string."); else { // Make a C string out of the default URL pascal string. char cStr[255]; ODBlockMove(&defaultURL[1], cStr, defaultURL[0]); cStr[ defaultURL[0] ] = 0; // Create a Cyberdog item from the URL. fCyberItem = GetCyberSession(ev)->CreateCyberItemFromURL (ev, (char*)cStr); // Make the default name equivalent to the URL. // Assume all URLs are smRoman font. if (fCyberItem) fCyberItem->SetDefaultName(ev, defaultURL, smRoman); } } // Allow the state and content info to be written to storage. this->SetDirty(ev); CATCH_ALL RERAISE; ENDTRY }
- Note
- The default font for displaying URL's is
smRoman
. uReading and Writing Cyberdog Items
To read a Cyberdog item from a storage unit, you must obtain a reference to the Cyberdog session by calling the GetCyberSession function. You then can call the session's CreateCyberItemFromSU method. Optionally, you can call the Cyberdog item's GetStringProperty method to retrieve the string associated with the item's display name, as indicated by the kCDDefaultName constant.Listing 3-6 shows the button part's
InternalizeContent
method, which replaces the current Cyberdog item, if one exists, with one that has just been created from the storage unit. (TheInternalizeContent
method is called by theInitPartFromStorage
method.)Listing 3-6 The button part's
InternalizeContent
method
void CybTxtBtn::InternalizeContent (Environment* ev, ODStorageUnit* storageUnit) { if (ODSUExistsThenFocus(ev, storageUnit, kODPropContents, kCybTxtBtnKind)) { CyberItem* ci = kODNULL; // Retrieve the Cyberdog item from the storage unit. ci = GetCyberSession(ev)->CreateCyberItemFromSU(ev, storageUnit); // Replace the current Cyberdog item with the one in the // storage unit. if (ci != kODNULL) { if (fCyberItem != kODNULL) fCyberItem->Release(ev); fCyberItem = ci; } } }To write a Cyberdog item to a storage unit, you can call the item's StreamToStorageUnit method. Listing 3-7 shows the button part'sExternalizeContent
method, which takes this action. (TheInternalizeContent
method is called by theExternalize
method and other methods that write to storage units.)Listing 3-7 The button part's
ExternalizeContent
method
void CybTxtBtn::ExternalizeContent( Environment* ev, ODStorageUnit* storageUnit, ODDraftKey /*key*/, ODFrame* /*scopeFrame*/ ) { // Focus on content property and get the current size of the data. ODSUForceFocus(ev, storageUnit, kODPropContents, kCybTxtBtnKind); ODULong oldSize = storageUnit->GetSize(ev); // Flatten an item to a buffer and then write the // buffer out to the specified ODStorageUnit. fCyberItem->StreamToStorageUnit(ev, storageUnit); ODULong newSize = storageUnit->GetOffset(ev); if (newSize < oldSize) storageUnit->DeleteValue(ev, oldSize - newSize); }Once you write the Cyberdog item to storage in this fashion, you must call the Cyberdog session's CreateCyberItemFromSU method to recreate the item in the storage unit (see Listing 3-6).
- Note
- Whenever you store data in an OpenDoc storage unit, you must modify all methods that work with storage and change them to support your kind of data. In this example, the
kCybTxtBtnKind
constant specifies the kind of data associated with the Cyberdog item. It is defined as follows:#define kCybTxtBtnKind kODISOPrefix "Apple:Kind:CybTxtBtn" uOpening a Cyberdog Item
You call the Cyberdog item'sOpen
method to open a Cyberdog item. What it means to open a Cyberdog item depends on the kind of data at the location referenced by the Cyberdog item. For example, if the Cyberdog item represents a URL for HTML-formatted data, calling the item'sOpen
method causes the data to be downloaded and displayed in a Cyberdog display part. If the Cyberdog item represents an e-mail address, calling the item'sOpen
method results in actions to send mail.The
Open
method takes, as a parameter, a ParameterSet object that specifies various options for opening the Cyberdog item. The value can benil
, meaning that no additional options are used. For information about the ParameterSet class, see "ParameterSet" (page 391).Listing 3-8 shows a portion of the button part's HandleMouseEvent method from which the Cyberdog item's
Open
method is called. The HandleMouseEvent method is called when the user clicks in the button part. (The HandleMouseEvent method is called from theHandleEvent
method.)Listing 3-8 Opening the Cyberdog item
ODBoolean CybTxtBtn::HandleMouseEvent( Environment* ev, ODEventData* event, ODFacet* facet, ODEventInfo* eventInfo ) { if ( facet != kODNULL ) { if ( event->what == kODEvtMouseUp ) { ... } else if ( event->what == kODEvtMouseDown ) { if (fCyberItem == kODNULL) SysBeep(1); else fCyberItem->Open(ev, nil); } } else { SysBeep(1); } return kODTrue; }Supporting Drag and Drop of Cyberdog Items
To support drag and drop, you must implement the OpenDoc drag-and-drop protocol, which is explained in OpenDoc Programmer's Guide. It involves overriding the DragEnter, DragWithin, DragLeave, and Drop methods. To support drag and drop of Cyberdog items, you must modify two methods:
In this example, the button part accepts drags of Cyberdog items and of text. Text is used to create a Cyberdog item representing a URL.
- Modify the
DragEnter
method so that a Cyberdog item can be dragged onto the part.- Modify the
Drop
method so that the part accepts the dropped item.
Listing 3-9 shows the
DragEnter
method that checks for Cyberdog items and for text. The kCyberItemKind constant, which is passed to the storage unit'sExists
method, identifies a Cyberdog item.Listing 3-9 The button part's
DragEnter
method
ODDragResult CybTxtBtn::DragEnter(Environment* ev, ODDragItemIterator* dragInfo, ODFacet* facet, ODPoint* where) { ODUnused(facet); ODUnused(where); ODStorageUnit dragSU; ODValueType textType = ODGetSession(ev,fSelf)->GetTranslation(ev)-> GetISOTypeFromPlatformType(ev, 'TEXT', kODPlatformDataType); fAcceptThisDrag = kODFalse; fActiveFrameHilitedForDrop = kODFalse; // Accept the drag if it is a Cyberdog item or text for (dragSU = dragInfo->First(ev); dragSU != kODNULL; dragSU = dragInfo->Next(ev)) { if (dragSU->Exists(ev, kODPropContents, kCyberItemKind, 0)) fAcceptThisDrag = kODTrue; else if (dragSU->Exists(ev, kODPropContents, textType, 0)) fAcceptThisDrag = kODTrue; } return fAcceptThisDrag; }TheDrop
method handles dropping of data allowed by theDragEnter
method. Specifically, the method should create a Cyberdog item from the specified kind of data. You create a Cyberdog item from an item dropped into your part's storage unit by calling the Cyberdog session's CreateCyberItemFromSU method. In the call to CreateCyberItemFromSU, you specify the drag storage unit as a parameter. If your part supports drag and drop of text, you can create a Cyberdog item by calling the Cyberdog session's CreateCyberItemFromURL method.Listing 3-10 shows how the button part creates a Cyberdog item when Cyberdog item data or text is dropped on the part. If a Cyberdog item already exists, it is released and a reference to the newly created Cyberdog item is saved in the
fCyberItem
field. The draft is marked as dirty so that its state will be saved, and the facet is invalidated so that it will be redrawn.Listing 3-10 The button part's
Drop
method
ODDropResult CybTxtBtn::Drop(Environment* ev, ODDragItemIterator* dragInfo, ODFacet* facet, ODPoint* where) { ODStorageUnit*dragSU; CyberItem* ci = kODNULL; CyberSession*cyberSession = GetCyberSession(ev); ScriptCode script= smRoman; ODValueType textType = ODGetSession(ev,fSelf)-> GetTranslation(ev)->GetISOTypeFromPlatformType(ev, 'TEXT', kODPlatformDataType); for (dragSU = dragInfo->First(ev); dragSU != kODNULL; dragSU = dragInfo->Next(ev)) { // A Cyberdog item is dropped. if (dragSU->Exists(ev, kODPropContents, kCyberItemKind, 0)) { // Focus on the Cyberdog item data in the drag storage unit dragSU->Focus(ev, kODPropContents, kODPosUndefined, kCyberItemKind, 0, kODPosUndefined); // Retrieve the Cyberdog item from the drag storage unit. ci = cyberSession->CreateCyberItemFromSU(ev, dragSU); } // The drop is not a Cyberdog item; deal with it as text. else if (dragSU->Exists(ev, kODPropContents, textType, 0)) { Size textSize = 0; ODPtr theText = kODNULL; // Get the text from the drag storage unit. dragSU->Focus(ev, kODPropContents, kODPosUndefined, textType, 0, kODPosUndefined); // Get the text length and enough memory for the text. textSize = (long) dragSU->GetSize(ev); theText = ODNewPtrClear(textSize + 1); if (theText) { // Read the text. StorageUnitGetValue(dragSU, ev, textSize, (ODValue)theText); // Create a Cyberdog item for the text. ci = cyberSession->CreateCyberItemFromURL(ev, (char*)theText); if (ci != kODNULL) { // Convert the text to a pascal string. Str255 pStr; Size maxSize = 255; textSize = (textSize > maxSize) ? maxSize : textSize; ODBlockMove(theText, &pStr[1], textSize); pStr[0] = textSize; // Set the Cyberdog item's default name. ci->SetDefaultName(ev, pStr, script); } ODDisposePtr(theText); } } // Replace the current Cyberdog item with the one from the drop. if (ci != kODNULL) { if (fCyberItem != kODNULL) fCyberItem->Release(ev); fCyberItem = ci; // Successful; save the state and invalidate the display. this->SetDirty(ev); facet->Invalidate(ev, kODNULL, kODNULL); return kODDropCopy; } } // Not successful return kODDropFail; }