Programming Guide


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's DisplayFrameConnected method. Here is its interface (this and all other method prototypes in this book are written in IDL):

void DisplayFrameConnected(in ODFrame frame);

Your DisplayFrameConnected 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 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 for DisplayFrameAdded (see "Responding to an Added Display Frame"), your DisplayFrameConnected 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);

Your DisplayFrameClosed method should

  1. Update your part's internal list of display frames and other related structures to reflect the closing of the frame

  2. Relinquish any focus owned by the frame (see "Relinquishing Focuses")

  3. Call the Close method of all your embedded frames

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, you must dispose of the platform window yourself at this time.

Closing and reconnecting can happen at other times as well:

Do not update your persistently stored display frames when your DisplayFrameConnected or DisplayFrameClosed methods are called; these methods should have no effect on stored data. In general, you should write your part content and frames to storage only when your Externalize or ExternalizeKinds methods are 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's FacetAdded method. The interface is:

void FacetAdded (in ODFacet facet);

Your FacetAdded 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 FacetRemoved method:

void FacetRemoved (in ODFacet facet);

Your FacetRemoved method must perform certain actions to handle the removal of the facet. In general, this method reverses the actions performed by FacetAdded. Typically, the method should at least:

Facets are intended to be ephemeral objects. Do not hold references to them when they are no longer needed. Your FacetRemoved method should delete all references to the facets that it removes.

Note:

If your part is the root part in a window, it receives a FacetAdded call from the root frame when the window is opened and a FacetRemoved call from the root frame when the window is closed.

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 point of view of both the containing part and the embedded part, see "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 refuse the request by returning a size identical to your current frame size.

        To request a new frame size, take these steps:

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 an extra frame 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 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 connects it to the part it displays. This 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 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's DisplayFrameAdded 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 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's DisplayFrameConnected 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 the RemoveEmbeddedFrame 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's RequestEmbeddedFrame method. Your other display frames can be removed only by your containing part.

When the containing part receives the RemoveEmbeddedFrame 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).

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 your DisplayFrameRemoved method, take steps such as these:

  1. Relinquish any focus owned by the frame (see "Relinquishing Focuses" ).

  2. 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.

  3. Update your part's internal list of display frames and other related structures to reflect the removal of the frame.

  4. 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 this frame is the root frame of your window and you have previously instructed OpenDoc not to dispose of the platform-specific window structure, you must dispose of the platform window yourself at this time.

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's DisplayFrameClosed 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, if you need to flow text or other content through a sequence of separate display frames of your part (as for page-layout purposes) then you can request that the containing part create and assign 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's SequenceChanged method. This is its interface:

void SequenceChanged(in ODFrame frame);

Your part can then retrieve the new sequence number of the frame by calling its GetSequenceNumber 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's AttachSourceFrame method. This is its interface:

void AttachSourceFrame(in ODFrame frame,
                       in ODFrame sourceFrame);

Your AttachSourceFrame 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 embedded frames in 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 "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 into 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 the AcquireContainingPartProperties 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);

Your ContainingPartPropertiesUpdated method should read and adopt any container properties that it understands from the provided storage unit. Then, it should in turn call the ContainingPartPropertiesUpdated method of any of your part's own embedded frames (other than bundled frames) that are displayed within the frame passed to ContainingPartPropertiesUpdated.


[ Top | Previous | Next | Contents | Index | Documentation Homepage ]