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:
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.
To help build a dynamic verb menu, the OleClient class provides these instance methods:
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.
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.