AspectAdaptor.st
changeset 69 225a9efd50f5
child 71 5b34cd877517
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AspectAdaptor.st	Tue May 09 02:23:22 1995 +0200
@@ -0,0 +1,205 @@
+ProtocolAdaptor subclass:#AspectAdaptor 
+	 instanceVariableNames:'myAspect getMsg putMsg'
+	 classVariableNames:''
+	 poolDictionaries:''
+	 category:'Interface-Support'
+!
+
+!AspectAdaptor 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/AspectAdaptor.st,v 1.1 1995-05-09 00:20:52 claus Exp $
+"
+!
+
+documentation
+"
+    an AspectAdaptor forwards updates and change messages
+    from/to a complex model.
+
+    Consider the case where editFields are required for the
+    elements (instance variables) of a more complex model.
+    Without an aspect adaptor, you needed to copy the individual
+    values out-of and into multiple valueHolders.
+    An aspectAdaptor makes this easier, by playing model with
+    vale/value: symbols towards the editField, and forwarding changes and
+    updates to/from the complex model using different aspect symbols.
+
+    Notice: this class was implemented using protocol information
+    from alpha testers and PD code - 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 dialog on a points x/y coordinates:
+
+	|dialog data f|
+
+	data := 0@0.
+
+	dialog := DialogBox new.
+	dialog addTextLabel:'x:'.
+	f := dialog addInputFieldOn:(AspectAdaptor new
+					subject:data; 
+					accessWith:#x 
+					assignWith:#x:).
+	f converter:(PrintConverter new initForNumber).
+
+	dialog addTextLabel:'y:'.
+	f := dialog addInputFieldOn:(AspectAdaptor new
+					subject:data; 
+					forAspect:#y).
+	f converter:(PrintConverter new initForNumber).
+
+	dialog addOkButton.
+	data inspect.
+	dialog open.
+
+	dialog accepted ifTrue:[
+	    Transcript showCr:'data now: ' , data printString
+	]
+
+
+    a dialog on a four-field complex model:
+
+
+	|dialog data dataModel|
+
+	data := #('hello' 'one' 'two' 'three').
+	dataModel := Plug new.
+	dataModel respondTo:#field1 with:[data at:1].
+	dataModel respondTo:#field2 with:[data at:2].
+	dataModel respondTo:#field3 with:[data at:3].
+	dataModel respondTo:#field4 with:[data at:4].
+	dataModel respondTo:#field1: with:[:arg | data at:1 put:arg].
+	dataModel respondTo:#field2: with:[:arg | data at:2 put:arg].
+	dataModel respondTo:#field3: with:[:arg | data at:3 put:arg].
+	dataModel respondTo:#field4: with:[:arg | data at:4 put:arg].
+
+	dialog := DialogBox new.
+	dialog addTextLabel:'1:'.
+	dialog addInputFieldOn:(AspectAdaptor new
+					subject:dataModel; 
+					accessWith:#field1
+					assignWith:#field1:). 
+	dialog addTextLabel:'2:'.
+	dialog addInputFieldOn:(AspectAdaptor new
+					subject:dataModel; 
+					forAspect:#field2).
+	dialog addTextLabel:'3:'.
+	dialog addInputFieldOn:(AspectAdaptor new
+					subject:dataModel; 
+					accessWith:#field3
+					assignWith:#field3:
+					aspect:#field3). 
+	dialog addTextLabel:'4:'.
+	dialog addInputFieldOn:(AspectAdaptor new
+					subject:dataModel; 
+					forAspect:#field4).
+	dialog addOkButton.
+	dataModel inspect.
+	dialog open.
+	dialog accepted ifTrue:[
+	    Transcript showCr:'data now: ' , data printString
+	]
+"
+! !
+
+!AspectAdaptor class methodsFor:'instance creation'!
+
+accessWith:getSelector assignWith:putSelector 
+    ^ (self new) accessWith:getSelector assignWith:putSelector
+! !
+
+!AspectAdaptor methodsFor:'change & update'!
+
+update:something with:aParameter from:changedObject
+    "translate an update from the model into a #value-change
+     via my depenedents ..."
+
+    ((changedObject == subject)
+    or:[changedObject == subjectChannel]) ifTrue:[
+	something == self forAspect ifTrue:[
+	    self changed:#value
+	].
+	^ self
+    ].
+! !
+
+!AspectAdaptor methodsFor:'accessing-value'!
+
+value
+    "translate a query for my value from my user
+     into an aspect access towards my subject"
+
+    |target|
+
+    target := super value.
+    ^ target perform:getMsg
+!
+
+setValue:newValue
+    |target oldValue|
+
+    target := super value.
+    oldValue := target perform:getMsg.
+    oldValue ~~ newValue ifTrue:[
+	target perform:putMsg with:newValue.
+    ]
+!
+
+value:newValue
+    |target oldValue|
+
+    target := super value.
+    oldValue := target perform:getMsg.
+    oldValue ~~ newValue ifTrue:[
+	target perform:putMsg with:newValue.
+	subjectSendsUpdates ifFalse:[
+	    self changed:#value
+	]
+    ]
+! !
+        
+!AspectAdaptor methodsFor:'accessing-spec'!
+
+forAspect
+    myAspect isNil ifTrue:[
+	^ getMsg
+    ].
+    ^ myAspect
+!
+
+forAspect:aSelector
+    getMsg := myAspect := aSelector.
+    putMsg := (aSelector , ':') asSymbol.
+!
+
+accessWith:getSelector assignWith:putSelector
+    getMsg := getSelector.
+    putMsg := putSelector
+!
+
+accessWith:getSelector assignWith:putSelector aspect:aspectSymbol
+    getMsg := getSelector.
+    putMsg := putSelector.
+    myAspect := aspectSymbol
+! !