author | sr |
Thu, 26 Nov 2015 17:20:45 +0100 | |
changeset 3527 | aa939bace1e9 |
parent 3300 | c8cd574b5966 |
child 3614 | 3272e655d847 |
permissions | -rw-r--r-- |
74 | 1 |
" |
2 |
COPYRIGHT (c) 1995 by Claus Gittinger |
|
3 |
All Rights Reserved |
|
4 |
||
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
2286 | 12 |
"{ Package: 'stx:libview2' }" |
74 | 13 |
|
125 | 14 |
ProtocolAdaptor subclass:#AspectAdaptor |
217 | 15 |
instanceVariableNames:'myAspect getMsg putMsg' |
16 |
classVariableNames:'' |
|
17 |
poolDictionaries:'' |
|
18 |
category:'Interface-Support-Models' |
|
69 | 19 |
! |
20 |
||
21 |
!AspectAdaptor class methodsFor:'documentation'! |
|
22 |
||
23 |
copyright |
|
24 |
" |
|
25 |
COPYRIGHT (c) 1995 by Claus Gittinger |
|
71 | 26 |
All Rights Reserved |
69 | 27 |
|
28 |
This software is furnished under a license and may be used |
|
29 |
only in accordance with the terms of that license and with the |
|
30 |
inclusion of the above copyright notice. This software may not |
|
31 |
be provided or otherwise made available to, or used by, any |
|
32 |
other person. No title to or ownership of the software is |
|
33 |
hereby transferred. |
|
34 |
" |
|
35 |
! |
|
36 |
||
37 |
documentation |
|
38 |
" |
|
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
39 |
an AspectAdaptor forwards updates and change messages from/to a complex model. |
69 | 40 |
|
41 |
Consider the case where editFields are required for the |
|
789 | 42 |
elements (instance variables) of a compound object: |
238 | 43 |
- without an aspect adaptor, you needed to copy the individual |
44 |
values out-of the object and move these into multiple valueHolders. |
|
45 |
Then, let the editFields modify the valueHolders contents and |
|
46 |
finally, fetch the values and put them back into the compound object. |
|
47 |
||
69 | 48 |
An aspectAdaptor makes this easier, by playing model with |
85 | 49 |
value/value: symbols towards the editField, and forwarding changes and |
789 | 50 |
updates to/from the compound object using different aspect symbols |
238 | 51 |
and access messages. |
69 | 52 |
|
231 | 53 |
Notice: |
54 |
this class was implemented using protocol information |
|
55 |
from alpha testers - it may not be complete or compatible to |
|
56 |
the corresponding ST-80 class. |
|
57 |
If you encounter any incompatibilities, please forward a note |
|
58 |
describing the incompatibility verbal (i.e. no code) to the ST/X team. |
|
217 | 59 |
|
223 | 60 |
[author:] |
61 |
Claus Gittinger |
|
62 |
||
217 | 63 |
[see also:] |
64 |
ValueHolder Model |
|
69 | 65 |
" |
66 |
! |
|
67 |
||
68 |
examples |
|
69 |
" |
|
70 |
a dialog on a points x/y coordinates: |
|
231 | 71 |
[exBegin] |
72 |
|dialog data f| |
|
69 | 73 |
|
231 | 74 |
data := 0@0. |
69 | 75 |
|
231 | 76 |
dialog := DialogBox new. |
77 |
dialog addTextLabel:'x:'. |
|
78 |
f := dialog addInputFieldOn:(AspectAdaptor new |
|
79 |
subject:data; |
|
80 |
accessWith:#x |
|
81 |
assignWith:#x:). |
|
82 |
f converter:(PrintConverter new initForNumber). |
|
69 | 83 |
|
231 | 84 |
dialog addTextLabel:'y:'. |
85 |
f := dialog addInputFieldOn:(AspectAdaptor new |
|
86 |
subject:data; |
|
87 |
forAspect:#y). |
|
88 |
f converter:(PrintConverter new initForNumber). |
|
69 | 89 |
|
231 | 90 |
dialog addOkButton. |
91 |
data inspect. |
|
92 |
dialog open. |
|
69 | 93 |
|
231 | 94 |
dialog accepted ifTrue:[ |
268 | 95 |
Transcript showCR:'data now: ' , data printString |
231 | 96 |
] |
97 |
[exEnd] |
|
69 | 98 |
|
99 |
||
100 |
a dialog on a four-field complex model: |
|
231 | 101 |
[exBegin] |
102 |
|dialog data dataModel| |
|
69 | 103 |
|
231 | 104 |
data := #('hello' 'one' 'two' 'three'). |
105 |
dataModel := Plug new. |
|
106 |
dataModel respondTo:#field1 with:[data at:1]. |
|
107 |
dataModel respondTo:#field2 with:[data at:2]. |
|
108 |
dataModel respondTo:#field3 with:[data at:3]. |
|
109 |
dataModel respondTo:#field4 with:[data at:4]. |
|
110 |
dataModel respondTo:#field1: with:[:arg | data at:1 put:arg]. |
|
111 |
dataModel respondTo:#field2: with:[:arg | data at:2 put:arg]. |
|
112 |
dataModel respondTo:#field3: with:[:arg | data at:3 put:arg]. |
|
113 |
dataModel respondTo:#field4: with:[:arg | data at:4 put:arg]. |
|
69 | 114 |
|
231 | 115 |
dialog := DialogBox new. |
116 |
dialog addTextLabel:'1:'. |
|
117 |
dialog addInputFieldOn:(AspectAdaptor new |
|
118 |
subject:dataModel; |
|
119 |
accessWith:#field1 |
|
120 |
assignWith:#field1:). |
|
121 |
dialog addTextLabel:'2:'. |
|
122 |
dialog addInputFieldOn:(AspectAdaptor new |
|
123 |
subject:dataModel; |
|
124 |
forAspect:#field2). |
|
125 |
dialog addTextLabel:'3:'. |
|
126 |
dialog addInputFieldOn:(AspectAdaptor new |
|
127 |
subject:dataModel; |
|
128 |
accessWith:#field3 |
|
129 |
assignWith:#field3: |
|
130 |
aspect:#field3). |
|
131 |
dialog addTextLabel:'4:'. |
|
132 |
dialog addInputFieldOn:(AspectAdaptor new |
|
133 |
subject:dataModel; |
|
134 |
forAspect:#field4). |
|
135 |
dialog addOkButton. |
|
136 |
dataModel inspect. |
|
137 |
dialog open. |
|
138 |
dialog accepted ifTrue:[ |
|
268 | 139 |
Transcript showCR:'data now: ' , data printString |
231 | 140 |
] |
141 |
[exEnd] |
|
69 | 142 |
" |
143 |
! ! |
|
144 |
||
145 |
!AspectAdaptor class methodsFor:'instance creation'! |
|
146 |
||
147 |
accessWith:getSelector assignWith:putSelector |
|
83 | 148 |
"create and return an adaptor which uses getSelector to fetch a value |
149 |
and setSelector to change it." |
|
150 |
||
69 | 151 |
^ (self new) accessWith:getSelector assignWith:putSelector |
85 | 152 |
! |
153 |
||
439 | 154 |
forAspect:anAspect |
155 |
"create and return a new adaptor, which forwards requests |
|
156 |
to anObject, using anAspect as get-selector and anAspect-colon as putSelector |
|
157 |
for access. The returned object can be used in place of a ValueHolder" |
|
158 |
||
159 |
^ self new forAspect:anAspect |
|
160 |
||
161 |
"Modified: 22.1.1997 / 12:00:42 / cg" |
|
162 |
! |
|
163 |
||
85 | 164 |
subject:anObject sendsUpdates:aBoolean accessWith:getSel assignWith:putSel aspect:aspect |
379 | 165 |
"create and return a new adaptor, which forwards requests |
166 |
to anObject, using getSel/putSel for access. |
|
167 |
The returned object can be used in place of a ValueHolder" |
|
168 |
||
85 | 169 |
^ (self subject:anObject sendsUpdates:aBoolean) |
379 | 170 |
accessWith:getSel assignWith:putSel aspect:aspect |
171 |
||
172 |
"Modified: 22.1.1997 / 12:00:42 / cg" |
|
69 | 173 |
! ! |
174 |
||
125 | 175 |
!AspectAdaptor methodsFor:'accessing-spec'! |
176 |
||
177 |
accessWith:getSelector assignWith:putSelector |
|
178 |
"setup the recevier to use getSelector to fetch a value |
|
381 | 179 |
and putSelector to change it." |
125 | 180 |
|
181 |
getMsg := getSelector. |
|
182 |
putMsg := putSelector |
|
381 | 183 |
|
184 |
"Modified: 22.1.1997 / 18:28:46 / cg" |
|
125 | 185 |
! |
186 |
||
187 |
accessWith:getSelector assignWith:putSelector aspect:aspectSymbol |
|
188 |
"setup the recevier to use getSelector to fetch a value |
|
381 | 189 |
and putSelector to change it." |
125 | 190 |
|
191 |
getMsg := getSelector. |
|
192 |
putMsg := putSelector. |
|
193 |
myAspect := aspectSymbol |
|
381 | 194 |
|
195 |
"Modified: 22.1.1997 / 18:28:51 / cg" |
|
125 | 196 |
! |
197 |
||
409 | 198 |
aspect:aSelector |
199 |
"set the adapters change aspect - this is the aspect of the update message, |
|
200 |
on which the adaptor reacts" |
|
201 |
||
202 |
myAspect := aSelector. |
|
203 |
! |
|
204 |
||
125 | 205 |
forAspect |
381 | 206 |
"get the adapters aspect - if none was defined, the getMsg is returned" |
207 |
||
125 | 208 |
myAspect isNil ifTrue:[ |
381 | 209 |
^ getMsg |
125 | 210 |
]. |
211 |
^ myAspect |
|
381 | 212 |
|
213 |
"Modified: 22.1.1997 / 18:27:24 / cg" |
|
125 | 214 |
! |
215 |
||
216 |
forAspect:aSelector |
|
381 | 217 |
"set the adapters aspect - this sets both the get- and put-Messages |
218 |
(the putMessage is the aspect with a colon)" |
|
219 |
||
125 | 220 |
getMsg := myAspect := aSelector. |
3300 | 221 |
putMsg := aSelector asMutator. |
381 | 222 |
|
223 |
"Modified: 22.1.1997 / 18:29:05 / cg" |
|
125 | 224 |
! ! |
225 |
||
226 |
!AspectAdaptor methodsFor:'accessing-value'! |
|
227 |
||
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
228 |
defaultValueIfNoSubject |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
229 |
"if there is no subject (taget to provide the value), |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
230 |
this value is returned." |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
231 |
|
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
232 |
^ nil |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
233 |
|
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
234 |
"Created: / 01-03-2012 / 08:53:38 / cg" |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
235 |
! |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
236 |
|
125 | 237 |
setValue:newValue |
381 | 238 |
"set the value - this forwards a putMessage to the target" |
239 |
||
125 | 240 |
|target oldValue| |
241 |
||
242 |
target := super value. |
|
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
243 |
target notNil ifTrue:[ |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
244 |
oldValue := target perform:getMsg. |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
245 |
oldValue ~~ newValue ifTrue:[ |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
246 |
target perform:putMsg with:newValue. |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
247 |
] |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
248 |
]. |
2286 | 249 |
|
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
250 |
"Modified: / 01-03-2012 / 08:54:10 / cg" |
125 | 251 |
! |
252 |
||
253 |
value |
|
254 |
"translate a query for my value from my user |
|
255 |
into an aspect access towards my subject" |
|
256 |
||
257 |
|target| |
|
258 |
||
259 |
target := super value. |
|
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
260 |
target isNil ifTrue:[^ self defaultValueIfNoSubject]. |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
261 |
|
125 | 262 |
^ target perform:getMsg |
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
263 |
|
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
264 |
"Modified (format): / 01-03-2012 / 08:54:33 / cg" |
125 | 265 |
! |
266 |
||
267 |
value:newValue |
|
381 | 268 |
"set the value - this forwards a putMessage to the target |
269 |
and sends out a changeNotification if the value did really change." |
|
270 |
||
125 | 271 |
|target oldValue| |
272 |
||
273 |
target := super value. |
|
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
274 |
target notNil ifTrue:[ |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
275 |
oldValue := target perform:getMsg. |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
276 |
oldValue ~~ newValue ifTrue:[ |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
277 |
target perform:putMsg with:newValue. |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
278 |
subjectSendsUpdates ifFalse:[ |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
279 |
self changed:#value |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
280 |
] |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
281 |
] |
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
282 |
]. |
2286 | 283 |
|
2988
bc154fbdd68d
added: #defaultValueIfNoSubject
Claus Gittinger <cg@exept.de>
parents:
2742
diff
changeset
|
284 |
"Modified: / 01-03-2012 / 08:54:27 / cg" |
125 | 285 |
! ! |
286 |
||
69 | 287 |
!AspectAdaptor methodsFor:'change & update'! |
288 |
||
289 |
update:something with:aParameter from:changedObject |
|
290 |
"translate an update from the model into a #value-change |
|
291 |
via my depenedents ..." |
|
292 |
||
448 | 293 |
((changedObject == subject and:[something == self forAspect]) |
69 | 294 |
or:[changedObject == subjectChannel]) ifTrue:[ |
448 | 295 |
self changed:#value |
69 | 296 |
]. |
297 |
! ! |
|
298 |
||
129 | 299 |
!AspectAdaptor class methodsFor:'documentation'! |
300 |
||
301 |
version |
|
3300 | 302 |
^ '$Header: /cvs/stx/stx/libview2/AspectAdaptor.st,v 1.24 2014-03-05 21:57:24 cg Exp $' |
129 | 303 |
! ! |
3300 | 304 |