.
authorclaus
Tue, 09 May 1995 02:23:22 +0200
changeset 69 225a9efd50f5
parent 68 43b867285d01
child 70 2ab6538e2643
.
AppModel.st
ApplicationModel.st
AspctAdptr.st
AspectAdaptor.st
PrintConv.st
PrintConverter.st
ProtAdptr.st
ProtocolAdaptor.st
UIBuilder.st
ValHolder.st
ValModel.st
ValueHolder.st
ValueModel.st
WinBuilder.st
WindowBuilder.st
--- a/AppModel.st	Sat May 06 16:15:18 1995 +0200
+++ b/AppModel.st	Tue May 09 02:23:22 1995 +0200
@@ -39,7 +39,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libview2/Attic/AppModel.st,v 1.5 1995-05-03 00:01:12 claus Exp $
+$Header: /cvs/stx/stx/libview2/Attic/AppModel.st,v 1.6 1995-05-09 00:20:49 claus Exp $
 "
 !
 
@@ -88,6 +88,8 @@
 !ApplicationModel class methodsFor:'startup'!
 
 open
+    "create an instance of the application and open its view"
+
     self new open
 
     "
@@ -102,6 +104,8 @@
 !ApplicationModel class methodsFor:'change & update'!
 
 update:something
+    "flush resources on language changes"
+
     something == #Language ifTrue:[
 	"flush resources on language changes"
 	self flushAllClassResources
@@ -111,6 +115,8 @@
 !ApplicationModel class methodsFor:'queries'!
 
 interfaceSpecFor:aSelector
+    "return an interface spec"
+
     ^ self perform:aSelector
 ! !
 
@@ -160,6 +166,11 @@
 !ApplicationModel methodsFor:'initialization'!
 
 basicInitialize
+    "initialize the application.
+     Since ST-80 applications seem commonly to redefine initialize
+     without doing a super initialize, the real initialization is
+     done here ..."
+
     super initialize.
     "
      Create a windowBuilder to have someone around which
@@ -187,16 +198,30 @@
 !ApplicationModel methodsFor:'startup'!
 
 allButOpenFrom:aSpec
+    "create my views but do not open the main window"
+
     self preBuildWith:builder.
     builder buildFromSpec:aSpec.
     self postBuildWith:builder.
 !
 
+open
+    "open a standard interface"
+
+    self openInterface.
+!
+
 openInterface
+    "open a standard interface"
+
     self openInterface:#windowSpec
 !
 
 openInterface:aSymbol
+    "open an interface; the argument, aSymbol specifies which.
+     Typically, applications only use one interface, 
+     returned by the windowSpec method."
+
     |spec realBuilder|
 
     spec := self class interfaceSpecFor:aSymbol.
@@ -220,12 +245,8 @@
     ^ builder
 !
 
-open
-    self openInterface.
-!
-
 closeDownViews
-    "close down the application"
+    "close down the applications view"
 
     |wg views|
 
@@ -240,8 +261,16 @@
 !
 
 close
+    "this is sent by my topView when about to be closed
+     (By the program - not by the windowManager)."
+
+    self closeDownViews
+!
+
+closeRequest
     "this is sent by my topView when about to be closed by the
-     windowmanager. What should this do ?"
+     windowmanager. Can be redefined to inform & query about unsafed
+     view contents, to send #close on ok, or ignore the closeRequest."
 
     self closeDownViews
 !
@@ -253,11 +282,12 @@
     self postOpenWith:builder
 !
 
-closeRequest
-    "this is sent by my topView when about to be closed by the
-     windowmanager. What should this do ?"
-
-    self closeDownViews
+restarted
+    "sent by my windowGroup, when restarted from an image.
+     Nothing done here, but can be redefined to perform any actions
+     required to reset the application after an image-restart.
+     (for example: check if application files are still around, restart
+     subprocesses etc.)."
 !
 
 saveAndTerminateRequest
@@ -269,35 +299,58 @@
 !
 
 preBuildWith:aBuilder
-    "mhmh - what does this do ?"
+    "this is sent before an interface is built from a spec.
+     Can be redefined in subclasses.
+     mhmh - what should this do here ?"
 !
 
 postBuildWith:aBuilder
-    "mhmh - what does this do ?"
+    "this is sent after an interface is built from a spec.
+     Can be redefined in subclasses.
+     mhmh - what should this do here ?"
 !
 
 postOpenWith:aBuilder
-    "mhmh - what does this do ?"
+    "this is sent after the applications main window is opened.
+     Can be redefined in subclasses.
+     mhmh - what should this do here ?"
 ! !
 
 !ApplicationModel methodsFor:'accessing'!
 
 resources
+    "return the applications resources - thats a ResourcePack containing
+     language strings"
+
     ^ resources
 !
 
 windowGroup 
+    "return the applications windowGroup"
+
     ^ builder window windowGroup
 !
 
 builder
+    "return the applications builder; this one has more information
+     about views, components etc."
+
     ^ builder
 !
 
 builder:aBuilder
+    "set the applications builder. Normally, you should not set it
+     directly, but depend on the default builder, as created when the application
+     was created."
+
     builder := aBuilder
 !
 
 focusSequence
+    "return a focusSequence for stepping through the applications views.
+     The builder usually keeps track of so-called 'tabable' views.
+     Stepping is done with the FocusNext/FocusPrevius keys, which are typically bound
+     to Meta-CursorUp/Meta-CursorDown"
+
     ^ builder focusSequence
 ! !
--- a/ApplicationModel.st	Sat May 06 16:15:18 1995 +0200
+++ b/ApplicationModel.st	Tue May 09 02:23:22 1995 +0200
@@ -39,7 +39,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libview2/ApplicationModel.st,v 1.5 1995-05-03 00:01:12 claus Exp $
+$Header: /cvs/stx/stx/libview2/ApplicationModel.st,v 1.6 1995-05-09 00:20:49 claus Exp $
 "
 !
 
@@ -88,6 +88,8 @@
 !ApplicationModel class methodsFor:'startup'!
 
 open
+    "create an instance of the application and open its view"
+
     self new open
 
     "
@@ -102,6 +104,8 @@
 !ApplicationModel class methodsFor:'change & update'!
 
 update:something
+    "flush resources on language changes"
+
     something == #Language ifTrue:[
 	"flush resources on language changes"
 	self flushAllClassResources
@@ -111,6 +115,8 @@
 !ApplicationModel class methodsFor:'queries'!
 
 interfaceSpecFor:aSelector
+    "return an interface spec"
+
     ^ self perform:aSelector
 ! !
 
@@ -160,6 +166,11 @@
 !ApplicationModel methodsFor:'initialization'!
 
 basicInitialize
+    "initialize the application.
+     Since ST-80 applications seem commonly to redefine initialize
+     without doing a super initialize, the real initialization is
+     done here ..."
+
     super initialize.
     "
      Create a windowBuilder to have someone around which
@@ -187,16 +198,30 @@
 !ApplicationModel methodsFor:'startup'!
 
 allButOpenFrom:aSpec
+    "create my views but do not open the main window"
+
     self preBuildWith:builder.
     builder buildFromSpec:aSpec.
     self postBuildWith:builder.
 !
 
+open
+    "open a standard interface"
+
+    self openInterface.
+!
+
 openInterface
+    "open a standard interface"
+
     self openInterface:#windowSpec
 !
 
 openInterface:aSymbol
+    "open an interface; the argument, aSymbol specifies which.
+     Typically, applications only use one interface, 
+     returned by the windowSpec method."
+
     |spec realBuilder|
 
     spec := self class interfaceSpecFor:aSymbol.
@@ -220,12 +245,8 @@
     ^ builder
 !
 
-open
-    self openInterface.
-!
-
 closeDownViews
-    "close down the application"
+    "close down the applications view"
 
     |wg views|
 
@@ -240,8 +261,16 @@
 !
 
 close
+    "this is sent by my topView when about to be closed
+     (By the program - not by the windowManager)."
+
+    self closeDownViews
+!
+
+closeRequest
     "this is sent by my topView when about to be closed by the
-     windowmanager. What should this do ?"
+     windowmanager. Can be redefined to inform & query about unsafed
+     view contents, to send #close on ok, or ignore the closeRequest."
 
     self closeDownViews
 !
@@ -253,11 +282,12 @@
     self postOpenWith:builder
 !
 
-closeRequest
-    "this is sent by my topView when about to be closed by the
-     windowmanager. What should this do ?"
-
-    self closeDownViews
+restarted
+    "sent by my windowGroup, when restarted from an image.
+     Nothing done here, but can be redefined to perform any actions
+     required to reset the application after an image-restart.
+     (for example: check if application files are still around, restart
+     subprocesses etc.)."
 !
 
 saveAndTerminateRequest
@@ -269,35 +299,58 @@
 !
 
 preBuildWith:aBuilder
-    "mhmh - what does this do ?"
+    "this is sent before an interface is built from a spec.
+     Can be redefined in subclasses.
+     mhmh - what should this do here ?"
 !
 
 postBuildWith:aBuilder
-    "mhmh - what does this do ?"
+    "this is sent after an interface is built from a spec.
+     Can be redefined in subclasses.
+     mhmh - what should this do here ?"
 !
 
 postOpenWith:aBuilder
-    "mhmh - what does this do ?"
+    "this is sent after the applications main window is opened.
+     Can be redefined in subclasses.
+     mhmh - what should this do here ?"
 ! !
 
 !ApplicationModel methodsFor:'accessing'!
 
 resources
+    "return the applications resources - thats a ResourcePack containing
+     language strings"
+
     ^ resources
 !
 
 windowGroup 
+    "return the applications windowGroup"
+
     ^ builder window windowGroup
 !
 
 builder
+    "return the applications builder; this one has more information
+     about views, components etc."
+
     ^ builder
 !
 
 builder:aBuilder
+    "set the applications builder. Normally, you should not set it
+     directly, but depend on the default builder, as created when the application
+     was created."
+
     builder := aBuilder
 !
 
 focusSequence
+    "return a focusSequence for stepping through the applications views.
+     The builder usually keeps track of so-called 'tabable' views.
+     Stepping is done with the FocusNext/FocusPrevius keys, which are typically bound
+     to Meta-CursorUp/Meta-CursorDown"
+
     ^ builder focusSequence
 ! !
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AspctAdptr.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/Attic/AspctAdptr.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
+! !
--- /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
+! !
--- a/PrintConv.st	Sat May 06 16:15:18 1995 +0200
+++ b/PrintConv.st	Tue May 09 02:23:22 1995 +0200
@@ -9,7 +9,7 @@
 
 version 
 "
-$Header: /cvs/stx/stx/libview2/Attic/PrintConv.st,v 1.2 1995-05-06 14:14:34 claus Exp $
+$Header: /cvs/stx/stx/libview2/Attic/PrintConv.st,v 1.3 1995-05-09 00:21:50 claus Exp $
 "
 !
 
@@ -30,34 +30,52 @@
 
 examples 
 "
-    |conv|
+    stupid examples"
+      |conv|
 
-    conv := (PrintConverter new)
-		toPrint:[:date | date printString]
-		toRead:[:string | Date readFromString:string].
-    (conv printStringFor:(Date today)) inspect.
-    (conv readValueFrom:(Date today printString)) inspect
+      conv := (PrintConverter new)
+		  toPrint:[:date | date printString]
+		  toRead:[:string | Date readFromString:string].
+      (conv printStringFor:(Date today)) inspect.
+      (conv readValueFrom:(Date today printString)) inspect
+
+
+      |conv|
+
+      conv := (PrintConverter new) initForNumber.
+      (conv printStringFor:12345) inspect.
+      (conv readValueFrom:'12345') inspect
 
 
-    |conv|
+      |conv|
+
+      conv := (PrintConverter new) initForYesNo.
+      (conv printStringFor:true).  
+      (conv printStringFor:false).    
+      (conv readValueFrom:'yes').  
+      (conv readValueFrom:'no').  
+      'if language is german:'.
+      (conv readValueFrom:'ja').    
+      (conv readValueFrom:'nein')  
+
+    concrete example: convert in an inputField:
 
-    conv := (PrintConverter new) initForNumber.
-    (conv printStringFor:12345) inspect.
-    (conv readValueFrom:'12345') inspect
+      |dialog field|
+
+      dialog := Dialog new.
+      dialog addTextLabel:'a number (and only numbers):'.
+      dialog addVerticalSpace.
+      field := dialog addInputFieldOn:(0 asValue).
+      field converter:(PrintConverter new initForNumber).
+      field immediateAccept:true.
+      dialog addOkButton.
+      dialog open.
+      dialog accepted ifTrue:[
+	  Transcript showCr:field editValue
+      ]
 
 
-    |conv|
-
-    conv := (PrintConverter new) initForYesNo.
-    (conv printStringFor:true).  
-    (conv printStringFor:false).    
-    (conv readValueFrom:'yes').  
-    (conv readValueFrom:'no').  
-    'if language is german:'.
-    (conv readValueFrom:'ja').    
-    (conv readValueFrom:'nein')  
-
-    see concrete uses in the EditField examples.
+    see more examples in the EditField examples.
 "
 ! !
 
@@ -72,31 +90,79 @@
 !PrintConverter methodsFor:'initialization'!
 
 toPrint:printBlock toRead:readBlock
+    "initialize to convert using two custom blocks"
+
     valueToStringBlock := printBlock.
     stringToValueBlock := readBlock.
 !
 
+initForInteger
+    "initialize to convert to/from an integer 
+     - if the string is empty or invalid, convert to 0"
+
+    valueToStringBlock := [:num | num printString].
+    stringToValueBlock := [:string | Integer readFromString:string onError:0]
+!
+
+initForIntegerOrNil
+    "initialize to convert to/from an integer 
+     - if the string is empty or invalid, convert to nil"
+
+    valueToStringBlock := [:num | 
+	num isNil ifTrue:[''] 
+		  ifFalse:[num printString]].
+    stringToValueBlock := [:string | 
+	Integer readFromString:string onError:nil]
+!
+
 initForNumber
+    "initialize to convert to/from a number 
+     - if the string is empty or invalid, convert to 0"
+
     valueToStringBlock := [:num | num printString].
     stringToValueBlock := [:string | Number readFromString:string onError:0]
 !
 
 initForNumberOrNil
-    valueToStringBlock := [:num | num isNil ifTrue:[''] ifFalse:[num printString]].
-    stringToValueBlock := [:string | Number readFromString:string onError:nil]
+    "initialize to convert to/from a number 
+     - if the string is empty or invalid, convert to nil"
+
+    valueToStringBlock := [:num | 
+	num isNil ifTrue:[''] 
+		  ifFalse:[num printString]].
+    stringToValueBlock := [:string | 
+	Number readFromString:string onError:nil]
 !
 
 initForString
+    "initialize for a string - this is trivial"
+
     valueToStringBlock := [:val | val isNil ifTrue:[''] ifFalse:[val]].
     stringToValueBlock := [:string | string]
 !
 
 initForDate
+    "initialize to convert to/from a date 
+     - if the string is empty or invalid, convert to the current date"
+
     valueToStringBlock := [:date | date printString].
     stringToValueBlock := [:string | Date readFromString:string onError:[Date today]]
 !
 
+initForDateOrNil
+    "initialize to convert to/from a date 
+     - if the string is empty or invalid, convert to nil"
+
+    valueToStringBlock := [:date | date printString].
+    stringToValueBlock := [:string | Date readFromString:string onError:nil]
+!
+
 initForYesNo
+    "initialize to convert a 'yes'/'no' string to/from a boolean 
+     The string is supposed to be in the current Language
+     (i.e. if german, ja/nein has to be enterred.
+     Invalid entries are converted to false."
+
     valueToStringBlock := [:bool | bool ifTrue:[ApplicationModel classResources string:'yes']
 					ifFalse:[ApplicationModel classResources string:'no']].
     stringToValueBlock := [:string | string = (ApplicationModel classResources string:'yes')]
--- a/PrintConverter.st	Sat May 06 16:15:18 1995 +0200
+++ b/PrintConverter.st	Tue May 09 02:23:22 1995 +0200
@@ -9,7 +9,7 @@
 
 version 
 "
-$Header: /cvs/stx/stx/libview2/PrintConverter.st,v 1.2 1995-05-06 14:14:34 claus Exp $
+$Header: /cvs/stx/stx/libview2/PrintConverter.st,v 1.3 1995-05-09 00:21:50 claus Exp $
 "
 !
 
@@ -30,34 +30,52 @@
 
 examples 
 "
-    |conv|
+    stupid examples"
+      |conv|
 
-    conv := (PrintConverter new)
-		toPrint:[:date | date printString]
-		toRead:[:string | Date readFromString:string].
-    (conv printStringFor:(Date today)) inspect.
-    (conv readValueFrom:(Date today printString)) inspect
+      conv := (PrintConverter new)
+		  toPrint:[:date | date printString]
+		  toRead:[:string | Date readFromString:string].
+      (conv printStringFor:(Date today)) inspect.
+      (conv readValueFrom:(Date today printString)) inspect
+
+
+      |conv|
+
+      conv := (PrintConverter new) initForNumber.
+      (conv printStringFor:12345) inspect.
+      (conv readValueFrom:'12345') inspect
 
 
-    |conv|
+      |conv|
+
+      conv := (PrintConverter new) initForYesNo.
+      (conv printStringFor:true).  
+      (conv printStringFor:false).    
+      (conv readValueFrom:'yes').  
+      (conv readValueFrom:'no').  
+      'if language is german:'.
+      (conv readValueFrom:'ja').    
+      (conv readValueFrom:'nein')  
+
+    concrete example: convert in an inputField:
 
-    conv := (PrintConverter new) initForNumber.
-    (conv printStringFor:12345) inspect.
-    (conv readValueFrom:'12345') inspect
+      |dialog field|
+
+      dialog := Dialog new.
+      dialog addTextLabel:'a number (and only numbers):'.
+      dialog addVerticalSpace.
+      field := dialog addInputFieldOn:(0 asValue).
+      field converter:(PrintConverter new initForNumber).
+      field immediateAccept:true.
+      dialog addOkButton.
+      dialog open.
+      dialog accepted ifTrue:[
+	  Transcript showCr:field editValue
+      ]
 
 
-    |conv|
-
-    conv := (PrintConverter new) initForYesNo.
-    (conv printStringFor:true).  
-    (conv printStringFor:false).    
-    (conv readValueFrom:'yes').  
-    (conv readValueFrom:'no').  
-    'if language is german:'.
-    (conv readValueFrom:'ja').    
-    (conv readValueFrom:'nein')  
-
-    see concrete uses in the EditField examples.
+    see more examples in the EditField examples.
 "
 ! !
 
@@ -72,31 +90,79 @@
 !PrintConverter methodsFor:'initialization'!
 
 toPrint:printBlock toRead:readBlock
+    "initialize to convert using two custom blocks"
+
     valueToStringBlock := printBlock.
     stringToValueBlock := readBlock.
 !
 
+initForInteger
+    "initialize to convert to/from an integer 
+     - if the string is empty or invalid, convert to 0"
+
+    valueToStringBlock := [:num | num printString].
+    stringToValueBlock := [:string | Integer readFromString:string onError:0]
+!
+
+initForIntegerOrNil
+    "initialize to convert to/from an integer 
+     - if the string is empty or invalid, convert to nil"
+
+    valueToStringBlock := [:num | 
+	num isNil ifTrue:[''] 
+		  ifFalse:[num printString]].
+    stringToValueBlock := [:string | 
+	Integer readFromString:string onError:nil]
+!
+
 initForNumber
+    "initialize to convert to/from a number 
+     - if the string is empty or invalid, convert to 0"
+
     valueToStringBlock := [:num | num printString].
     stringToValueBlock := [:string | Number readFromString:string onError:0]
 !
 
 initForNumberOrNil
-    valueToStringBlock := [:num | num isNil ifTrue:[''] ifFalse:[num printString]].
-    stringToValueBlock := [:string | Number readFromString:string onError:nil]
+    "initialize to convert to/from a number 
+     - if the string is empty or invalid, convert to nil"
+
+    valueToStringBlock := [:num | 
+	num isNil ifTrue:[''] 
+		  ifFalse:[num printString]].
+    stringToValueBlock := [:string | 
+	Number readFromString:string onError:nil]
 !
 
 initForString
+    "initialize for a string - this is trivial"
+
     valueToStringBlock := [:val | val isNil ifTrue:[''] ifFalse:[val]].
     stringToValueBlock := [:string | string]
 !
 
 initForDate
+    "initialize to convert to/from a date 
+     - if the string is empty or invalid, convert to the current date"
+
     valueToStringBlock := [:date | date printString].
     stringToValueBlock := [:string | Date readFromString:string onError:[Date today]]
 !
 
+initForDateOrNil
+    "initialize to convert to/from a date 
+     - if the string is empty or invalid, convert to nil"
+
+    valueToStringBlock := [:date | date printString].
+    stringToValueBlock := [:string | Date readFromString:string onError:nil]
+!
+
 initForYesNo
+    "initialize to convert a 'yes'/'no' string to/from a boolean 
+     The string is supposed to be in the current Language
+     (i.e. if german, ja/nein has to be enterred.
+     Invalid entries are converted to false."
+
     valueToStringBlock := [:bool | bool ifTrue:[ApplicationModel classResources string:'yes']
 					ifFalse:[ApplicationModel classResources string:'no']].
     stringToValueBlock := [:string | string = (ApplicationModel classResources string:'yes')]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ProtAdptr.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/Attic/ProtAdptr.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
+! !
+
--- /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
+! !
+
--- a/UIBuilder.st	Sat May 06 16:15:18 1995 +0200
+++ b/UIBuilder.st	Tue May 09 02:23:22 1995 +0200
@@ -88,10 +88,6 @@
     f := ScrollableView for:SelectionInListView in:aView.
     s := f scrolledView.
     self doSpec:aSpec for:s frame:f.
-    s
-	aspect:#value;
-	change:#value:;
-	listSymbol:#list 
 !
 
 xScrollerSpec:aSpec view:aView
--- a/ValHolder.st	Sat May 06 16:15:18 1995 +0200
+++ b/ValHolder.st	Tue May 09 02:23:22 1995 +0200
@@ -1,5 +1,5 @@
 ValueModel subclass:#ValueHolder 
-	 instanceVariableNames:'value changeMsg changeReceiver'
+	 instanceVariableNames:'value'
 	 classVariableNames:''
 	 poolDictionaries:''
 	 category:'Interface-Support'
@@ -7,13 +7,31 @@
 
 !ValueHolder 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/Attic/ValHolder.st,v 1.4 1995-05-09 00:22:53 claus Exp $
+"
+!
+
 documentation
 "
-    a valueHolder can me used as a model for editFields, buttons etc.
+    a valueHolder can be used as a model for editFields, buttons etc.
     It stores some value internally, and sends update messages to its
     dependents when changed.
-    In addition, a specific message (changeMsg) can be sent to a specific
-    object (changeObject) when the value is changed.
 
     Notice: this class was implemented using protocol information
     from alpha testers - it may not be complete or compatible to
@@ -27,7 +45,7 @@
 with:anObject
     "return a new ValueHolder holding anObject as initial value"
 
-    ^ (super new) value:anObject
+    ^ (super new) setValue:anObject
 !
 
 newString
@@ -57,29 +75,10 @@
 
 !ValueHolder methodsFor:'accessing'!
 
-onChangeSend:selector to:someone
-    "set the selector and receiver for a message sent when my value changes."
-
-    changeMsg := selector.
-    changeReceiver := someone
-!
+setValue:anObject
+    "set my value without notification."
 
-value:anObject
-    "set my value. Tell dependents and (optionally) the changeReceiver
-     about that change.
-     Typically, this is sent from a view which operates on myself.
-     The dependents are typically other views or the application."
-
-    |oldValue|
-
-    oldValue := value.
     value := anObject.
-    self changed:#value.
-    changeReceiver notNil ifTrue:[
-	changeMsg notNil ifTrue:[
-	    changeReceiver perform:changeMsg
-	]
-    ]
 !
 
 value
--- a/ValModel.st	Sat May 06 16:15:18 1995 +0200
+++ b/ValModel.st	Tue May 09 02:23:22 1995 +0200
@@ -1,5 +1,7 @@
-Model subclass:#ValueModel 
-	 instanceVariableNames:'accepted'
+'From Smalltalk/X, Version:2.10.5 on 9-may-1995 at 12:03:02 pm'!
+
+Model subclass:#ValueModel
+	 instanceVariableNames:'accepted interrest'
 	 classVariableNames:''
 	 poolDictionaries:''
 	 category:'Interface-Support'
@@ -7,14 +9,42 @@
 
 !ValueModel class methodsFor:'documentation'!
 
+Model 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/Attic/ValModel.st,v 1.4 1995-05-09 00:22:56 claus Exp $
+"
+!
+
 documentation
 "
     abstract superclass for ValueHolders and Adaptors.
+    It does not itself know how and where the value is stored,
+    but knows about interrested objects (which get informed, whenever
+    the value changes) and keeps track if the value was ever accepted.
 
     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.
+
+    subclasses must redefine: #setValue: and #value
+    (and optionally redefine #value:)
 "
 ! !
 
@@ -24,14 +54,33 @@
     ^ (super new) initialize
 ! !
 
-!ValueModel methodsFor:'initialization'!
+!ValueModel methodsFor:'change notification'!
 
-initialize
-    accepted := false
+notifyChange:aSymbol
+    interrest notNil ifTrue:[
+        interrest keysAndValuesDo:[:someone :selector |
+            someone perform:selector
+        ].
+    ].
+    self changed:aSymbol
 ! !
 
 !ValueModel methodsFor:'accessing'!
 
+value:anObject
+    |oldValue|
+
+    oldValue := self value.
+    self setValue:anObject.
+    anObject ~= oldValue ifTrue:[
+        self notifyChange:#value
+    ]
+!
+
+accepted
+    ^ accepted
+!
+
 accept
     accepted := true
 !
@@ -42,15 +91,35 @@
 
 setValue:newValue 
     self subclassResponsibility
+! !
+
+!ValueModel methodsFor:'initialization'!
+
+initialize
+    accepted := false
+! !
+
+!ValueModel methodsFor:'interrest'!
+
+retractInterrestFor:someone
+    "release interrest i.e. do no longer send changeMsg to changeReceiver
+     iff someone is the changeReceiver.
+     This can be used to (temporarily) turn off information sends,
+     to break endless cycles (if two values change each other)"
+
+    interrest notNil ifTrue:[
+	interrest removeKey:someone ifAbsent:nil
+    ]
 !
 
-value:anObject
-    |oldValue|
+onChangeSend:selector to:someone
+    "add an interrest, arranging that
+     a message with selector will be sent to someone 
+     when my value changes."
 
-    oldValue := self value.
-    self setValue:anObject.
-    anObject ~= oldValue ifTrue:[
-	self changed:#value
-    ]
+    interrest isNil ifTrue:[
+	interrest := IdentityDictionary new
+    ].
+    interrest at:someone put:selector
 ! !
 
--- a/ValueHolder.st	Sat May 06 16:15:18 1995 +0200
+++ b/ValueHolder.st	Tue May 09 02:23:22 1995 +0200
@@ -1,5 +1,5 @@
 ValueModel subclass:#ValueHolder 
-	 instanceVariableNames:'value changeMsg changeReceiver'
+	 instanceVariableNames:'value'
 	 classVariableNames:''
 	 poolDictionaries:''
 	 category:'Interface-Support'
@@ -7,13 +7,31 @@
 
 !ValueHolder 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/ValueHolder.st,v 1.4 1995-05-09 00:22:53 claus Exp $
+"
+!
+
 documentation
 "
-    a valueHolder can me used as a model for editFields, buttons etc.
+    a valueHolder can be used as a model for editFields, buttons etc.
     It stores some value internally, and sends update messages to its
     dependents when changed.
-    In addition, a specific message (changeMsg) can be sent to a specific
-    object (changeObject) when the value is changed.
 
     Notice: this class was implemented using protocol information
     from alpha testers - it may not be complete or compatible to
@@ -27,7 +45,7 @@
 with:anObject
     "return a new ValueHolder holding anObject as initial value"
 
-    ^ (super new) value:anObject
+    ^ (super new) setValue:anObject
 !
 
 newString
@@ -57,29 +75,10 @@
 
 !ValueHolder methodsFor:'accessing'!
 
-onChangeSend:selector to:someone
-    "set the selector and receiver for a message sent when my value changes."
-
-    changeMsg := selector.
-    changeReceiver := someone
-!
+setValue:anObject
+    "set my value without notification."
 
-value:anObject
-    "set my value. Tell dependents and (optionally) the changeReceiver
-     about that change.
-     Typically, this is sent from a view which operates on myself.
-     The dependents are typically other views or the application."
-
-    |oldValue|
-
-    oldValue := value.
     value := anObject.
-    self changed:#value.
-    changeReceiver notNil ifTrue:[
-	changeMsg notNil ifTrue:[
-	    changeReceiver perform:changeMsg
-	]
-    ]
 !
 
 value
--- a/ValueModel.st	Sat May 06 16:15:18 1995 +0200
+++ b/ValueModel.st	Tue May 09 02:23:22 1995 +0200
@@ -1,5 +1,7 @@
-Model subclass:#ValueModel 
-	 instanceVariableNames:'accepted'
+'From Smalltalk/X, Version:2.10.5 on 9-may-1995 at 12:03:02 pm'!
+
+Model subclass:#ValueModel
+	 instanceVariableNames:'accepted interrest'
 	 classVariableNames:''
 	 poolDictionaries:''
 	 category:'Interface-Support'
@@ -7,14 +9,42 @@
 
 !ValueModel class methodsFor:'documentation'!
 
+Model 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/ValueModel.st,v 1.4 1995-05-09 00:22:56 claus Exp $
+"
+!
+
 documentation
 "
     abstract superclass for ValueHolders and Adaptors.
+    It does not itself know how and where the value is stored,
+    but knows about interrested objects (which get informed, whenever
+    the value changes) and keeps track if the value was ever accepted.
 
     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.
+
+    subclasses must redefine: #setValue: and #value
+    (and optionally redefine #value:)
 "
 ! !
 
@@ -24,14 +54,33 @@
     ^ (super new) initialize
 ! !
 
-!ValueModel methodsFor:'initialization'!
+!ValueModel methodsFor:'change notification'!
 
-initialize
-    accepted := false
+notifyChange:aSymbol
+    interrest notNil ifTrue:[
+        interrest keysAndValuesDo:[:someone :selector |
+            someone perform:selector
+        ].
+    ].
+    self changed:aSymbol
 ! !
 
 !ValueModel methodsFor:'accessing'!
 
+value:anObject
+    |oldValue|
+
+    oldValue := self value.
+    self setValue:anObject.
+    anObject ~= oldValue ifTrue:[
+        self notifyChange:#value
+    ]
+!
+
+accepted
+    ^ accepted
+!
+
 accept
     accepted := true
 !
@@ -42,15 +91,35 @@
 
 setValue:newValue 
     self subclassResponsibility
+! !
+
+!ValueModel methodsFor:'initialization'!
+
+initialize
+    accepted := false
+! !
+
+!ValueModel methodsFor:'interrest'!
+
+retractInterrestFor:someone
+    "release interrest i.e. do no longer send changeMsg to changeReceiver
+     iff someone is the changeReceiver.
+     This can be used to (temporarily) turn off information sends,
+     to break endless cycles (if two values change each other)"
+
+    interrest notNil ifTrue:[
+	interrest removeKey:someone ifAbsent:nil
+    ]
 !
 
-value:anObject
-    |oldValue|
+onChangeSend:selector to:someone
+    "add an interrest, arranging that
+     a message with selector will be sent to someone 
+     when my value changes."
 
-    oldValue := self value.
-    self setValue:anObject.
-    anObject ~= oldValue ifTrue:[
-	self changed:#value
-    ]
+    interrest isNil ifTrue:[
+	interrest := IdentityDictionary new
+    ].
+    interrest at:someone put:selector
 ! !
 
--- a/WinBuilder.st	Sat May 06 16:15:18 1995 +0200
+++ b/WinBuilder.st	Tue May 09 02:23:22 1995 +0200
@@ -9,7 +9,7 @@
 
 documentation
 "
-    an no-op class, for systems which do not use the UIBuilder.
+    a no-op class, for systems which do not use the UIBuilder.
     Concrete subclasses know how to create a view (with components) from
     some interface spec. Currently, an experimantal version of UIBuilder exists,
     and more may be added in the future (for example, to parse different UI
@@ -47,6 +47,10 @@
     ^ components at:name ifAbsent:nil
 !
 
+window:aView
+    topView := aView
+!
+
 window
     ^ topView
 !
--- a/WindowBuilder.st	Sat May 06 16:15:18 1995 +0200
+++ b/WindowBuilder.st	Tue May 09 02:23:22 1995 +0200
@@ -9,7 +9,7 @@
 
 documentation
 "
-    an no-op class, for systems which do not use the UIBuilder.
+    a no-op class, for systems which do not use the UIBuilder.
     Concrete subclasses know how to create a view (with components) from
     some interface spec. Currently, an experimantal version of UIBuilder exists,
     and more may be added in the future (for example, to parse different UI
@@ -47,6 +47,10 @@
     ^ components at:name ifAbsent:nil
 !
 
+window:aView
+    topView := aView
+!
+
 window
     ^ topView
 !