'From Squeak3.3alpha of 12 January 2002 [latest update: #4761] on 17 February 2002 at 5:45:53 am'! "Change Set: buttonWithArg Date: 17 February 2002 Author: stephane ducasse, masato sumi, scott wallace Makes it possible for pluggableButtonMorphs and pluggableButtonViews to pass arguments with the message sent when the button is pressed. The button can be set up to obtain arguments just-in-time by giving it an argumentSelector and an argumentProvider. For example in the RegisteringFileList, the fileList needs to call FileStream with #fileIn: and passing as argument the currently selected file"! AlignmentMorph subclass: #PluggableButtonMorph instanceVariableNames: 'model label getStateSelector actionSelector getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging triggerOnMouseDown offColor onColor feedbackColor showSelectionFeedback allButtons argumentsSelector argumentsProvider arguments ' classVariableNames: '' module: #(Squeak Morphic Library Windows)! !PluggableButtonMorph commentStamp: 'sw 2/18/2002 00:29' prior: 0! A PluggableButtonMorph is a combination of an indicator for a boolean value stored in its model and an action button. The action of a button is often, but not always, to toggle the boolean value that it shows. Its pluggable selectors are: getStateSelector fetch a boolean value from the model actionSelector invoke this button's action on the model getLabelSelector fetch this button's lable from the model getMenuSelector fetch a pop-up menu for this button from the model Any of the above selectors can be nil, meaning that the model does not supply behavior for the given action, and the default behavior should be used. For example, if getStateSelector is nil, then this button shows the state of a read-only boolean that is always false. The model informs its view(s) of changes by sending #changed: to itself with getStateSelector as a parameter. The view tells the model when the button is pressed by sending actionSelector. If the actionSelector takes one or more arguments, then the following are relevant: arguments A list of arguments to provide when the actionSelector is called. argumentsProvider The object that is sent the argumentSelector to obtain arguments, if dynamic argumentsSelector The message sent to the argumentProvider to obtain the arguments. Options: askBeforeChanging have model ask user before allowing a change that could lose edits triggerOnMouseDown do this button's action on mouse down (vs. up) transition shortcutCharacter a place to record an optional shortcut key ! View subclass: #PluggableButtonView instanceVariableNames: 'label getStateSelector actionSelector getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging triggerOnMouseDown complemented argumentProvider argumentSelector argumentsProvider argumentsSelector ' classVariableNames: '' module: #(Squeak MVC PluggableViews)! !PluggableButtonMorph methodsFor: 'initialize-release' stamp: 'sw 2/17/2002 00:44'! initialize super initialize. self listDirection: #topToBottom. self hResizing: #shrinkWrap. "<--so naked buttons work right" self vResizing: #shrinkWrap. self wrapCentering: #center; cellPositioning: #topCenter. borderWidth _ 1. model _ nil. label _ nil. getStateSelector _ nil. actionSelector _ nil. getLabelSelector _ nil. getMenuSelector _ nil. shortcutCharacter _ nil. askBeforeChanging _ false. triggerOnMouseDown _ false. color _ Color lightGreen. onColor _ color darker. offColor _ color. feedbackColor _ Color red. showSelectionFeedback _ false. allButtons _ nil. argumentsProvider _ nil. argumentsSelector _ nil. self extent: 20@15. ! ! !PluggableButtonMorph methodsFor: 'arguments' stamp: 'sw 2/17/2002 01:03'! arguments: args "If the receiver takes argument(s) that are static, they can be filled by calling this. If its argument(s) are to be dynamically determined, then use an argumentProvider and argumentSelector instead" arguments _ args! ! !PluggableButtonMorph methodsFor: 'arguments' stamp: 'sw 2/17/2002 05:29'! argumentsProvider: anObject argumentsSelector: aSelector "Set the argument provider and selector" argumentsProvider _ anObject. argumentsSelector _ aSelector! ! !PluggableButtonMorph methodsFor: 'accessing' stamp: 'sw 2/17/2002 05:29'! performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed. If the button's actionSelector takes any arguments, they are obtained dynamically by sending the argumentSelector to the argumentsProvider" askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]]. actionSelector ifNotNil: [actionSelector numArgs == 0 ifTrue: [model perform: actionSelector] ifFalse: [argumentsProvider ifNotNil: [arguments _ argumentsProvider perform: argumentsSelector]. model perform: actionSelector withArguments: arguments]]! ! !PluggableButtonMorph methodsFor: 'copying' stamp: 'sw 2/17/2002 05:29'! veryDeepInner: deepCopier "Copy all of my instance variables. Some need to be not copied at all, but shared. Warning!!!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment." super veryDeepInner: deepCopier. "model _ model. Weakly copied" label _ label veryDeepCopyWith: deepCopier. "getStateSelector _ getStateSelector. a Symbol" "actionSelector _ actionSelector. a Symbol" "getLabelSelector _ getLabelSelector. a Symbol" "getMenuSelector _ getMenuSelector. a Symbol" shortcutCharacter _ shortcutCharacter veryDeepCopyWith: deepCopier. askBeforeChanging _ askBeforeChanging veryDeepCopyWith: deepCopier. triggerOnMouseDown _ triggerOnMouseDown veryDeepCopyWith: deepCopier. offColor _ offColor veryDeepCopyWith: deepCopier. onColor _ onColor veryDeepCopyWith: deepCopier. feedbackColor _ feedbackColor veryDeepCopyWith: deepCopier. showSelectionFeedback _ showSelectionFeedback veryDeepCopyWith: deepCopier. allButtons _ nil. "a cache" arguments _ arguments veryDeepCopyWith: deepCopier. argumentsProvider _ argumentsProvider veryDeepCopyWith: deepCopier. argumentsSelector _ argumentsSelector. " a Symbol" ! ! !PluggableButtonView methodsFor: 'initialize-release' stamp: 'sw 2/17/2002 05:32'! on: anObject getState: getStateSel action: actionSel getArguments: getArgumentsSel from: argsProvidor label: labelSel menu: menuSel self initialize. self model: anObject. getStateSelector _ getStateSel. actionSelector _ actionSel. argumentsSelector _ getArgumentsSel. argumentsProvider _ argsProvidor. getLabelSelector _ labelSel. getMenuSelector _ menuSel! ! !PluggableButtonView methodsFor: 'other' stamp: 'sw 2/17/2002 05:32'! performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed." argumentsSelector ifNil: [actionSelector ifNotNil: [model perform: actionSelector]] ifNotNil: [model perform: actionSelector withArguments: (Array with: (argumentsProvider perform: argumentsSelector))]! ! !PluggableButtonView class methodsFor: 'instance creation' stamp: 'sumim 2/15/2002 17:18'! on: anObject getState: getStateSel action: actionSel getArguments: getArgumentsSel from: argsProvidor ^ self new on: anObject getState: getStateSel action: actionSel getArguments: getArgumentsSel from: argsProvidor label: nil menu: nil! ! View subclass: #PluggableButtonView instanceVariableNames: 'label getStateSelector actionSelector getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging triggerOnMouseDown complemented argumentsProvider argumentsSelector ' classVariableNames: '' module: #(Squeak MVC PluggableViews)! PluggableButtonMorph removeSelector: #argsGettingBlock! PluggableButtonMorph removeSelector: #argsGettingBlock:! PluggableButtonMorph removeSelector: #argumentProvider:argumentSelector:! AlignmentMorph subclass: #PluggableButtonMorph instanceVariableNames: 'model label getStateSelector actionSelector getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging triggerOnMouseDown offColor onColor feedbackColor showSelectionFeedback allButtons arguments argumentsProvider argumentsSelector ' classVariableNames: '' module: #(Squeak Morphic Library Windows)! !PluggableButtonMorph reorganize! ('initialize-release' initialize on:getState:action:label:menu:) ('arguments' arguments: argumentsProvider:argumentsSelector:) ('accessing' action: actionSelector askBeforeChanging askBeforeChanging: feedbackColor: label label: label:font: model: offColor offColor: onColor:offColor: performAction shortcutCharacter shortcutCharacter: triggerOnMouseDown triggerOnMouseDown:) ('drawing' drawOn:) ('events' handlesMouseDown: mouseDown: mouseMove: mouseUp: updateFeedbackForEvt:) ('updating' update:) ('private' getMenu: getModelState invokeMenu:) ('copying' veryDeepFixupWith: veryDeepInner:) !