Initialization
The first responsibility of a part editor is initialization. When the user launches a document, either preexisting or newly created from stationery, OpenDoc instantiates the part object belonging to each currently visible part in the document. In SamplePart, the part object is an instance of thesom_SamplePart
class, which is a subclass ofODPart
. At that time, the SOM runtime system calls the part object'ssomInit
method.The
SamplePart
object'ssomInit
method, belonging tosom_SamplePart
, does nothing. The SOM runtime system automatically calls the inheritedsomInit
methods, in the manner of a C++ constructor. SOM automatically zeroes the instance variables of a newly constructed SOM object, so there is no need to do so in thesomInit
method.Next, OpenDoc calls one of the part object's initialization methods. If the part is creating stationery, OpenDoc calls the
InitPart
method of the part object; if the part was previously created, either as the root part or embedded in a document, OpenDoc calls the part'sInitPartFromStorage
method. In SamplePart, these methods instantiate theSamplePart
C++ class, call their inherited methods, and call theSamplePart
object's methods of the same name. When theSamplePart
class is instantiated, the C++ runtime system calls its constructor, which does set instance variables to zero, as shown in Listing 2-3.In SamplePart, initialization code resides in four methods: the
SamplePart
constructor, theInitPart
method, theInitPartFromStorage
method, and the internalInitialize
method. TheInitialize
method contains the code that is common to both initialization situations: initializing a part when creating stationery (when OpenDoc callsInitPart
) and initializing a part previously created and written to persistent storage (when OpenDoc callsInitPartFromStorage
). Both of those methods callInitialize
. The following sections discuss the implementation of these methods.The Constructor
In SamplePart, the constructor performs only one action: it sets initial values for theSamplePart
object's private data fields. You should not do anything in the constructor that can fail, such as allocating memory. TheSOM_Trace
macro call indicates the name of the method currently executing for debugging purposes.Listing 2-3 shows the
SamplePart
object's constructor.Listing 2-3
SamplePart
constructor
SamplePart::SamplePart() { SOM_Trace("SamplePart","Constructor"); fDisplayFrames = kODNULL; fDirty = kODFalse; fSelf = kODNULL; fReadOnlyStorage = kODFalse; }The InitPart Method
If the part has no stored data, OpenDoc calls theInitPart
method after it instantiates the part object. Every part must implement this method. You can do things that might fail in this method, such as allocating extra storage, setting up your storage unit, and getting resources if you need them.As with all methods in SamplePart, the implementation is delegated. That is, OpenDoc calls the
InitPart
method belonging to theODPart
subclass, which in turn calls theInitPart
method of theSamplePart
object, which contains the method's implementation. For more information, refer to "SamplePart System Object Model Interface".The implementation of the
InitPart
method is contained within an exception handler, a block of code delimited by the macro callsTRY
andENDTRY
. When the body of the method executes, the statements following theTRY
macro execute; if any of them causes an exception to be thrown, the statements following theCATCH_ALL
macro execute. TheRERAISE
macro causes the exception to be thrown again to the caller ofInitPart
. If no exception is thrown, control passes to the statement following theENDTRY
macro call (the end of the method body in this case). For more information about the OpenDoc exception-handling utility, see Appendix A, "OpenDoc Utilities."The
SamplePart
implementation of theInitPart
method performs the following actions:
If any of the called methods throws an exception, the
- Initializes the part-wrapper field.
OpenDoc passes a pointer to its internal representation for the part editor, its part wrapper, when it calls theInitPart
method, and theSamplePart
object stores the pointer in itsfSelf
data member.OpenDoc uses the part wrapper in place of a pointer to the actual part object to enable swapping part editors at runtime for part translation. Wherever OpenDoc requires a reference to the part editor, such as when registering for idle time, you must pass the part wrapper pointer, rather than passing
this
(from theSamplePart
C++ object) orsomSelf
(from thesom_SamplePart
object).
- Ensures that the part's destination storage is writable.
OpenDoc calls the method when a part is first instantiated, so we must be able to write part status and content information to its storage unit.
- Calls the common initialization code.
Initialization code common toInitPart
andInitPartFromStorage
resides in the internalInitialize
method. TheInitialize
method is described in "The Initialize Method".
- Sets the dirty flag.
Setting the dirty flag tokODTrue
enables SamplePart to write out its state and content information at the next opportunity.
CATCH_ALL
method puts the error code in SOM'sEnvironment
structure. Cleanup occurs in theSamplePart
destructor.Listing 2-4 shows the implementation of the
InitPart
method.
void SamplePart::InitPart( Environment*ev, ODStorageUnit*storageUnit, ODPart* partWrapper ) { SOM_Trace("SamplePart","InitPart"); TRY fSelf = partWrapper; fReadOnlyStorage = kODFalse; this->Initialize(ev); this->SetDirty(ev); CATCH_ALL RERAISE; ENDTRY }The InitPartFromStorage Method
If a part has previously been stored persistently, OpenDoc calls theInitPartFromStorage
method, instead ofInitPart
, after it instantiates the part object. This situation occurs when a document or stationery is opened or when the part is embedded and its containing part reads it into memory. So, every part must also implement this method, which should do many of the same things asInitPart
, but which must also handle reading content and status information from the storage unit into memory.The part must not alter its storage unit in this method; if it does so, the document's Save menu item becomes enabled without the user having changed the document.
The
SamplePart
object's implementation of theInitPartFromStorage
method performs the following actions:
Listing 2-5 shows the implementation of the
- Initializes the part-wrapper field.
The method puts the part-wrapper pointer passed in from OpenDoc into the privatefSelf
data member.
- Determines if the draft from which the part is being opened is read only.
If the draft permissions are read only, the part must not write any data back to its storage unit. The method sets the part's privatefReadOnlyStorage
Boolean flag accordingly, to be checked before writing data in theExternalize
method.
- Calls the common initialization code.
Initialization code common toInitPart
andInitPartFromStorage
resides in the internalInitialize
method. TheInitialize
method is described in "The Initialize Method".
- Reads the part's status information.
Because the part was previously written to its storage unit,InitPartFromStorage
reads in the part's status information by calling the internalInternalizeStateInfo
method, which is described in "The InternalizeStateInfo Method".
- Reads the part's content value from the storage unit.
In SamplePart, the internal method that would read in the part's content value,InternalizeContent
, does nothing, because SamplePart has no intrinsic content. A brief discussion of the method appears in "The InternalizeContent Method".
InitPartFromStorage
method.Listing 2-5
InitPartFromStorage
method
void SamplePart::InitPartFromStorage( Environment*ev, ODStorageUnit*storageUnit, ODPart* partWrapper ) { SOM_Trace("SamplePart","InitPartFromStorage"); TRY fSelf = partWrapper; fReadOnlyStorage = ( ODGetDraft(ev,storageUnit)-> GetPermissions(ev) < kODDPSharedWrite ); this->Initialize(ev); this->InternalizeStateInfo(ev, storageUnit); this->InternalizeContent(ev, storageUnit); CATCH_ALL RERAISE; ENDTRY }The Initialize Method
TheInitialize
method is internal to theSamplePart
class. OpenDoc doesn't callInitialize
; bothInitPart
andInitPartFromStorage
call it. TheInitialize
method contains the initialization code that is common to both situations, whether the part is newly created or is to be read in from persistent storage.The
Initialize
method performs the following actions:
The final logic of the
- Creates a frame list collection object.
The frame list collection object (CList
) is necessary to keep track of the multiple display frames in which the part displays its content. The class is defined in the SamplePart utilities file SampleCollections.h.
- Checks the usage count of the SamplePart global variables.
If the usage count is not equal to zero, another instance of this part object is running. In that case, the following initialization steps have already been done and can be skipped. Otherwise, the method performs the following steps and sets the global variables usage count to 1.
- Stores a reference to the OpenDoc session object.
This is a convenience, because the session object provides access to session-wide global objects and services such as the window-state object and unique name tokenization. Note that the self-reference passed with theODGetSession
call is the part-wrapper object passed in by OpenDoc toInitPart
orInitPartFromStorage
.
- Creates the global variables structure.
The global variables structure is described in "Shared Global Variables".
- Instantiates the part's menu bar.
The part editor instantiates its menu bar by copying OpenDoc's session-wide menu bar, a base menu bar object maintained by the window-state object. That action maintains consistency in the arrangement of default menu items. Also, because its menu bar is a copy, this part editor can add and subtract menus and items without affecting the menu bars of other parts.Note that the menu bar object is shared among all the currently running instances of
SamplePart
in this document by virtue of its declaration in the shared global variables structure shown in Listing 2-2.
- Tokenizes and stores values for the foci the part needs.
The tokens are used for equivalence tests in the part activation methods and for requesting foci from the arbitrator. The method also packages into a set the three user-interface foci required by the part editor when it is activated, so it can request them all at once. The tokenized foci values are stored in the part's global variables.
- Tokenizes view types and presentation type.
The method tokenizes the four view types that all part editors must support and the part editor's main presentation type. The method tokenizes these strings for convenience, because tokens are faster to handle than strings.
- Determines the script and language to which the part is localized.
TheGetEditorScriptLanguage
utility function is defined in the SamplePart utilities file SamplePartUtils.cpp.
Initialize
method manages SamplePart's global variables usage count, which was mentioned in step 2. If the globals usage count was not equal to zero at that step, then another instance of the part is already running, and this instance can use the same tokens, focus set, and menu bar object. In that case, the method merely increments the global variables usage count.Listing 2-6 shows the implementation of the
Initialize
method.
void SamplePart::Initialize( Environment* ev ) { SOM_Trace("SamplePart","Initialize"); fDisplayFrames = new CList; if ( gGlobalsUsageCount == 0 ) { ODSession* session = ODGetSession(ev,fSelf); gGlobals = new SamplePartGlobals; gGlobals->fMenuBar = session->GetWindowState(ev)->CopyBaseMenuBar(ev); gGlobals->fSelectionFocus = session->Tokenize(ev, kODSelectionFocus); gGlobals->fMenuFocus = session->Tokenize(ev, kODMenuFocus); gGlobals->fModalFocus = session->Tokenize(ev, kODModalFocus); gGlobals->fMainPresentation = session->Tokenize(ev, kMainPresentation); gGlobals->fFrameView = session->Tokenize(ev, kODViewAsFrame); gGlobals->fLargeIconView = session->Tokenize(ev, kODViewAsLargeIcon); gGlobals->fSmallIconView = session->Tokenize(ev, kODViewAsSmallIcon); gGlobals->fThumbnailView = session->Tokenize(ev, kODViewAsThumbnail); gGlobals->fUIFocusSet = session->GetArbitrator(ev)->CreateFocusSet(ev); gGlobals->fUIFocusSet->Add(ev, gGlobals->fMenuFocus); gGlobals->fUIFocusSet->Add(ev, gGlobals->fSelectionFocus); GetEditorScriptLanguage(ev, &gGlobals->fEditorsScript, &gGlobals->fEditorsLanguage); gGlobalsUsageCount = 1; } else { gGlobalsUsageCount++; } }After these initialization methods have executed, the SamplePart part editor is in a consistent state, ready to become active.
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help