.
authorclaus
Sun, 07 May 1995 02:16:56 +0200
changeset 122 04ec3fda7c11
parent 121 4e63bbdb266a
child 123 25ab7ade4d3a
.
DialogBox.st
EFGroup.st
EditField.st
EnterBox.st
EnterFieldGroup.st
LSelBox.st
ListSelectionBox.st
Make.proto
ScrView.st
ScrollableView.st
--- a/DialogBox.st	Sat May 06 16:18:13 1995 +0200
+++ b/DialogBox.st	Sun May 07 02:16:56 1995 +0200
@@ -25,7 +25,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/DialogBox.st,v 1.10 1995-05-06 14:16:36 claus Exp $
+$Header: /cvs/stx/stx/libwidg/DialogBox.st,v 1.11 1995-05-07 00:15:45 claus Exp $
 "
 !
 
@@ -41,6 +41,9 @@
     in a top-to-bottom fashion, and also keep track of added text-fields and,
     since they are most common, automatically create an EnterFieldGroup for
     them.
+    Caveat: more adding support is required - especially for row-wise
+    construction.
+
 
     instance variables:
 
@@ -97,6 +100,10 @@
 
 	DialogBox new addAbortButton; addOkButton; open
 
+    with different ok-label:
+
+	DialogBox new addAbortButton; addOkButtonLabelled:'yeah'; open
+
     adding a textlabel gives an infoBox:
 
 	DialogBox new
@@ -122,6 +129,18 @@
 	    addOkButton; 
 	    open
 
+    with modified buttons:
+
+	|box|
+
+	box := DialogBox new.
+	(box addTextLabel:'are you certain ?') adjust:#left.
+	box addAbortButtonLabelled:'not really'. 
+	(box addOkButtonLabelled:'yes, absolutely') 
+		activeBackgroundColor:Color red. 
+	box open
+
+
     two textlabels:
 
 	DialogBox new
@@ -164,7 +183,6 @@
 
 	DialogBox new
 	    addTextLabel:(Image fromFile:'bitmaps/garfield.gif');
-	    addAbortButton; 
 	    addOkButton; 
 	    open
 
@@ -202,6 +220,7 @@
 	(DialogBox new
 	    addTextLabel:'Please enter your name:';
 	    addInputFieldOn:firstName; 
+	    addVerticalSpace;
 	    addInputFieldOn:lastName; 
 	    addAbortButton; 
 	    addOkButton; 
@@ -234,6 +253,7 @@
 	(DialogBox new
 	    addTextLabel:'Please enter your name:';
 	    addInputFieldOn:firstName; 
+	    addVerticalSpace;
 	    addInputFieldOn:lastName; 
 	    addAbortButton; 
 	    addOkButton;
@@ -680,7 +700,7 @@
     "user pressed ok-button; make myself invisible and if an action was
      specified do it"
 
-    okButton turnOffWithoutRedraw.
+    okButton notNil ifTrue:[okButton turnOffWithoutRedraw].
     self accept.
     self hideAndEvaluate:okAction.
 !
@@ -713,43 +733,71 @@
     buttonPanel subViews size > 1 ifTrue:[
 	buttonPanel layout:#fitSpace.
     ].
+    ^ aButton
 !
 
-addOkButton:action
+addOkButtonLabelled:buttonLabel 
+    "create an okButton with a label - to be sent from redefined initialize
+     methods in subclasses or when creating a box programmatically.
+     A nil argument creates one with the default text.
+     Returns the button."
+
+    okButton := Button okButton.
+    okButton model:self; change:#okPressed.
+    buttonLabel notNil ifTrue:[okButton label:buttonLabel].
+    okButton isReturnButton:acceptReturnAsOK.
+    ^ self addButton:okButton.
+!
+
+XXaddOkButton:action
     "create an okButton - to be sent from redefined initialize
-     methods in subclasses."
+     methods in subclasses or when creating a box programmatically."
 
     okButton := Button okButton.
     action notNil ifTrue:[okButton action:action].
     okButton model:self; change:#okPressed.
     okButton isReturnButton:acceptReturnAsOK.
-    self addButton:okButton.
+    ^ self addButton:okButton.
 !
 
 addOkButton
     "create an okButton - to be sent from redefined initialize
-     methods in subclasses."
+     methods in subclasses or when creating a box programmatically.
+     Returns the button."
 
-    self addOkButton:nil
+    ^ self addOkButtonLabelled:nil
 !
 
 addButton:aButton
-    "add a button in the buttonPanel"
+    "add a button into the buttonPanel.
+     Returns the button."
+
+    ^ self addButton:aButton after:nil
+!
 
-    self addButton:aButton after:nil
+addAbortButtonLabelled:buttonLabel
+    "create an abortButton with a label - to be sent from redefined initialize
+     methods in subclasses or when creating a box programmatically.
+     A nil argument creates one with the default label.
+     Returns the button."
+
+    abortButton := Button abortButton.
+    abortButton model:self; change:#abortPressed.
+    buttonLabel notNil ifTrue:[abortButton label:buttonLabel].
+    ^ self addButton:abortButton.
 !
 
 addAbortButton
     "create an abortButton - to be sent from redefined initialize
-     methods in subclasses."
+     methods in subclasses or when creating a box programmatically.
+     Returns the button."
 
-    abortButton := Button abortButton.
-    abortButton model:self; change:#abortPressed.
-    self addButton:abortButton.
+    ^ self addAbortButtonLabelled:nil
 !
 
 addComponent:aComponent withHeight:height 
-    "add a component with some given height and full width"
+    "add a component with some given height and full width.
+     Returns the component."
 
     self basicAddComponent:aComponent.
     aComponent height:height.
@@ -758,10 +806,12 @@
 	       leftInset:leftIndent+ViewSpacing;
 	       rightInset:ViewSpacing.
     yPosition := yPosition + aComponent height.
+    ^ aComponent
 !
 
 addComponent:aComponent withExtent:ext 
-    "add a component with some given extent"
+    "add a component with some given extent.
+     Returns the component."
 
     self basicAddComponent:aComponent.
     aComponent extent:ext.
@@ -769,18 +819,21 @@
 	       leftInset:leftIndent; 
 	       rightInset:ViewSpacing.
     yPosition := yPosition + aComponent height.
+    ^ aComponent
 !
 
 addComponent:aComponent
-    "add a component with its prefered height and full width"
+    "add a component with its prefered height and full width.
+     Returns the component."
 
-    self addComponent:aComponent 
+    ^ self addComponent:aComponent 
 	   withHeight:(aComponent preferedExtent y).
 !
 
 addTextLabel:aString
     "create a text label - the name has been choosen for ST-80 compatibility;
-     however, ST/X labels allow image labels too."
+     however, ST/X labels allow image labels too.
+     Returns the label."
 
     |l|
 
@@ -844,6 +897,9 @@
 !
 
 addCheckBox:label on:aModel
+    "create a checkBox with label on aModel and add it.
+     Returns the box."
+
     |b|
 
     b := CheckBox on:aModel.
@@ -852,23 +908,10 @@
     ^ b
 !
 
-addVerticalSpace:nPixel
-    yPosition := yPosition + nPixel.
-!
-
-yPosition 
-    ^ yPosition 
-!
+addInputField:aField
+    "add an already created input field; return the field.
+     Returns the field."
 
-yPosition:aNumber 
-    yPosition := aNumber.
-!
-
-leftIndent:aNumber 
-    leftIndent := aNumber.
-!
-
-addInputField:aField
     self addComponent:aField.
     inputFieldGroup isNil ifTrue:[
 	inputFieldGroup := EnterFieldGroup new.
@@ -881,6 +924,9 @@
 !
 
 addInputFieldOn:aModel
+    "create an input field on aModel and add it.
+     Returns the field."
+
     |f|
 
     f := EditField new.
@@ -901,6 +947,39 @@
      dialog open.
      ok ifTrue:[Transcript showCr:model value].
     "
+!
+
+addVerticalSpace
+    "add a default vertical space (1 mm)"
+
+    self addVerticalSpace:(ViewSpacing).
+!
+
+addVerticalSpace:nPixel
+    "add some pixels of space to the next component"
+
+    yPosition := yPosition + nPixel.
+!
+
+yPosition 
+    "return the current y position (thats where the next component
+     will be located)."
+
+    ^ yPosition 
+!
+
+yPosition:aNumber 
+    "set the current y position (thats where the next component
+     will be located)."
+
+    yPosition := aNumber.
+!
+
+leftIndent:aNumber 
+    "set the left indent (current x position - thats where the next component
+     will be located)."
+
+    leftIndent := aNumber.
 ! !
 
 !DialogBox methodsFor:'initialization'!
@@ -925,7 +1004,7 @@
 	borderWidth:0;
 	layout:#spread.
 
-    yPosition := 0.
+    yPosition := ViewSpacing.
     leftIndent := 0.
 
     "
@@ -1006,8 +1085,7 @@
     ] ifFalse:[
 	w := super preferedExtent x.
     ].
-    h := ViewSpacing
-	 + yPosition
+    h := yPosition
 	 + ViewSpacing.
 
     okButton notNil ifTrue:[
@@ -1145,4 +1223,3 @@
 	shown ifTrue:[self resize]
     ]
 ! !
-
--- a/EFGroup.st	Sat May 06 16:18:13 1995 +0200
+++ b/EFGroup.st	Sun May 07 02:16:56 1995 +0200
@@ -11,7 +11,8 @@
 "
 
 Object subclass:#EnterFieldGroup
-	 instanceVariableNames:'fields currentField leaveAction'
+	 instanceVariableNames:'fields currentField leaveAction
+				wrap'
 	 classVariableNames:''
 	 poolDictionaries:''
 	 category:'Views-Support'
@@ -21,7 +22,7 @@
 COPYRIGHT (c) 1992 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/Attic/EFGroup.st,v 1.8 1995-05-06 14:16:40 claus Exp $
+$Header: /cvs/stx/stx/libwidg/Attic/EFGroup.st,v 1.9 1995-05-07 00:15:50 claus Exp $
 '!
 
 !EnterFieldGroup class methodsFor:'documentation'!
@@ -42,7 +43,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/Attic/EFGroup.st,v 1.8 1995-05-06 14:16:40 claus Exp $
+$Header: /cvs/stx/stx/libwidg/Attic/EFGroup.st,v 1.9 1995-05-07 00:15:50 claus Exp $
 "
 !
 
@@ -58,12 +59,38 @@
     field of the group is left (by cursor-down or cr). 
     Usually this block triggers accept on the fields and/or performs some
     followup processing and closes  the topview (for example: in a dialog).
+
+    EnterFieldGroups can be used as a delegate (of the topView) to forward
+    input (entered into the topView) to the currently active field.
+
+    Stepping to previous field is via CursorUp/PreviousField,
+    to next field via CursorDown/NextField/Tab.
+    Notice, that by default, the editField takes the tab-character as
+    a normal character. To step using tab, you have to add the Tab key to the
+    fields leaveKeys.
+
+    Instance variables:
+
+	fields          <Collection of EditField>       the fields of the group
+
+	currentField    <EditField>                     the active field
+
+	leaveAction     <nil|Block>                     action to perform, when the
+							last field is left by a non-wrap
+
+	wrap            <Boolean>                       if true, non-return next-keys wrap
+							back to the first field.
+							If false (the default), next in
+							the last field is taken as return.
+							This is ignored, if no leaveAction was 
+							defined.
 "
 !
 
 examples 
 "
-    without a group - user has to click on next field to activate it:
+    without a group - user has to enter mouse into the next field to activate it;
+    Cursor-keys dont work:
 
 	|top panel field1 field2 field3|
 
@@ -80,6 +107,8 @@
 
 
     with a group - Return-key or CursorKey enables next field:
+    (but still, mouse pointer has to be moved into any of the fields,
+     because the topView does not forward its input into the fields)
 
 	|top panel group field1 field2 field3|
 
@@ -99,7 +128,74 @@
 
 
 
-    with a group - close the box when the last field is left:
+    same, enables tabbing via the Tab key:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+
+	field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	top open
+
+
+
+    with a group - Return-key or CursorKey enables next field:
+    input into topView is forwarded to the group:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+
+	top delegate:group.
+	top open
+
+
+
+    as above, but close the box when the last field is left:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+	group leaveAction:[top destroy].
+
+	top delegate:group.
+	top open
+
+
+
+    same as above, with Tab-key stepping:
 
 	|top panel group field1 field2 field3|
 
@@ -116,14 +212,122 @@
 	group add:field1; add:field2; add:field3.
 	group leaveAction:[top destroy].
 
+	field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+
+	top delegate:group.
 	top open
+
+
+
+    the next example shows that the input order is defined by the
+    order in the group; NOT by the physical layout of the fields in the superview:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field3; add:field2; add:field1.
+	group leaveAction:[top destroy].
+
+	top delegate:group.
+	top open
+
+
+
+    using a single model for all fields:
+    (here, we use a Plug to simulate a more complex model):
+
+	|top panel group field1 field2 field3 model
+	 value1 value2 value3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+	group leaveAction:[top destroy].
+
+	value1 := 'one'. value2 := 'two'. value3 := 'three'.
+
+	model := Plug new.
+	model respondTo:#value1 with:[value1].
+	model respondTo:#value1: with:[:arg | value1 := arg].
+	model respondTo:#value2 with:[value2].
+	model respondTo:#value2: with:[:arg | value2 := arg].
+	model respondTo:#value3 with:[value3].
+	model respondTo:#value3: with:[:arg | value3 := arg].
+
+	field1 model:model; aspect:#value1; change:#value1:.
+	field2 model:model; aspect:#value2; change:#value2:.
+	field3 model:model; aspect:#value3; change:#value3:.
+
+	top delegate:group.
+	top openModal.
+
+	Transcript showCr:'value1: ' , value1.
+	Transcript showCr:'value2: ' , value2.
+	Transcript showCr:'value3: ' , value3.
+
+
+    the above is done automatically for you, if you add inputFields
+    to a dialogBox:
+
+	|box model
+	 value1 value2 value3|
+
+	box := DialogBox new.
+	box extent:200@200.
+
+	value1 := 'one'. value2 := 'two'. value3 := 'three'.
+
+	model := Plug new.
+	model respondTo:#value1 with:[value1].
+	model respondTo:#value1: with:[:arg | value1 := arg].
+	model respondTo:#value2 with:[value2].
+	model respondTo:#value2: with:[:arg | value2 := arg].
+	model respondTo:#value3 with:[value3].
+	model respondTo:#value3: with:[:arg | value3 := arg].
+
+	(box addInputFieldOn:model) aspect:#value1; change:#value1:.
+	box addVerticalSpace.
+	(box addInputFieldOn:model) aspect:#value2; change:#value2:.
+	box addVerticalSpace.
+	(box addInputFieldOn:model) aspect:#value3; change:#value3:.
+
+	box open.
+
+	Transcript showCr:'value1: ' , value1.
+	Transcript showCr:'value2: ' , value2.
+	Transcript showCr:'value3: ' , value3.
 "
 ! !
 
+!EnterFieldGroup class methodsFor:'instance creation'!
+
+new
+    ^ self basicNew wrap:false
+! !
+
 !EnterFieldGroup methodsFor:'adding / removing'!
 
 add:aField
-    |thisIndex next|
+    |thisIndex next action|
 
     fields isNil ifTrue:[
 	fields := OrderedCollection new
@@ -153,6 +357,8 @@
 	    currentField disable.
 	    currentField hideCursor.
 	].
+
+	action := key.
 	((key == #CursorUp) or:[key == #PreviousField]) ifTrue:[
 	    (thisIndex == 1) ifTrue:[
 		next := fields size
@@ -160,14 +366,20 @@
 		next := thisIndex - 1
 	    ]
 	].
-	((key == #CursorDown) or:[key == #NextField]) ifTrue:[
+	((key == #CursorDown) 
+	or:[key == #NextField
+	or:[key == #Tab]]) ifTrue:[
 	    (thisIndex == (fields size)) ifTrue:[
-		next := 1
+		wrap ifFalse:[
+		    action := #Return.
+		] ifTrue:[
+		    next := 1
+		].
 	    ] ifFalse:[
 		next := thisIndex + 1
 	    ]
 	].
-	(key == #Return) ifTrue:[
+	(action == #Return) ifTrue:[
 	    (thisIndex == (fields size)) ifTrue:[
 		leaveAction notNil ifTrue:[
 		    leaveAction value.
@@ -181,8 +393,6 @@
 	].
 	next notNil ifTrue:[
 	    self makeActive:(fields at:next) 
-"/            (fields at:next) enable.
-"/            currentField := fields at:next
 	]
     ].
 
@@ -194,6 +404,13 @@
 
 !EnterFieldGroup methodsFor:'accessing'!
 
+wrap:aBoolean
+    "specifies if leaveing the last field via non-Return
+     should wrap back to the first, or leave the group"
+
+    wrap := aBoolean
+!
+
 leaveAction:aBlock
     "set the action to perform when the last field is left.
      Usually, this is to accept the values of all fields and perform
@@ -259,15 +476,6 @@
     ]
 !
 
-keyPress:key x:x y:y
-    "key-press in an enclosing view (via delegation)
-     forward the key to the active field"
-
-    currentField notNil ifTrue:[
-	currentField keyPress:key x:-1 y:-1 
-    ]
-!
-
 buttonPress:button x:x y:y view:aView
     "clicking on a field activates it and forwards the click to it"
 
--- a/EditField.st	Sat May 06 16:18:13 1995 +0200
+++ b/EditField.st	Sun May 07 02:16:56 1995 +0200
@@ -13,8 +13,8 @@
 'From Smalltalk/X, Version:2.10.5 on 4-may-1995 at 8:46:55 am'!
 
 EditTextView subclass:#EditField
-	 instanceVariableNames:'leaveAction enabled enableAction alwaysAccept crAction tabAction
-		converter acceptAction leaveKeys'
+	 instanceVariableNames:'leaveAction enabled enableAction crAction tabAction
+		converter acceptAction leaveKeys alwaysAccept acceptOnLeave acceptOnReturn'
 	 classVariableNames:'DefaultForegroundColor DefaultBackgroundColor
 		DefaultSelectionForegroundColor DefaultSelectionBackgroundColor
 		DefaultFont'
@@ -26,7 +26,7 @@
 COPYRIGHT (c) 1990 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.19 1995-05-06 14:16:58 claus Exp $
+$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.20 1995-05-07 00:15:56 claus Exp $
 '!
 
 !EditField class methodsFor:'documentation'!
@@ -47,7 +47,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.19 1995-05-06 14:16:58 claus Exp $
+$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.20 1995-05-07 00:15:56 claus Exp $
 "
 !
 
@@ -71,10 +71,6 @@
       enabled        <Boolean>                  if false, input is ignored.
 
       enableAction   <Block | nil>
-      alwaysAccept   <Boolean>                  if true, every change of the text is immediately
-						forwardd to the model/acceptBlock.
-						Default is false i.e. only forward changes
-						on accept.
 
       crAction       <Block | nil>              if non-nil, keyboard input of a cr are not
 						handled specially, instead this block is evaluated
@@ -93,12 +89,28 @@
 						the leaveAction.
 
       leaveKeys      <Collection>               keys which are interpreted as 'leving the field'
+
+      alwaysAccept   <Boolean>                  if true, every change of the text is immediately
+						forwardd to the model/acceptBlock.
+						Default is false i.e. only forward changes
+						on accept.
+
+      acceptOnLeave  <Boolean>                  if true, leaving the field (via cursor keys)
+						automatically accepts the value into the model.
+						Default is false.
+
+      acceptOnReturn <Boolean>                  if true, leaving the field via return
+						automatically accepts the value into the model.
+						Default is true.
 "
 !
 
 examples 
 "
-    basic field:
+    see more examples in EnterFieldGroup>>examples.
+
+
+    basic field in a view:
 
 	|top field|
 
@@ -110,6 +122,21 @@
 
 	top open
 
+
+    forward input in topView to field:
+
+	|top field|
+
+	top := StandardSystemView new.
+	top extent:200@100.
+
+	field := EditField origin:0.0@0.0 in:top.
+	field width:1.0.        'let its height as-is'.
+
+	top delegate:(KeyboardForwarder toView:field).
+	top open
+
+
     just to make it look better: set some inset:
 
 	|top field|
@@ -124,6 +151,7 @@
 
 	top open
 
+
     give it an initial contents:
 
 	|top field|
@@ -139,6 +167,7 @@
 
 	top open
 
+
     and have it preselected:
 
 	|top field|
@@ -154,6 +183,7 @@
 
 	top open
 
+
     have part of it preselected:
 
 	|top field|
@@ -170,6 +200,7 @@
 
 	top open
 
+
     use a converter:
       - numbers:
 
@@ -207,6 +238,7 @@
 	field crAction:[field accept. top destroy].
 	top open.
 
+
     setting alwaysAccept, makes the field update with every key:
       - numbers:
 
@@ -227,6 +259,7 @@
 	field crAction:[field accept. top destroy].
 	top open.
 
+
     use a model:
     (see changing model value in inspector when return is pressed in the field)
 
@@ -246,6 +279,7 @@
 	top open.
 	model inspect.
 
+
     two views on the same model:
 
 	|top1 top2 field1 field2 model|
@@ -270,6 +304,7 @@
 	field2 model:model.
 	top2 open.
 
+
     just an example; a checkBox and an editField on the same model:
 
 	|top1 top2 field1 box model|
@@ -331,6 +366,8 @@
     nFullLinesShown := 1.
     nLinesShown := 1.
     alwaysAccept := false.
+    acceptOnLeave := false.
+    acceptOnReturn := true.
     leaveKeys := self class defaultLeaveKeys.
     cursorShown := true
 !
@@ -472,7 +509,9 @@
 
 contents:someText
     "set the contents from a string
-     - redefined to place the cursor to the end"
+     - redefined to place the cursor to the end.
+    In your application, please use #editValue:; 
+    it uses a converter (if any) and is compatible to ST-80."
 
     super contents:someText.
     self cursorCol:(someText size + 1).
@@ -480,7 +519,9 @@
 
 contents
     "return contents as a string
-     - redefined since EditFields hold only one line of text"
+     - redefined since EditFields hold only one line of text.
+    In your application, please use #editValue; 
+    it uses a converter (if any) and is compatible to ST-80."
 
     list isNil ifTrue:[^ ''].
     (list size == 0) ifTrue:[^ ''].
@@ -505,6 +546,14 @@
     leaveAction := aBlock
 !
 
+leaveKeys:aCollectionOfKeySymbols 
+    "define the set of keys which are interpreted as leaveKeys.
+     I.e. those that make the field inactive and accept (if acceptOnLeave is true).
+     The default is a set of #CursorUp, #CursorDown, #Next, #Prior and #Return."
+
+    leaveKeys := aCollectionOfKeySymbols
+!
+
 crAction:aBlock
     "define an action to be evaluated when the return key is pressed."
 
@@ -524,11 +573,23 @@
 !
 
 alwaysAccept:aBoolean
-    "set/clear the alwaysAccept flag"
+    "set/clear the alwaysAccept flag. The default is false."
 
      alwaysAccept := aBoolean
 !
 
+acceptOnReturn:aBoolean
+    "set/clear the acceptOnReturn flag. The default is true."
+
+     acceptOnReturn := aBoolean
+!
+
+acceptOnLeave:aBoolean
+    "set/clear the acceptOnLeave flag. The default is false."
+
+     acceptOnLeave := aBoolean
+!
+
 converter
     "return the converter (if any)."
 
@@ -715,7 +776,11 @@
 	    leaveAction value:key
 	].
 
-	self accept.
+	((key == #Return and:[acceptOnReturn])
+	or:[key ~~ #Return and:[acceptOnLeave]]) ifTrue:[
+	    self accept.
+	].
+
 	x >= 0 ifTrue:[
 	    "
 	     let superview know about the leave ...
--- a/EnterBox.st	Sat May 06 16:18:13 1995 +0200
+++ b/EnterBox.st	Sun May 07 02:16:56 1995 +0200
@@ -37,7 +37,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/EnterBox.st,v 1.22 1995-05-06 14:17:02 claus Exp $
+$Header: /cvs/stx/stx/libwidg/EnterBox.st,v 1.23 1995-05-07 00:16:00 claus Exp $
 "
 !
 
@@ -300,7 +300,7 @@
     "
      forward keyboard input to the enterfield
     "
-    self delegate:(KeyboardForwarder to:enterField condition:#noFocus).
+    self delegate:(KeyboardForwarder toView:enterField condition:#noFocus).
     enterField hasKeyboardFocus:true.
 !
 
--- a/EnterFieldGroup.st	Sat May 06 16:18:13 1995 +0200
+++ b/EnterFieldGroup.st	Sun May 07 02:16:56 1995 +0200
@@ -11,7 +11,8 @@
 "
 
 Object subclass:#EnterFieldGroup
-	 instanceVariableNames:'fields currentField leaveAction'
+	 instanceVariableNames:'fields currentField leaveAction
+				wrap'
 	 classVariableNames:''
 	 poolDictionaries:''
 	 category:'Views-Support'
@@ -21,7 +22,7 @@
 COPYRIGHT (c) 1992 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/EnterFieldGroup.st,v 1.8 1995-05-06 14:16:40 claus Exp $
+$Header: /cvs/stx/stx/libwidg/EnterFieldGroup.st,v 1.9 1995-05-07 00:15:50 claus Exp $
 '!
 
 !EnterFieldGroup class methodsFor:'documentation'!
@@ -42,7 +43,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/EnterFieldGroup.st,v 1.8 1995-05-06 14:16:40 claus Exp $
+$Header: /cvs/stx/stx/libwidg/EnterFieldGroup.st,v 1.9 1995-05-07 00:15:50 claus Exp $
 "
 !
 
@@ -58,12 +59,38 @@
     field of the group is left (by cursor-down or cr). 
     Usually this block triggers accept on the fields and/or performs some
     followup processing and closes  the topview (for example: in a dialog).
+
+    EnterFieldGroups can be used as a delegate (of the topView) to forward
+    input (entered into the topView) to the currently active field.
+
+    Stepping to previous field is via CursorUp/PreviousField,
+    to next field via CursorDown/NextField/Tab.
+    Notice, that by default, the editField takes the tab-character as
+    a normal character. To step using tab, you have to add the Tab key to the
+    fields leaveKeys.
+
+    Instance variables:
+
+	fields          <Collection of EditField>       the fields of the group
+
+	currentField    <EditField>                     the active field
+
+	leaveAction     <nil|Block>                     action to perform, when the
+							last field is left by a non-wrap
+
+	wrap            <Boolean>                       if true, non-return next-keys wrap
+							back to the first field.
+							If false (the default), next in
+							the last field is taken as return.
+							This is ignored, if no leaveAction was 
+							defined.
 "
 !
 
 examples 
 "
-    without a group - user has to click on next field to activate it:
+    without a group - user has to enter mouse into the next field to activate it;
+    Cursor-keys dont work:
 
 	|top panel field1 field2 field3|
 
@@ -80,6 +107,8 @@
 
 
     with a group - Return-key or CursorKey enables next field:
+    (but still, mouse pointer has to be moved into any of the fields,
+     because the topView does not forward its input into the fields)
 
 	|top panel group field1 field2 field3|
 
@@ -99,7 +128,74 @@
 
 
 
-    with a group - close the box when the last field is left:
+    same, enables tabbing via the Tab key:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+
+	field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	top open
+
+
+
+    with a group - Return-key or CursorKey enables next field:
+    input into topView is forwarded to the group:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+
+	top delegate:group.
+	top open
+
+
+
+    as above, but close the box when the last field is left:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+	group leaveAction:[top destroy].
+
+	top delegate:group.
+	top open
+
+
+
+    same as above, with Tab-key stepping:
 
 	|top panel group field1 field2 field3|
 
@@ -116,14 +212,122 @@
 	group add:field1; add:field2; add:field3.
 	group leaveAction:[top destroy].
 
+	field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+	field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+
+	top delegate:group.
 	top open
+
+
+
+    the next example shows that the input order is defined by the
+    order in the group; NOT by the physical layout of the fields in the superview:
+
+	|top panel group field1 field2 field3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field3; add:field2; add:field1.
+	group leaveAction:[top destroy].
+
+	top delegate:group.
+	top open
+
+
+
+    using a single model for all fields:
+    (here, we use a Plug to simulate a more complex model):
+
+	|top panel group field1 field2 field3 model
+	 value1 value2 value3|
+
+	top := StandardSystemView new.
+	top extent:200@200.
+
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+
+	panel add:(field1 := EditField extent:(1.0 @ nil)).
+	panel add:(field2 := EditField extent:(1.0 @ nil)).
+	panel add:(field3 := EditField extent:(1.0 @ nil)).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+	group leaveAction:[top destroy].
+
+	value1 := 'one'. value2 := 'two'. value3 := 'three'.
+
+	model := Plug new.
+	model respondTo:#value1 with:[value1].
+	model respondTo:#value1: with:[:arg | value1 := arg].
+	model respondTo:#value2 with:[value2].
+	model respondTo:#value2: with:[:arg | value2 := arg].
+	model respondTo:#value3 with:[value3].
+	model respondTo:#value3: with:[:arg | value3 := arg].
+
+	field1 model:model; aspect:#value1; change:#value1:.
+	field2 model:model; aspect:#value2; change:#value2:.
+	field3 model:model; aspect:#value3; change:#value3:.
+
+	top delegate:group.
+	top openModal.
+
+	Transcript showCr:'value1: ' , value1.
+	Transcript showCr:'value2: ' , value2.
+	Transcript showCr:'value3: ' , value3.
+
+
+    the above is done automatically for you, if you add inputFields
+    to a dialogBox:
+
+	|box model
+	 value1 value2 value3|
+
+	box := DialogBox new.
+	box extent:200@200.
+
+	value1 := 'one'. value2 := 'two'. value3 := 'three'.
+
+	model := Plug new.
+	model respondTo:#value1 with:[value1].
+	model respondTo:#value1: with:[:arg | value1 := arg].
+	model respondTo:#value2 with:[value2].
+	model respondTo:#value2: with:[:arg | value2 := arg].
+	model respondTo:#value3 with:[value3].
+	model respondTo:#value3: with:[:arg | value3 := arg].
+
+	(box addInputFieldOn:model) aspect:#value1; change:#value1:.
+	box addVerticalSpace.
+	(box addInputFieldOn:model) aspect:#value2; change:#value2:.
+	box addVerticalSpace.
+	(box addInputFieldOn:model) aspect:#value3; change:#value3:.
+
+	box open.
+
+	Transcript showCr:'value1: ' , value1.
+	Transcript showCr:'value2: ' , value2.
+	Transcript showCr:'value3: ' , value3.
 "
 ! !
 
+!EnterFieldGroup class methodsFor:'instance creation'!
+
+new
+    ^ self basicNew wrap:false
+! !
+
 !EnterFieldGroup methodsFor:'adding / removing'!
 
 add:aField
-    |thisIndex next|
+    |thisIndex next action|
 
     fields isNil ifTrue:[
 	fields := OrderedCollection new
@@ -153,6 +357,8 @@
 	    currentField disable.
 	    currentField hideCursor.
 	].
+
+	action := key.
 	((key == #CursorUp) or:[key == #PreviousField]) ifTrue:[
 	    (thisIndex == 1) ifTrue:[
 		next := fields size
@@ -160,14 +366,20 @@
 		next := thisIndex - 1
 	    ]
 	].
-	((key == #CursorDown) or:[key == #NextField]) ifTrue:[
+	((key == #CursorDown) 
+	or:[key == #NextField
+	or:[key == #Tab]]) ifTrue:[
 	    (thisIndex == (fields size)) ifTrue:[
-		next := 1
+		wrap ifFalse:[
+		    action := #Return.
+		] ifTrue:[
+		    next := 1
+		].
 	    ] ifFalse:[
 		next := thisIndex + 1
 	    ]
 	].
-	(key == #Return) ifTrue:[
+	(action == #Return) ifTrue:[
 	    (thisIndex == (fields size)) ifTrue:[
 		leaveAction notNil ifTrue:[
 		    leaveAction value.
@@ -181,8 +393,6 @@
 	].
 	next notNil ifTrue:[
 	    self makeActive:(fields at:next) 
-"/            (fields at:next) enable.
-"/            currentField := fields at:next
 	]
     ].
 
@@ -194,6 +404,13 @@
 
 !EnterFieldGroup methodsFor:'accessing'!
 
+wrap:aBoolean
+    "specifies if leaveing the last field via non-Return
+     should wrap back to the first, or leave the group"
+
+    wrap := aBoolean
+!
+
 leaveAction:aBlock
     "set the action to perform when the last field is left.
      Usually, this is to accept the values of all fields and perform
@@ -259,15 +476,6 @@
     ]
 !
 
-keyPress:key x:x y:y
-    "key-press in an enclosing view (via delegation)
-     forward the key to the active field"
-
-    currentField notNil ifTrue:[
-	currentField keyPress:key x:-1 y:-1 
-    ]
-!
-
 buttonPress:button x:x y:y view:aView
     "clicking on a field activates it and forwards the click to it"
 
--- a/LSelBox.st	Sat May 06 16:18:13 1995 +0200
+++ b/LSelBox.st	Sun May 07 02:16:56 1995 +0200
@@ -21,7 +21,7 @@
 COPYRIGHT (c) 1990 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/Attic/LSelBox.st,v 1.10 1995-05-03 00:29:49 claus Exp $
+$Header: /cvs/stx/stx/libwidg/Attic/LSelBox.st,v 1.11 1995-05-07 00:16:17 claus Exp $
 '!
 
 !ListSelectionBox class methodsFor:'documentation'!
@@ -42,7 +42,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/Attic/LSelBox.st,v 1.10 1995-05-03 00:29:49 claus Exp $
+$Header: /cvs/stx/stx/libwidg/Attic/LSelBox.st,v 1.11 1995-05-07 00:16:17 claus Exp $
 "
 !
 
@@ -166,7 +166,7 @@
      mhm: the lists keyboard functions are disabled,
      and input passed to the enterfield
     "
-    selectionList delegate:(KeyboardForwarder to:enterField condition:#noFocus) 
+    selectionList delegate:(KeyboardForwarder toView:enterField condition:#noFocus) 
 !
 
 updateList
--- a/ListSelectionBox.st	Sat May 06 16:18:13 1995 +0200
+++ b/ListSelectionBox.st	Sun May 07 02:16:56 1995 +0200
@@ -21,7 +21,7 @@
 COPYRIGHT (c) 1990 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/ListSelectionBox.st,v 1.10 1995-05-03 00:29:49 claus Exp $
+$Header: /cvs/stx/stx/libwidg/ListSelectionBox.st,v 1.11 1995-05-07 00:16:17 claus Exp $
 '!
 
 !ListSelectionBox class methodsFor:'documentation'!
@@ -42,7 +42,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/ListSelectionBox.st,v 1.10 1995-05-03 00:29:49 claus Exp $
+$Header: /cvs/stx/stx/libwidg/ListSelectionBox.st,v 1.11 1995-05-07 00:16:17 claus Exp $
 "
 !
 
@@ -166,7 +166,7 @@
      mhm: the lists keyboard functions are disabled,
      and input passed to the enterfield
     "
-    selectionList delegate:(KeyboardForwarder to:enterField condition:#noFocus) 
+    selectionList delegate:(KeyboardForwarder toView:enterField condition:#noFocus) 
 !
 
 updateList
--- a/Make.proto	Sat May 06 16:18:13 1995 +0200
+++ b/Make.proto	Sun May 07 02:16:56 1995 +0200
@@ -1,4 +1,4 @@
-# $Header: /cvs/stx/stx/libwidg/Make.proto,v 1.18 1995-05-03 00:39:07 claus Exp $
+# $Header: /cvs/stx/stx/libwidg/Make.proto,v 1.19 1995-05-07 00:16:56 claus Exp $
 #
 # -------------- no need to change anything below ----------
 
@@ -145,8 +145,8 @@
 BUTTON=$(I)/Button.H $(LABEL)
 CONTROLLER=$(I)/Controll.H $(OBJECT)
 
-RButtGrp.$(O):          RButtGrp.st $(I)/VarArray.H $(OBJECT)
-EFGroup.$(O):           EFGroup.st $(I)/VarArray.H $(OBJECT)
+RButtGrp.$(O):          RButtGrp.st $(I)/OrdColl.H $(OBJECT)
+EFGroup.$(O):           EFGroup.st $(OBJECT)
 
 DialogBox.$(O):         DialogBox.st $(MODALBOX)
 InfoBox.$(O):           InfoBox.st $(DIALOGBOX)
--- a/ScrView.st	Sat May 06 16:18:13 1995 +0200
+++ b/ScrView.st	Sun May 07 02:16:56 1995 +0200
@@ -22,7 +22,7 @@
 COPYRIGHT (c) 1989 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/Attic/ScrView.st,v 1.15 1995-05-03 00:37:26 claus Exp $
+$Header: /cvs/stx/stx/libwidg/Attic/ScrView.st,v 1.16 1995-05-07 00:16:36 claus Exp $
 '!
 
 !ScrollableView class methodsFor:'documentation'!
@@ -43,7 +43,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/Attic/ScrView.st,v 1.15 1995-05-03 00:37:26 claus Exp $
+$Header: /cvs/stx/stx/libwidg/Attic/ScrView.st,v 1.16 1995-05-07 00:16:36 claus Exp $
 "
 !
 
@@ -511,7 +511,7 @@
 	 pass my keyboard input (and other subviews input) 
 	 to the scrolled view ...
 	"
-	self delegate:(KeyboardForwarder to:scrolledView).
+	self delegate:(KeyboardForwarder toView:scrolledView).
     ]
 !
 
@@ -663,7 +663,7 @@
      pass my keyboard input (and other subviews input) 
      to the scrolled view ...
     "
-    self delegate:(KeyboardForwarder to:scrolledView).
+    self delegate:(KeyboardForwarder toView:scrolledView).
 
     realized ifTrue:[
 	self sizeChanged:nil.
--- a/ScrollableView.st	Sat May 06 16:18:13 1995 +0200
+++ b/ScrollableView.st	Sun May 07 02:16:56 1995 +0200
@@ -22,7 +22,7 @@
 COPYRIGHT (c) 1989 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/ScrollableView.st,v 1.15 1995-05-03 00:37:26 claus Exp $
+$Header: /cvs/stx/stx/libwidg/ScrollableView.st,v 1.16 1995-05-07 00:16:36 claus Exp $
 '!
 
 !ScrollableView class methodsFor:'documentation'!
@@ -43,7 +43,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/ScrollableView.st,v 1.15 1995-05-03 00:37:26 claus Exp $
+$Header: /cvs/stx/stx/libwidg/ScrollableView.st,v 1.16 1995-05-07 00:16:36 claus Exp $
 "
 !
 
@@ -511,7 +511,7 @@
 	 pass my keyboard input (and other subviews input) 
 	 to the scrolled view ...
 	"
-	self delegate:(KeyboardForwarder to:scrolledView).
+	self delegate:(KeyboardForwarder toView:scrolledView).
     ]
 !
 
@@ -663,7 +663,7 @@
      pass my keyboard input (and other subviews input) 
      to the scrolled view ...
     "
-    self delegate:(KeyboardForwarder to:scrolledView).
+    self delegate:(KeyboardForwarder toView:scrolledView).
 
     realized ifTrue:[
 	self sizeChanged:nil.