A user typically accesses an object by opening a view of that object. For example, to access the contents of a folder object, the user opens the default view (usually an icon view) of the folder, which then displays its contents. This is certainly true for container objects such as folders, and for the password-protected folder class used as an example in this chapter, although other "device" objects such as printers or the shredder may be used without a view.
When no view of an object is open, and the folder within which the object resides is not open, the object is said to be dormant; typically, no system resources are allocated to the object and its instance data is in an unknown state. Opening and closing views of an object therefore involve not only the opening and closing of windows, but also allocating and freeing resources, and saving and restoring the instance data of the object. Similarly, opening a folder requires saving and restoring the instance data of the objects in that folder.
Opening an Object
As mentioned above, a user typically interacts with an object using a view of that object. An object may support various types of view; for example, the WPFolder object class supports icon, tree, details and settings views. By default, an object class supports the view types defined by its ancestors, and a programmer may also define new view types for the object class.
When a view of an object is opened, a method named _wpOpen is invoked by the Workplace Shell. This method is defined and implemented by the base storage class WPObject, and may be overridden by a new object class to perform its own class-specific processing. The supported views for each object class are implemented as part of the _wpOpen method, using Presentation Manager windows.
When a view is opened by the user from a context menu, the _wpMenuItemSelected method is invoked (see Methods (Attaching a Method to the Context Menu) for more detailed discussion of this method). The _wpMenuItemSelected method typically invokes the _wpOpen method, and passes the identifier of the requested view as the third parameter. The _wpOpen method may then interrogate this parameter to decide which view to open.
When the user opens a view by double-clicking the mouse on an object's icon, the system invokes the _wpOpen method and passes an OPEN_DEFAULT value. The default processing for the _wpOpen method invokes the _wpQueryDefaultView method to determine the default view for the object, and immediately invokes the _wpOpen method a second time with the identifier for that view.
An example of an overridden _wpOpen method is given in Figure "Opening an Object". This example shows a password-protection facility being added to a folder to prevent access by unauthorized users. Upon invocation of the _wpOpen method, the password-protected folder object class displays a dialog box to accept a password from the user. It then compares that password with the correct password for that folder before actually opening the folder. Visual cues such as the folder's icon and the word "Locked" on the folder's title are modified or removed during the _wpOpen processing.
Since the view being opened in this case is the icon view defined by the WPFolder class, the actual opening of the view and presentation of the folder's contents is handled using the default processing supplied by the parent class, which is called after the class-specific processing has completed.
If an object class wishes to create a new view, it must add the name of the view to the Open submenu in the object's context menu, and include a case for that view in the _wpMenuItemSelected method. This method then invokes _wpOpen with a specific value in the ulView parameter, indicating the view to be opened. The class-specific processing for _wpOpen must test for this value, open a window and display the correct information using Presentation Manager functions.
The example in Figure "Opening an Object" does not include the code to set the folder's icon to the "unlocked" state. This code is identical to the code used in Figure "Adding a New Method" to set the icon to the "locked" state; the resource identifier of the "unlocked" icon is simply substituted in the _wpOpen method for the identifier of the "locked" icon.
Note that in many cases, it is important for an object class to allow the default processing for _wpOpen to occur before it attempts to carry out its own processing. This allows instance data and control information to be established and initialized before the object attempts any processing using these items. In Figure "Opening an Object" however, the additional class-specific processing determines whether the object should open at all; if processing is allowed to proceed, no alteration to the default processing takes place. The default processing may therefore be carried out after the additional class-specific processing introduced by the password-protected folder class.
The default processing for the _wpOpen method supports a number of views, depending upon the parent class of the object; for example, the processing for the WPFolder class supports ICON, TREE and DETAILS views. For new object classes which support additional views, the _wpOpen method must be overridden and the additional view types opened explicitly as windows using appropriate Presentation Manager functions. Since a view of an object is essentially a window, new views can be implemented as normal Presentation Manager windows and the correct information displayed using text or graphical programming functions, according to the requirements of the object class.
Note that upon opening a view using a Presentation Manager window, an object should add itself to the "Use List" maintained by the Workplace Shell. If the view is the first view of the object to be opened, this causes the Workplace Shell to modify the object's icon to indicate the "in use" state. The object should also register the view with the Workplace Shell, which will then subclass the view's frame window, automatically attach the object's context menu to the window's system menu icon, and add the view to the Workplace Shell's Window List. These steps are done using the _wpAddToObjUseList and _wpRegisterView methods, as shown in Figure "Opening a Custom View of an Object".
The Workplace Shell makes use of a USEITEM and a VIEWITEM structure in the _wpAddToObjUseList method. It assumes that these structures are contiguous in memory; hence they should be allocated as part of a larger data structure such as the OBJECTVIEW structure shown in Figure "Opening a Custom View of an Object". A pointer to this structure is stored in the window words of the view window, so that information such as the object's pointer can be accessed from the view's window procedure.
Note that upon closing a view, the view's window procedure should invoke the _wpDeleteFromObjUseList method to remove the view from the Use List. If the view is the only open view of the object, the object's icon is modified to remove the "in use" emphasis.
Automatic Opening Upon Instantiation
In many cases, it is desirable to automatically open a view of an object when the object is created. This may be achieved by using the OPEN= keyword in the setup string passed to the WinCreateObject() function. An example of this technique is shown in Figure "Automatically Instantiating an Object".
The opening of the view specified in the OPEN= keyword is handled by the default processing for the _wpSetup method, as defined by the WPObject class. The default processing supports the icon, tree and details views, specified using the ICON, TREE and DETAILS values for the OPEN= keyword respectively. For new object classes that support additional views, the _wpSetup method must be overridden and the additional view types opened explicitly as windows using appropriate Presentation Manager functions.
Closing an Object
When all open views of an object are to be closed, the _wpClose method is invoked. This method is normally invoked when the user selects the Close option from a view's context menu.
The _wpClose method may be overridden to perform class-specific processing for closing views, or to free system resources allocated during processing of the _wpOpen method. For example, Figure "Closing an Object" shows the _wpClose method being overridden to automatically lock a password-protected folder whenever it is closed by the user.
When a view of an object is closed, the system sends a WM_DESTROY message to the view's frame window. This allows the object to release any allocated resources and save its instance data, so that the object may be reopened in its current state at some future time.
Note that since the _wpClose method is defined by the parent class and is overridden, the default processing performed by the parent is called after the class-specific processing has completed.
Saving and Restoring the Object State
As already mentioned, an object is persistent; that is, it remains in existence even when all views of the object are closed. In order to maintain its instance data so that it may subsequently be opened in the same state in which it was closed, the object must save this data when its views are closed and restore it when a view is opened. The Workplace Shell provides methods that handle the saving and restoration of instance data on behalf of object classes; these methods are automatically invoked by the system at the appropriate times, and are described below.
When an object is made dormant, the system invokes the object's _wpSaveState method, which allows the object to save its instance data. A number of predefined methods are available to the object to save its data, such as _wpSaveString. These methods may be called by the object during the processing of its _wpSaveState method, in order to save instance data. An example of the _wpSaveState method for the password-protected folder example is given in Figure "Saving an Object's State".
An object's instance data items are saved in different locations, depending upon the class of the object. Object classes that are descendants of the WPAbstract class store their instance data in the OS/2 initialization file OS2.INI. Object classes that are descendants of the WPFileSystem class store their instance data in extended attributes. Since the password-protected folder class is descended from the WPFolder class defined by the Workplace Shell, which in turn is a descendant of the WPFileSystem class, the instance data of this object class is saved as extended attributes in the OS/2 file system.
The class-defined key passed to the _wpSaveString method is used to save the data item in a particular location, which can then be accessed, using the same key, to restore the item. In addition to strings, numeric data may be saved using the _wpSaveLong method, and other binary data such as application-defined data structures may be saved using the _wpSaveData method.
Note that since the _wpSaveState method is defined by the object's class's ancestors and overridden, it must invoke the default processing supplied by the parent class in order to correctly save any instance data defined by ancestor classes. Failure to do so may cause unpredictable results upon awakening the object from its dormant state.
An object must retrieve its instance data and restore its state whenever it is made awake. At this point, the system invokes an object's _wpRestoreState method, which allows the object to restore its state. During the processing of this method, the object can invoke other methods such as _wpRestoreString, which restore specific instance data items. An example of the _wpRestoreState method is given in Figure "Restoring an Object's State".
The class-defined key passed to the _wpRestoreString method is used to locate the required data item, and the item is restored into the specified target string variable. Numeric data can be restored using the _wpRestoreLong method, and other binary data such as application-defined structures can be restored using the _wpRestoreData method.
Since the _wpRestoreState method is an overridden method, it is important that the default processing supplied by the parent class be invoked. Failure to do so will result in any instance data defined by ancestor classes being in an unknown state, with unpredictable results.