Working With Your Display Frames and Facets
Your part's display frames are the frames in which you draw your part's contents. This section discusses how to request or respond to changes and additions to those frames.You do not directly create your own part's display frames; your part's containing part does that. When your part is first created or first read into memory from storage, the containing part of your part will in most cases have already provided at least one frame for your part to display itself in. However, it is possible that your part can be instantiated without already having a display frame (see "Adding an Embedded Part"). Your part should allow for that possibility.
Your part should also allow for the possibility of multiple display frames. Your part must keep a list of its display frames, with enough information so that your part knows how to display itself in each and synchronize their displays when necessary. OpenDoc does not specify the format of that list. It is your responsibility to keep the list and to update each display frame that has been affected by any change to your part.
Responding to Reconnected and Closed Display Frames
When the document containing your part opens and your previously stored display frames are read in and instantiated, OpenDoc calls your part'sDisplayFrameConnected
method. Here is its interface (note that this and all other method prototypes in this book are written in IDL):
void DisplayFrameConnected(in ODFrame frame);YourDisplayFrameConnected
method should update your part's internal list of display frames and other related structures to reflect the addition of the frame. It should assign the frame's used shape, if different from the frame shape itself. The method should also check the frame's content extent and update it if necessary, as described in "Content Extent". The method should also call the frame's SetDroppable method if you wish the frame to be able to accept drops.Unlike
DisplayFrameAdded
(see page 111), yourDisplayFrameConnected
method does not normally have to create new part info data or a new set of embedded frames for the display frame, because they will have been created earlier.When your part's document is closed, OpenDoc calls your part's
DisplayFrameClosed
method when it closes your display frame.
void DisplayFrameClosed(in ODFrame frame);YourDisplayFrameClosed
method should
If this frame is the root frame of your window and you have previously instructed OpenDoc not to dispose of the platform-specific window structure (see "Allocating Window Memory Efficiently"), you must dispose of the platform window yourself at this time.
- update your part's internal list of display frames and other related structures to reflect the closing of the frame
- relinquish any foci owned by the frame (see "Relinquishing Foci")
- unregister the frame, if your part has registered it for idle time (see "Null Events"), you must dispose of the platform window yourself at this time.
- call the
Close
method of all your embedded frames
Closing and reconnecting can happen at other times as well:
Do not update your persistently stored display frames when your
- When a part's editor is changed at runtime, OpenDoc calls the
DisplayFrameClosed
method of the editor losing the part and theDisplayFrameConnected
method of the editor receiving the part.- For efficient memory use, a containing part may not always keep frame objects in memory for all of its embedded frames. Instead, as described in the section "Reconnecting and Releasing Embedded Frames", it might release frames as they become invisible through scrolling, and recreate them as they become visible. Released frames can then be closed by OpenDoc.
DisplayFrameConnected
orDisplayFrameClosed
methods is called; these methods should have no effect on stored data. In general, you should write your part content and frames to storage only when yourExternalize
orExternalizeKinds
methods is called.Responding to Added or Removed Facets
When your part's containing part has added a facet to one of your part's display frames, the display frame notifies your part of the addition by calling your part'sFacetAdded
method. Here is its interface:
void FacetAdded(in ODFacet facet);YourFacetAdded
method must perform certain actions to handle the addition of the new facet to one of your frames. Some actions depend on the nature and implementation of your part itself, but others are standard.
When a containing part removes a facet from one of your part's display frames, the frame notifies your part by calling your part's
- The
FacetAdded
method should examine the facet's canvas to make sure your part editor understands how to draw on that canvas; it should return an error if it does not understand.- The method should store any private information that it needs as part info data in the facet that is being added. Although a facet's part info is not persistent, it can hold information (such as a view port reference, for example) that the facet needs for display.
- The method should assign an active shape to the facet, if needed. If you do not explicitly assign an active shape, OpenDoc uses the frame shape of the facet's associated frame as the active shape.
- The method should create facets for all embedded frames that are visible within the area of the added facet. See "Adding a Facet".
FacetRemoved
method, which has the following interface:
void FacetRemoved(in ODFacet facet);YourFacetRemoved
method must perform certain actions to handle the removal of the facet. In general, this method reverses the actions performed byFacetAdded
. Typically, the method should at least
Facets are intended to be ephemeral objects; don't retain references to them when they are no longer needed. Your
- remove the facets for all embedded frames that were visible in the area of the removed facet
- delete any part info data that was referenced in the facet
FacetRemoved
method should delete all references to the facets that it removes.
- Note
- If your part is visible in a window, it receives a
FacetAdded
call from its display frame when the window opens, and aFacetRemoved
call when the window closes.![]()
Resizing a Display Frame
Because of editing operations in your part, or because of an undesirable frame size imposed by your part's containing part, you may wish to change the size or shape of your display frame. You must negotiate this change with the containing part. (For an example of frame negotiation, showing the points of view of both the containing part and the embedded part, see the section "Frame Negotiation".)You start by requesting a new frame size from your part's containing part. Depending on its current contents and other constraints such as gridding, the containing part may grant the requested size, return a different size, or in essence refuse the request by returning a size identical to your current frame size.
To request a new frame size, take these steps:
- Call the
RequestFrameShape
method of your display frame. The frame in turn calls the containing part'sRequestFrameShape
method to forward the request.- The containing part may honor the request, or it may decide on a different (usually smaller) shape. It returns the shape it will let your display frame have. The frame stores it as its frame shape and returns it to you.
- Use the returned frame shape to update the used shape for that frame. At this time, you can also update the active shape of your frame's facet.
- If your part does not wish to accept the new shape, it can call the frame's
RequestFrameShape
method again, but with a different shape to avoid endless repetition of these steps. Alternatively, it can request an additional frame, as described in the section "Requesting an Additional Display Frame" (next).
Requesting an Additional Display Frame
Your part may need a display frame in addition to the frame or frames already created by your part's containing part. For example, you may need to flow content into another frame (as when you add another column or page of text), or you may need another frame to display your part with a new presentation.To request another frame, you can call the
RequestEmbeddedFrame
method of the containing part. You must specify one of your current display frames as the base frame, the frame that defines certain characteristics of the new frame.
You also pass additional information, such as the new frame's view type, presentation, and overlay status (that is, whether it should overlay, or float over, the content of the containing part).
- The new frame is a sibling of the base frame; that is, it is embedded at the same level as the base frame.
- The new frame is in the same frame group as the base frame.
- The new frame has a sequence number within the base frame's frame group, assigned by the containing part. (By convention, the containing part adds the new frame to the end of the sequence in that group.)
The shape you request for the new frame is understood to be expressed in the frame coordinates of the base frame (see "Frame Coordinate Space"). Thus you can request a position for the new frame that is relative to the base frame (such as above, below, to the side, or overlapping) by specifying an origin that is offset from the base frame's origin. The containing part has ultimate control over frame positioning, however, and is not required to size or place the new frame exactly as you request. Furthermore, the frame shape returned by the containing part is by convention normalized; that is, the relative-positioning information has been stripped from it and its origin is
at (0, 0).The containing part responds to this call as described in "Adding an Embedded Frame on Request". Your part then responds as described in "Responding to an Added Display Frame" (next).
Responding to an Added Display Frame
When an additional display frame is created, OpenDoc automatically connects it to the part it displays. This automatic connection ensures that frames are always valid and usable; the object that creates the new frame need do nothing beyond creating the frame itself.To achieve that automatic connection, the part displayed in the frame must respond to this method call, which informs the part that it has a new frame:
void DisplayFrameAdded(in ODFrame frame);Your part receives this call when it is first created and has no previously stored display frame, and also when additional display frames are created for it. In response to this call, your part'sDisplayFrameAdded
method performs the appropriate tasks. Most of them depend on the nature and implementation of your part itself; however, here are some general actions it should take:
Your part should not perform any layout or imaging tasks as a result of a display frame being added; specifically, it should not at this point negotiate with its containing part for a different frame shape. It should wait until its
- The method should add the new display frame to your part's list of display frames. This list, like other internal structures, is completely hidden from OpenDoc. You can represent the list any way you choose.
- The method should validate the view type and presentation of the new frame. Your part should accept any view types that are in the required set of view types, plus any other view types or presentations that you support. The
DisplayFrameAdded
method should correct these values if necessary, as described in the section "Defining General Display Characteristics".- The method should assign your part's current content extent to the frame, using the frame's
ChangeContentExtent
method; see "Content Extent" for an explanation.- The method should assign a used shape for the frame. If you do not specifically assign a used shape, the frame shape is used; a containing part that calls the frame's
AcquireUsedShape
method receives the frame shape in that case.- The method should add any needed part info to the frame, by calling the frame's
SetPartInfo
method. See the section "Part Info" for more information.- If the frame being added is the root frame of its window, your part may want to activate itself. Part activation is described in the section "How Part Activation Happens". (This situation can occur only when your part is first opened into a window, such as a part window; it cannot happen when an additional display frame for the current window is created.)
- If the frame being added can accept dropped data, the method should call the frame's
SetDroppable
method, passing it a value ofkODTrue
. (Frames, by default, are not droppable.) Otherwise, the frame will not be able to receive data through drag and drop. See "Drag and Drop" for more information.
FacetAdded
method is called, by which time the containing part has stored the frame shape and the frame has become visible.
- Note
- OpenDoc calls
DisplayFrameAdded
only when a frame is newly created. When your part opens and its stored display frame is recreated, OpenDoc calls your part'sDisplayFrameConnected
method; see "Responding to Reconnected and Closed Display Frames"![]()
Removing a Display Frame
To remove a frame in which your part is displayed, you call theRemoveEmbeddedFrame
method of your part's containing part (see "Removing an Embedded Frame"). You can remove only those frames that you have previously requested through calls to your containing part'sRequestEmbeddedFrame
method. Your other display frames can be removed only by your containing part.When the containing part receives the
RemoveEmbedded
Frame call, it permanently severs all connection between your part and the frame (and the draft object may delete the frame from storage if its reference count becomes 0). Just before deleting the frame, OpenDoc calls your part'sDisplayFrameRemoved
method (next).Responding to a Removed Display Frame
Your part's containing part can also initiate removal of one of your display frames, as described in "Removing an Embedded Frame". The removal may occur, for example, if your frame is part of a selection that is cut or deleted.Regardless of whether your part or the containing part initiates the removal, OpenDoc calls your part's
DisplayFrameRemoved
method. This is its interface:
void DisplayFrameRemoved(in ODFrame frame);In yourDisplayFrameRemoved
method, take steps such as these:
If this frame is the root frame of your window and you have previously instructed OpenDoc not to dispose of the platform-specific window structure (see "Allocating Window Memory Efficiently"), you must dispose of the platform window yourself at this time.
- Relinquish any foci owned by the frame (see "Relinquishing Foci").
- Delete any part info that your part had associated with the frame. Set the frame's part info data to null by calling the frame's
SetPartInfo
method.- Unregister the frame, if your part had registered it for idle time (see "Null Events").
- Update your part's internal list of display frames and other related structures to reflect the removal of the frame.
- Remove in turn any embedded frames that your part had been displaying in the removed frame. Check the identity of the embedded frame's containing frame to determine which call to make:
- If your (removed) display frame is designated as the embedded frame's containing frame, the display frame has not been moved from your part to another object. In this case, call the embedded frame's
Remove
method.- If your (removed) display frame is not designated as the embedded frame's containing frame, the display frame has been moved from
your part to another object. In this case, call the embedded frame'sRelease
method.
- Note
- OpenDoc calls
DisplayFrameRemoved
only when a frame is permanently removed from your part. When your part closes and OpenDoc stores its display frame, OpenDoc calls your part'sDisplayFrameClosed
method; see "Responding to Reconnected and Closed Display Frames".![]()
Grouping Display Frames
As an embedded part, your part does not directly control the frames in which it is displayed. However, you may need to flow text or other content in order through a sequence of separate display frames of your part (as for page-layout purposes). If so, you can request that the containing part create and assign you the needed frames as a sequence in a single frame group. See "Creating Frame Groups".If your part's containing part adds a new frame to your display frame's group or reorders the sequence of one of your display frames within its group (by calling the frame's
ChangeSequenceNumber
method), OpenDoc calls your part'sSequenceChanged
method. This is its interface:
void SequenceChanged(in ODFrame frame);Your part can then retrieve the new sequence number of the frame by calling itsGetSequenceNumber
method.Synchronizing Display Frames
Sometimes, views of your part in two or more separate frames must be synchronized, meaning that any editing or other changes to the contents of one (the source frame) must force updating of the other. In some cases, such as when you open one of your display frames into a window, you can determine these dependencies internally. In other cases, you cannot. For example, if your part is an embedded part and your containing part creates multiple views of your part, your containing part asks you to synchronize those views by calling your part'sAttachSourceFrame
method. This is its interface:
void AttachSourceFrame(in ODFrame frame, in ODFrame sourceFrame);YourAttachSourceFrame
method should take whatever action is necessary to synchronize the frames; make sure that the result of any editing in one frame appears in the other. At a minimum, if the two frames have the same presentation, the method should duplicate all the embedded frames of one frame into the other (and attach them to their source frames as well).It is the containing frame that determines when embedded frames must be synchronized. See "Synchronizing Embedded Frames".
Adopting Container Properties
As described in the section "Transmitting Your Container Properties to Embedded Parts", a containing part can notify its embedded parts of the container properties, the characteristics of its content that it expects the embedded parts to adopt. For example, if your part is a text part and the user embeds it in another text part, the containing part may expect your part to adopt the general text appearance (font, size, stylistic variation, and so on) of the containing part.Your part can, of course, adopt only those container properties whose format and meaning it understands. You obtain the set of container properties
that your containing part makes available for adoption by calling theAcquireContainingPartProperties
method of your containing part.A containing part calls your part's
ContainingPartPropertiesUpdated
method when it changes any of the container properties available for your part to adopt. This is its interface:
void ContainingPartPropertiesUpdated (in ODFrame frame, in ODStorageUnit propertyUnit);YourContainingPartPropertiesUpdated
method should read and adopt any container properties that it understands from the provided storage unit. Then, it should in turn call theContainingPartPropertiesUpdated
method of any of your part's own embedded frames (other than bundled frames) that are displayed within the frame passed toContainingPartPropertiesUpdated
.
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help