Patching OpenDoc
You can enhance or alter the functioning of OpenDoc in ways even more fundamental than implementing extension interfaces, dispatch modules, and focus modules. Because OpenDoc is modular and object-oriented, you can directly replace certain of its objects with your own versions.OpenDoc allows you to patch any of its session-level objects. The session-level objects are those directly referenced by the session object, as shown in Figure 11-4. They are represented by these OpenDoc classes:
ODArbitrator ODInfo ODSemanticInterface subclass[11] ODBinding ODLinkManager ODStorageSystem ODClipboard ODMessageInterface ODTranslation ODDispatcher ODNameResolver ODUndo ODDragAndDrop ODNameSpaceManager ODWindowState This section discusses the mechanics of writing a patch to a session-level object, although it does not discuss the capabilities of the individual objects or the reasons for patching them. Before patching any object, be sure you are very familiar with its purpose and its interface. Read the appropriate parts of this book and the OpenDoc Class Reference for the Mac OS for more information.
Writing a Patch
Because your OpenDoc patch replaces a specific object with a known public interface, you should write it as a subclass of the class of object you are patching. You must override every method, and your overrides (other thansomInit
andsomUninit
) should not call their inherited versions. If you want only partial replacement of OpenDoc's functionality, delegate to the patched-
out object (the one you have replaced) those methods that you do not wish to change.Immediately after creating your replacement object, your patch installer (see "Installing a Patch," next) should call the object's initialization method (
InitClassName
). For example, if you are replacing the drag-and-drop object, you would call your replacement object'sInitDragAndDrop
method immediately after callingnew
to create it.Your replacement object's initialization method should call the
GetClassName
method of the session object to get a reference to the current object and then store that reference in a field. For the drag-and-drop example, yourInitDragAndDrop
method would call the session object'sGetDragAndDrop
method and store the returned reference in a field such asfOldDragAndDrop
.At the end of initialization, your
InitClassName
method should assign the replacement object as the current object. It should call theSetClassName
method of the session object and pass itself (somSelf
) as the new object reference. For example, if you were replacing the drag-and-drop object, you would make this call:
theSession->SetDragAndDrop(ev, somSelf);Your destructor method (somUninit
) should delete the patched-out object (the one referenced in thefOldDragAndDrop
field, for example) before calling the inheritedsomUninit
.If the object you are replacing has additional entry points besides those based on the session object's reference to it, you need to patch those also. For example, on the Mac OS platform the drag-and-drop object registers callbacks with the Mac OS Drag Manager; your replacement object would have to reregister those callbacks to point to itself.
Installing a Patch
Once you have written your patch, you need to install it so that OpenDoc uses it in place of the original object. Depending on what your patching needs are, you can place your patch installer in either of two places.
When called, your installer instantiates and initializes the patch object.
- If the scope of your patch needs to be global (applied to all OpenDoc documents), make your patch installer a shell plug-in (see "Shell Plug-Ins"). Install the patch within your plug-in's
Install
function.- If the scope of your patch is confined to the document containing your part, you can use your part editor's
Open
method to install the patch. Only the root part of a document can install an OpenDoc patch.
Potential Patch Conflicts
Every time it opens a document, the document shell installs, in order, all shell plug-ins, and then the root part opens its window. This installation sequence can lead to patching conflicts. Because you do not control the order in which shell plug-ins are installed, you cannot ensure that your patch will not itself be patched out by a subsequently installed patch.You can minimize the potential for conflicts by writing your patch correctly. Properly written patch objects always delegate everything but their specific functionality to the object that was previously in place. Consistently following this convention ensures the proper chaining of patch functionality.
Ultimately, the root part controls which patches remain, because it has the final opportunity to install its own patches.
[11] The document shell's semantic interface
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help