--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ProtocolAdaptor.st Tue May 09 02:23:22 1995 +0200
@@ -0,0 +1,282 @@
+'From Smalltalk/X, Version:2.10.5 on 9-may-1995 at 12:03:43 pm'!
+
+ValueModel subclass:#ProtocolAdaptor
+ instanceVariableNames:'accessPath subject subjectChannel subjectSendsUpdates'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Interface-Support'
+!
+
+!ProtocolAdaptor class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1995 by Claus Gittinger
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+version
+"
+$Header: /cvs/stx/stx/libview2/ProtocolAdaptor.st,v 1.1 1995-05-09 00:21:52 claus Exp $
+"
+!
+
+documentation
+"
+ a ProtocolAdaptor allows access to embeded values in a
+ complex model and plays model towards the outside world.
+
+ Consider the case where editFields are required for the
+ elements (instance variables) of a more complex model.
+ Using ValueHolders, you had to copy the individual
+ values out-of and into multiple valueHolders.
+ A protocolAdaptor makes this easier, by playing model towards
+ the editField, returning a value from the complex model,
+ and forwards changes to the complex model.
+
+ Notice: since you can specify the aspect- and changeSymbols in most ST/X
+ widgets, ProtocolAdapters are not always needed (at least, if no access-
+ path is required).
+ However, if you want to apply widgets on objects which where not originally
+ designed as models (such as Arrays), ProtocolAdapters are very useful.
+
+ Notice: this class was implemented using protocol information
+ from alpha testers - it may not be complete or compatible to
+ the corresponding ST-80 class. If you encounter any incompatibilities,
+ please forward a note to the ST/X team.
+"
+!
+
+examples
+"
+ |a obj|
+
+ a := ProtocolAdaptor accessPath:#(1 2 3).
+ obj := Array with:#(11 (121 122 123) 13)
+ with:#(21 (221 222 223) 23)
+ with:#(33 (321 322 323) 33).
+ a valueUsingSubject:obj
+
+
+
+ |a obj|
+
+ a := ProtocolAdaptor accessPath:#(1 2 origin).
+ obj := Array with:(Array with:1@1 with:(1@2 corner:100@100))
+ with:(Array with:2@1 with:2@2)
+ with:(Array with:3@1 with:3@2).
+ a valueUsingSubject:obj
+
+
+
+ |a model|
+
+ a := ProtocolAdaptor accessPath:#(1 2 origin).
+ model := (Array with:(Array with:1@1 with:(1@2 corner:100@100))
+ with:(Array with:2@1 with:2@2)
+ with:(Array with:3@1 with:3@2)) asValue.
+ a subjectChannel:model.
+ a value
+"
+! !
+
+!ProtocolAdaptor class methodsFor:'instance creation'!
+
+accessPath:aCollectionOfSelectors
+ ^ (self new) accessPath:aCollectionOfSelectors
+!
+
+subject:anObject
+ ^ (self new) subject:anObject
+!
+
+subject:anObject sendsUpdates:aBoolean
+ ^ (self new) subject:anObject; sendsUpdates:aBoolean
+!
+
+subject:anObject accessPath:aCollectionOfSelectors
+ ^ (self new) subject:anObject; accessPath:aCollectionOfSelectors
+!
+
+subject:anObject sendsUpdates:aBoolean accessPath:aCollectionOfSelectors
+ ^ (self new) subject:anObject; sendsUpdates:aBoolean; accessPath:aCollectionOfSelectors
+!
+
+subjectChannel:aValueHolder
+ ^ (self new) subjectChannel:aValueHolder
+!
+
+subjectChannel:aValueHolder sendsUpdates:aBoolean
+ ^ (self new) subjectChannel:aValueHolder; sendsUpdates:aBoolean
+!
+
+subjectChannel:aValueHolder accessPath:aCollectionOfSelectors
+ ^ (self new) subjectChannel:aValueHolder; accessPath:aCollectionOfSelectors
+!
+
+subjectChannel:aValueHolder sendsUpdates:aBoolean accessPath:aCollectionOfSelectors
+ ^ (self new) subjectChannel:aValueHolder; sendsUpdates:aBoolean; accessPath:aCollectionOfSelectors
+! !
+
+!ProtocolAdaptor methodsFor:'accessing'!
+
+setValue:newValue usingSubject:anObject
+ "set a value in anObject, using the selectors in accessPath.
+ A helper for setValue:."
+
+ |obj lastIndex|
+
+ obj := anObject.
+ lastIndex := accessPath size.
+ accessPath keysAndValuesDo:[:idx :aSelectorOrIndex |
+ aSelectorOrIndex isInteger ifTrue:[
+ idx == lastIndex ifTrue:[
+ obj at:aSelectorOrIndex put:newValue
+ ] ifFalse:[
+ obj := obj at:aSelectorOrIndex
+ ]
+ ] ifFalse:[
+ idx == lastIndex ifTrue:[
+ obj perform:(aSelectorOrIndex , ':') asSymbol with:newValue
+ ] ifFalse:[
+ obj := obj perform:aSelectorOrIndex
+ ]
+ ]
+ ].
+ ^ newValue
+!
+
+valueUsingSubject:anObject
+ "return the value from anObject, using the selectors in accessPath.
+ A helper for value."
+
+ |obj|
+
+ obj := anObject.
+ accessPath notNil ifTrue:[
+ accessPath do:[:aSelectorOrIndex |
+ aSelectorOrIndex isInteger ifTrue:[
+ obj := obj at:aSelectorOrIndex
+ ] ifFalse:[
+ obj := obj perform:aSelectorOrIndex
+ ]
+ ].
+ ].
+ ^ obj
+!
+
+value
+ "return the value from my subject or subjectChannel."
+
+ |obj|
+
+ subject notNil ifTrue:[
+ obj := subject.
+ ] ifFalse:[
+ obj := subjectChannel value
+ ].
+ ^ self valueUsingSubject:obj
+!
+
+setValue:newValue
+ "set the value in my subject or subjectChannel."
+
+ |obj|
+
+ subject notNil ifTrue:[
+ obj := subject.
+ ] ifFalse:[
+ obj := subjectChannel value
+ ].
+ ^ self setValue:newValue usingSubject:obj
+! !
+
+!ProtocolAdaptor methodsFor:'change notification'!
+
+notifyChange
+ subjectSendsUpdates ifFalse:[
+ super notifyChange:#value
+ ]
+! !
+
+!ProtocolAdaptor methodsFor:'initialization'!
+
+initialize
+ super initialize.
+ subjectSendsUpdates := false.
+! !
+
+!ProtocolAdaptor methodsFor:'change & update'!
+
+update:something with:aPArameter from:changedObject
+ "translate updates from my subject into value-changes towards
+ my dependents. Since I have no specific aspect, every change is forwarded"
+
+ (changedObject == subject
+ or:[changedObject == subjectChannel]) ifTrue:[
+ self changed:#value.
+ ^ self
+ ].
+! !
+
+!ProtocolAdaptor methodsFor:'accessing-spec'!
+
+subjectSendsUpdates
+ "return true, if the subject sends updates itself
+ If true, the receiver will not send updates on changes"
+
+ ^ subjectSendsUpdates
+!
+
+subjectSendsUpdates:aBoolean
+ "set/clear the flag which states if the subject sends updates itself.
+ If true, the receiver will not send updates on changes"
+
+ subjectSendsUpdates := aBoolean.
+!
+
+subjectChannel:aValueHolder
+ |oldChannel|
+
+ oldChannel := subjectChannel.
+ subjectChannel := aValueHolder.
+ oldChannel notNil ifTrue:[
+ self changed:#value.
+ ].
+!
+
+subjectChannel
+ ^ subjectChannel
+!
+
+subject:anObject
+ subject notNil ifTrue:[
+ subject removeDependent:self
+ ].
+ subject := anObject.
+ self changed:#value.
+ subject notNil ifTrue:[
+ subject addDependent:self
+ ].
+!
+
+subject
+ ^ subject
+!
+
+accessPath:aCollectionOfSelectors
+ accessPath := aCollectionOfSelectors
+!
+
+accessPath
+ ^ accessPath
+! !
+