Programmer's Reference

Creating an object verb menu

Verbs are actions that a container can ask an OLE object to perform. The names of the verbs that an OLE object can execute are registered with the object in the system registry. All OLE objects have one verb designated as the primary verb, which in most cases is Edit. Other common verbs are Open, Show, Hide, and Play.

When an OLE object is activated in its container by double-clicking on the OleClient widget, it is the primary verb that is invoked on the OLE object. Therefore, if the Edit verb is the primary verb, on activation, the server opens for editing on the OLE object. Verbs can also be invoked programmatically through the doVerb: method of OleClient. The parameter to this method is the name of the verb to execute. For example, a contained OLE object can be activated for editing using anOleClient doVerb: 'Edit'.

The doVerb: method can also take as a parameter a constant representing the most common verbs that most OLE objects support. For example, the edit verb could also be invoked using anOleClient doVerb: XmVERBPRIMARY.

The standard parameter values for the OLE doVerb: include the following:

XmVERBPRIMARY
Open the OLE object for editing
XmVERBSHOW
Show the OLE object
XmVERBOPEN
Open the OLE object for editing in a separate window
XmVERBHIDE
Hide the OLE object
XmVERBUIACTIVATE
Activate the UI for the OLE object
XmVERBINPLACEACTIVATE
Open the OLE object for editing in place
XmVERBDISCARDUNDOSTATE
Close the OLE object and discard the undo state
XmVERBPROPERTIES
Request the OLE object properties dialog

The OLE user interface guidelines suggest that a container provide access to an object's verbs from a cascade menu off its Edit menu. The container must dynamically change the contents of the cascade menu depending on which OleClient widget has the current focus. The guidelines also suggest that the label of the cascade menu change to reflect the name of the object that the verbs apply to.
A typical OLE object verb menu

To help build a dynamic verb menu, the OleClient class provides these instance methods:

clientUserName
Answers a String representing the type of contained OLE object
verbs
Answers a collection of strings that are the names of the verbs supported by the contained OLE object

These methods provide sufficient information to build the dynamic verb menus of a container application. As an example, suppose the Edit menu of an application is created as a simple pull-down menu using the following code:

createEditMenu: menuBar
   "Private - Create and answer the Edit menu for the receiver."
   | types |
   types := OrderedCollection new.
   types
      add: XmPUSHBUTTON;
      add: XmPUSHBUTTON;
      add: XmPUSHBUTTON;
      add: XmPUSHBUTTON;
      add: XmPUSHBUTTON;
      add: XmSEPARATOR;
      add: XmPUSHBUTTON;
      add: XmPUSHBUTTON;
      add: XmCASCADEBUTTON.
 
   editMenu := menuBar
      createSimplePulldownMenu: 'edit'
      argBlock: [ :w |
         w
            buttons: #('Cut' 'Copy' 'Paste' 'Paste Special...'
              'Delete Object' '' 'Insert	Object...' 'Links...' 'Object');
            buttonType: types;
            buttonMnemonics: #();
            postFromButton: 1].
   editMenu
      addCallback: XmNsimpleCallback
      receiver: [:w :clientData :callData |
         | selectors |
         selectors := #(menuEditCut menuEditCopy menuEditPaste
         menuEditPasteSpecial menuEditDeleteObject menuEditInsertObject
         menuEditLinks menuEditObject).
         self perform: (selectors at: clientData + 1)]
      selector: #value:value:value:
      clientData: nil.
   editMenu
      addCallback: XmNmapCallback
      receiver: [:w :clientData :callData |
         | widget buttons |
         buttons := editMenu children.
         widget := self shell focusWidget.
        (buttons at: 1) sensitive: widget isOleClient.	"Cut"
        ...
        (buttons at: 9)
           sensitive: self enableVerbs.	"Object"]
      selector: #value:value:value:
      clientData: nil.
   ^editMenu

In this example, the last item on the menu is a cascade button that is used to attach the verb menu to. The verb menu must be disabled if no OleClient widget has focus. Hence, the XmNmapCallback callback calls the enableVerbs method to build the verb menu if appropriate. The enableVerbs method first checks for the existence of an OleClient with focus and, if it finds one, proceeds to build the verb menu:

enableVerbs
   "Private - Answer true if the selected embedded object's verbs 
    are to be enabled."
   | widget |
   widget := self shell focusWidget.
   "Widget with focus is the selected item."
   (widget isOleClient not or: [widget isStaticEmbedding])
      ifTrue: [
         (editMenu children at: 9) labelString: 'Object'.
         ^false].
   "An embedded or linked OLE object is selected, so add verb menu to edit menu."
   self addObjectMenu: widget clientUserName
      verbs: widget verbs.
   ^true

The cascading verb menu is built in the addObject:verbs: method as follows:

addObjectMenu: objectType verbs: verbNames
   "Private - Add an object menu for object with type name String
    objectType containing the verb names in the verbNames Array."
   | types labels verbCount objectMenu |
   labels := OrderedCollection new: (verbCount := verbNames size) + 2.
   types := OrderedCollection new: labels size.
   1 to: verbCount do: [ :i |
      labels add: (verbNames at: i).
      types add: XmPUSHBUTTON].
   labels add: 'separator'; add: 'Convert'.
   types add: XmSEPARATOR; add: XmPUSHBUTTON.
   (editMenu children at: 9) labelString: (objectType, ' Object').
 
   objectMenu := editMenu
      createSimplePulldownMenu: 'object'
      argBlock: [ :w |
         w
            buttons: labels asArray;
            buttonType: types asArray;
            postFromButton: 8].
   objectMenu
      addCallback: XmNsimpleCallback
      receiver: [:w :clientData :callData |
         | widget |
         widget := self shell focusWidget.
        (widget isOleClient and: [verbCount > 0])
           ifTrue: [clientData >= verbCount
              ifTrue: [self menuEditConvert]
           ifFalse: 
              [widget doVerb: (verbNames at: clientData + 1)]]]
      selector: #value:value:value:
      clientData: nil.

Notice in this example that one additional menu item, Convert, is attached to the bottom of the verb menu. This item provides access to the standard OLE Convert dialog, which allows you to change the display aspect of the OLE object from its content display to its icon display and conversely.
The standard OLE Convert Dialog

This dialog is easily invoked on an OleClient widget through its promptConvertObject method. For example:

menuEditConvert
   "Private - Process the Edit menu Convert item."
   | widget |
   (widget := self shell focusWidget) isOleClient
      ifFalse: [^self].
   widget promptConvertObject == true 
      ifTrue: [changed := true]

The promptConvertObject method answers true if the display aspect of the OLE object changed. If it did, the OleClient widget's display was already refreshed to reflect the new aspect.


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]