.
--- 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
!