innerWidth:/innerHeight support; much more docu in editField
authorClaus Gittinger <cg@exept.de>
Tue, 16 Jan 1996 20:07:57 +0100
changeset 290 f539121393b1
parent 289 82d20a3e2fe8
child 291 71f4a66b3281
innerWidth:/innerHeight support; much more docu in editField
EditField.st
ListView.st
--- a/EditField.st	Tue Jan 16 03:04:32 1996 +0100
+++ b/EditField.st	Tue Jan 16 20:07:57 1996 +0100
@@ -14,7 +14,7 @@
 	instanceVariableNames:'leaveAction enabled enableAction crAction tabAction converter
 		leaveKeys immediateAccept acceptOnLeave acceptOnReturn
 		lengthLimit entryCompletionBlock passwordCharacter
-		cursorMovementWhenUpdating enableChannel'
+		cursorMovementWhenUpdating enableChannel autoScrollHorizontally'
 	classVariableNames:'DefaultForegroundColor DefaultBackgroundColor
 		DefaultSelectionForegroundColor DefaultSelectionBackgroundColor
 		DefaultFont'
@@ -44,6 +44,56 @@
     and forcing its size to 1 line - disabling cursor movement
     in the vertical direction.
 
+    Basically, an editField is an editor for a single line text,
+    and provides the usual access protocol as defined in its superClasses
+    (especially: #contents / #contents:).
+
+    The above underlying internal mechanism can be used for fields which
+    are passive; i.e. into which text can be entered and the value (string)
+    is extracted actively by someone else.
+
+  accepting:
+    The opposite way to use editFields is to connect them to a model
+    and let the field notify changes to it.
+    This notification is called ``accepting''.
+    Unless accepted, the models value is not updated from the editFields contents
+    this default is the normal operation and way things should work, since most
+    uses of editFields are not interrested in every individual change
+    (i.e. getting each keyStroke when a long number is entered).
+    The default behavior is to ``accept'' when either return or a cursorUp/Down
+    key is pressed in a field.
+    However, the field can setup to accept/not accept on leave, on return
+    or on each individual key input.
+    See the methods #acceptOnLeave: / #acceptOnReturn: / #immediateAccept.
+
+    In addition, the set of keys which are considered ``leaveKeys'' can be
+    specified by #leaveKeys: (in case you need keys other than Return, CursorUp/Down).
+
+  models value vs. field contents:
+    Although the field internally keeps its contents as some string object,
+    the application may prefer to think of numbers, floats, yes/no values etc.
+    To support this, a converter may defined, which is responsible for conversion of
+    strings to/from the models domain value.
+    If present (i.e. nonNil), the converter is asked to convert a string to the models
+    domain with #readValueFrom:aString and vice versa, a value to a string by #printStringFor:.
+    The PrintConverter class already provides a number of standard conversions, see the examples.
+    To access a converted value directly (i.e. not via the model), use #editValue.
+
+  grouping:
+    Individual fields do not know about being included in a group. This must be arranged on the
+    outside, by placing multiple fields into an EnterFieldGroup.
+    This groupObject keeps a reference to one active field, and forwards input from any other
+    field to the active one. Also have a look at the examples for this.
+
+  input completion:
+    To support input completion (i.e. filename completion, classname completion etc.),
+    a completionBlock can be defined which (if non-nil) is evaluated when the completion-key
+    is pressed and its value is taken as the new field-contents. 
+    The physical completion-key is the Tab key (this one cannot be defined by
+    the keyboardTranslation mechanism, since that would disable the Tab-key on regular text views.
+
+
+
     Instance variables:
 
       leaveAction    <Block | nil>              if non-nil, this is evaluated with
@@ -66,13 +116,14 @@
 
       tabAction      <Block | nil>              if non-nil, keyboard input of a tab character
 						is not entered into the text, instead this block
-						is evaluated.
+						is evaluated. Also, no input completion is performed if
+						tabAction is nonNil.
 
       converter      <PrintConverter | nil>     if non-nil, this is supposed to convert between
-						the object and its printed representation.
+						the object and its printed representation and vice versa.
 						Defaults to nil i.e. assume that strings are edited.
 
-      leaveKeys      <Collection>               keys which are interpreted as 'leving the field'
+      leaveKeys      <Collection>               keys which are interpreted as 'leaving the field'
 
       immediateAccept   <Boolean>               if true, every change of the text is immediately
 						forwarded to the model/acceptBlock. If false,
@@ -95,348 +146,401 @@
     see more examples in EnterFieldGroup>>examples.
 
 
-    basic field in a view:
+    Step-by-step introduction:
+
 
-        |top field|
+    basic field in some view:
+
+	|top field|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	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'.
+	field := EditField origin:0.0@0.0 in:top.
+	field width:1.0.                                'let its height as-is'.
 
-        top open
+	top open
 
 
     forward input in topView to the field:
     (currently, the field does not know this - therefore,
      its been told here ... this may change)
 
-        |top field|
+	|top field|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	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'.
+	field := EditField origin:0.0@0.0 in:top.
+	field width:1.0.                                'let its height as-is'.
 
-        top delegate:(KeyboardForwarder toView:field).
-        field hasKeyboardFocus:true.
-        top open
+	top delegate:(KeyboardForwarder toView:field).
+	field hasKeyboardFocus:true.
+	top open
 
 
     to make it look better: set some inset:
 
-        |top field|
+	|top field spacing|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.        'let its height as-is'.
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
+	spacing := View viewSpacing.
+	field := EditField origin:(0.0 @ spacing) in:top.
+	field width:1.0.                                        'let its height as-is'.
+	field leftInset:spacing; rightInset:spacing.
 
-        top open
+	top open
 
 
     give it an initial contents:
 
-        |top field|
+	|top field|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.       
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field editValue:'hello world'.
+	field := EditField origin:(0.0 @ 0@0) in:top.
+	field width:1.0.       
 
-        top open
+	field editValue:'hello world'.
+
+	top open
 
 
     have it preselected:
 
-        |top field|
+	|top field|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.     
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field editValue:'hello world' selected:true.
+	field := EditField origin:(0.0 @ 0.0) in:top.
+	field width:1.0.     
+	field editValue:'hello world' selected:true.
 
-        top open
+	top open
 
 
     have part of it preselected:
 
-        |top field|
+	|top field|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.     
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field editValue:'hello world';
-              selectFromCharacterPosition:1 to:5.
+	field := EditField origin:(0.0 @ 0.0) in:top.
+	field width:1.0.     
 
-        top open
+	field editValue:'hello world'.
+	field selectFromCharacterPosition:1 to:5.
+
+	top open
 
 
     set a size limit:
 
-        |top field|
+	|top field|
+
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	field := EditField origin:(0.0 @ 0.0) in:top.
+	field width:1.0.     
+	field editValue:'hello'.
+
+	field maxChars:8.
+
+	top open
+
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.     
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field editValue:'hello';
-              maxChars:8.
+    set a size limit, initial width and stop it from scrolling
+    notice: you may prefer a constant-pitch font (such as courier):
+
+	|top field|
+
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        top open
+	field := EditField origin:(0.0 @ 0.0) in:top.
+	field innerWidth:(field font widthOf:'00000000').     
+	field editValue:'12345678'.
+
+	field maxChars:8.
+	field autoScroll:false.
+
+	top open
 
 
     enable / disable:
 
-        |top panel check field ena|
+	|top panel check field ena|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
-        panel horizontalLayout:#leftSpace.
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+	panel horizontalLayout:#leftSpace.
 
-        check := CheckBox label:'enable' in:panel.
-        check turnOn.
-        check action:[:onOff | onOff ifTrue:[field enable] ifFalse:[field disable]].
+	check := CheckBox label:'enable' in:panel.
+	check turnOn.
+	check action:[:onOff | onOff ifTrue:[field enable] ifFalse:[field disable]].
 
-        panel add:(View new height:30).
+	panel add:(View new height:30).
 
-        field := EditField in:panel.
-        field width:1.0.     
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field editValue:'hello'.
+	field := EditField in:panel.
+	field width:1.0.     
+	field editValue:'hello'.
         
-        top open
+	top open
 
 
     enable / disable using a channel:
 
-        |top panel check field ena|
+	|top panel check field ena|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
-        panel horizontalLayout:#leftSpace.
+	panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+	panel horizontalLayout:#leftSpace.
 
-        ena := true asValue.
+	ena := true asValue.
 
-        check := CheckBox label:'enable' in:panel.
-        check model:ena.
+	check := CheckBox label:'enable' in:panel.
+	check model:ena.
 
-        panel add:(View new height:30).
+	panel add:(View new height:30).
 
-        field := EditField in:panel.
-        field enableChannel:ena.
-        field width:1.0.     
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field editValue:'hello'.
+	field := EditField in:panel.
+	field enableChannel:ena.
+	field width:1.0.     
+	field editValue:'hello'.
 
-        top open
+	top open
 
 
     use a converter:
       - numbers (default to 0):
 
-        |top field|
+	|top field|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
+	field := EditField origin:0.0@ViewSpacing in:top.
+	field width:1.0.
+	field leftInset:ViewSpacing;
+	      rightInset:ViewSpacing.
 
-        field converter:(PrintConverter new initForNumber).
-        field editValue:1234.
-        field acceptAction:[:value | Transcript showCr:value].
-        field crAction:[field accept. top destroy].
-        top open.
+	field converter:(PrintConverter new initForNumber).
+	field editValue:1234.
+	field acceptAction:[:value | Transcript showCr:value].
+	field crAction:[field accept. top destroy].
+	top open.
 
       - dates:
 
-        |top field|
+	|top field|
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
+	field := EditField origin:0.0@ViewSpacing in:top.
+	field width:1.0.
+	field leftInset:ViewSpacing;
+	      rightInset:ViewSpacing.
 
-        field converter:(PrintConverter new initForDate).
-        field editValue:Date today.
-        field acceptAction:[:value | Transcript showCr:value class name , ' ' , value printString].
-        field crAction:[field accept. top destroy].
-        top open.
+	field converter:(PrintConverter new initForDate).
+	field editValue:Date today.
+	field acceptAction:[:value | Transcript showCr:value class name , ' ' , value printString].
+	field crAction:[field accept. top destroy].
+	top open.
 
 
     setting immediateAccept, makes the field update with every key:
 
       - immediate accept numbers, defaulting to nil:
 
-        |top field|
+	|top field|
+
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	field := EditField origin:0.0@ViewSpacing in:top.
+	field width:1.0.
+	field leftInset:ViewSpacing;
+	      rightInset:ViewSpacing.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
+	field converter:(PrintConverter new initForNumberOrNil).
+	field immediateAccept:true.
+	field editValue:1234.
+	field acceptAction:[:value | Transcript showCr:value].
+	field crAction:[field accept. top destroy].
+	top open.
 
-        field converter:(PrintConverter new initForNumberOrNil).
-        field immediateAccept:true.
-        field editValue:1234.
-        field acceptAction:[:value | Transcript showCr:value].
-        field crAction:[field accept. top destroy].
-        top open.
+
+
+    grouping multiple fields, and forward keyPres from the outer view to the active field
+    (i.e. actually: to the group):
+
+	|top field1 field2 field3 group|
 
 
+	top := StandardSystemView new.
+	top extent:200@100.
+
+	field1 := EditField origin:(0.0 @ 0.0) in:top.
+	field1 width:1.0.
+
+	field2 := EditField origin:(0.0 @ 0.0) in:top.
+	field2 width:0.5.
+	field2 topInset:(field1 height); bottomInset:(field1 height negated).
+
+	field3 := EditField origin:(0.5 @ 0.0) in:top.
+	field3 width:0.5.
+	field3 topInset:(field1 height); bottomInset:(field1 height negated).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+
+	top delegate:(KeyboardForwarder to:group).
+
+	top open.
+
+        
+    in addition: tell the group to close when the last field is left:
+
+	|top field1 field2 field3 group|
+
+
+	top := StandardSystemView new.
+	top extent:200@100.
+
+	field1 := EditField origin:(0.0 @ 0.0) in:top.
+	field1 width:1.0.
+
+	field2 := EditField origin:(0.0 @ 0.0) in:top.
+	field2 width:0.5.
+	field2 topInset:(field1 height); bottomInset:(field1 height negated).
+
+	field3 := EditField origin:(0.5 @ 0.0) in:top.
+	field3 width:0.5.
+	field3 topInset:(field1 height); bottomInset:(field1 height negated).
+
+	group := EnterFieldGroup new.
+	group add:field1; add:field2; add:field3.
+	group leaveAction:[top destroy].
+
+	top delegate:(KeyboardForwarder to:group).
+
+	top open.
 
 
     use a model:
     (see changing model value in inspector when return is pressed in the field)
 
-        |top field model|
+	|top field model|
 
-        model := 'hello world' asValue.
+	model := 'hello world' asValue.
 
-        top := StandardSystemView new.
-        top extent:200@100.
+	top := StandardSystemView new.
+	top extent:200@100.
 
-        field := EditField origin:0.0@ViewSpacing in:top.
-        field width:1.0.
-        field leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field model:model.
-        field acceptOnReturn:true.
+	field := EditField origin:(0.0 @ 0.0) in:top.
+	field width:1.0.
+	field model:model.
+	field acceptOnReturn:true.
 
-        top open.
-        model inspect.
+	top open.
+	model inspect.
 
 
     two views on the same model (each accepts on return):
 
-        |top1 top2 field1 field2 model|
+	|top1 top2 field1 field2 model|
 
-        model := 'hello world' asValue.
+	model := 'hello world' asValue.
 
-        top1 := StandardSystemView new.
-        top1 extent:200@100.
-        field1 := EditField origin:0.0@ViewSpacing in:top1.
-        field1 width:1.0.
-        field1 leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field1 model:model.
-        field1 acceptOnReturn:true.
-        top1 open.
+	top1 := StandardSystemView new.
+	top1 extent:200@100.
+	field1 := EditField origin:(0.0 @ 0.0) in:top1.
+	field1 width:1.0.
+	field1 model:model.
+	field1 acceptOnReturn:true.
+	top1 open.
 
-        top2 := StandardSystemView new.
-        top2 extent:200@100.
-        field2 := EditField origin:0.0@ViewSpacing in:top2.
-        field2 width:1.0.
-        field2 leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field2 model:model.
-        field2 acceptOnReturn:true.
-        top2 open.
+	top2 := StandardSystemView new.
+	top2 extent:200@100.
+	field2 := EditField origin:(0.0 @ 0.0) in:top2.
+	field2 width:1.0.
+	field2 model:model.
+	field2 acceptOnReturn:true.
+	top2 open.
 
     two views on the same model (no accept on return):
 
-        |top1 top2 field1 field2 model|
+	|top1 top2 field1 field2 model|
 
-        model := 'hello world' asValue.
+	model := 'hello world' asValue.
 
-        top1 := StandardSystemView new.
-        top1 extent:200@100.
-        field1 := EditField origin:0.0@ViewSpacing in:top1.
-        field1 width:1.0.
-        field1 leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field1 model:model; acceptOnReturn:false.
-        top1 open.
+	top1 := StandardSystemView new.
+	top1 extent:200@100.
+	field1 := EditField origin:(0.0 @ 0.0) in:top1.
+	field1 width:1.0.
+	field1 model:model; acceptOnReturn:false.
+	top1 open.
 
-        top2 := StandardSystemView new.
-        top2 extent:200@100.
-        field2 := EditField origin:0.0@ViewSpacing in:top2.
-        field2 width:1.0.
-        field2 leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field2 model:model; acceptOnReturn:false.
-        top2 open.
+	top2 := StandardSystemView new.
+	top2 extent:200@100.
+	field2 := EditField origin:(0.0 @ 0.0) in:top2.
+	field2 width:1.0.
+	field2 model:model; acceptOnReturn:false.
+	top2 open.
 
-    with immediate accept:
+    with immediate accept (every key updates the model):
 
-        |top1 top2 field1 field2 model|
+	|top1 top2 field1 field2 model|
 
-        model := 'hello world' asValue.
+	model := 'hello world' asValue.
 
-        top1 := StandardSystemView new.
-        top1 extent:200@100.
-        field1 := EditField origin:0.0@ViewSpacing in:top1.
-        field1 width:1.0.
-        field1 leftInset:ViewSpacing; rightInset:ViewSpacing.
-        field1 model:model; immediateAccept:true.
-        top1 open.
+	top1 := StandardSystemView new.
+	top1 extent:200@100.
+	field1 := EditField origin:(0.0 @ 0.0) in:top1.
+	field1 width:1.0.
+	field1 model:model; immediateAccept:true.
+	top1 open.
 
-        top2 := StandardSystemView new.
-        top2 extent:200@100.
-        field2 := EditField origin:0.0@ViewSpacing in:top2.
-        field2 width:1.0.
-        field2 leftInset:ViewSpacing; rightInset:ViewSpacing.
-        field2 model:model; immediateAccept:true.
-        top2 open.
+	top2 := StandardSystemView new.
+	top2 extent:200@100.
+	field2 := EditField origin:(0.0 @ 0.0) in:top2.
+	field2 width:1.0.
+	field2 model:model; immediateAccept:true.
+	top2 open.
 
     just an example; a checkBox and an editField on the same model:
 
-        |top1 top2 field1 box model|
+	|top1 top2 field1 box model|
 
-        model := false asValue.
+	model := false asValue.
 
-        top1 := StandardSystemView new.
-        top1 extent:200@100.
-        field1 := EditField origin:0.0@ViewSpacing in:top1.
-        field1 width:1.0.
-        field1 leftInset:ViewSpacing;
-              rightInset:ViewSpacing.
-        field1 converter:(PrintConverter new initForYesNo).
-        field1 model:model.
-        top1 open.
+	top1 := StandardSystemView new.
+	top1 extent:200@100.
+	field1 := EditField origin:(0.0 @ 0.0) in:top1.
+	field1 width:1.0.
+	field1 converter:(PrintConverter new initForYesNo).
+	field1 model:model.
+	top1 open.
 
-        top2 := StandardSystemView new.
-        top2 extent:200@100.
-        box := CheckBox on:model.
-        box label:'on/off'.
-        top2 add:box.
-        top2 open.
+	top2 := StandardSystemView new.
+	top2 extent:200@100.
+	box := CheckBox on:model.
+	box label:'on/off'.
+	top2 add:box.
+	top2 open.
 
-        model inspect.
+	model inspect.
 
 
     connecting fields:
@@ -445,81 +549,81 @@
      class, or in a complex model. For the demonstration below, we use
      a Plug to simulate the protocol.)
 
-        |application top field1 field2 value1 value2|
+	|application top field1 field2 value1 value2|
 
-        application := Plug new.
-        application respondTo:#value1Changed
-                         with:[value2 value:(value1 value isNil ifTrue:[nil]
-                                                                ifFalse:[value1 value squared])].
+	application := Plug new.
+	application respondTo:#value1Changed
+			 with:[value2 value:(value1 value isNil ifTrue:[nil]
+								ifFalse:[value1 value squared])].
 
-        value1 := 1 asValue.
-        value2 := 1 asValue.
+	value1 := 1 asValue.
+	value2 := 1 asValue.
 
-        top := Dialog new.
-        top extent:200@200.
+	top := Dialog new.
+	top extent:200@200.
 
-        (top addTextLabel:'some number:') layout:#left.
-        top addVerticalSpace.
+	(top addTextLabel:'some number:') layout:#left.
+	top addVerticalSpace.
 
-        (top addInputFieldOn:value1 tabable:false) 
-            converter:(PrintConverter new initForNumberOrNil);
-            immediateAccept:true.
-        top addVerticalSpace.
+	(top addInputFieldOn:value1 tabable:false) 
+	    converter:(PrintConverter new initForNumberOrNil);
+	    immediateAccept:true.
+	top addVerticalSpace.
 
-        (top addTextLabel:'squared:') layout:#left.
-        top addVerticalSpace.
-        (top addInputFieldOn:value2 tabable:false) 
-            converter:(PrintConverter new initForNumberOrNil).
+	(top addTextLabel:'squared:') layout:#left.
+	top addVerticalSpace.
+	(top addInputFieldOn:value2 tabable:false) 
+	    converter:(PrintConverter new initForNumberOrNil).
 
-        value1 onChangeSend:#value1Changed to:application.
+	value1 onChangeSend:#value1Changed to:application.
 
-        top openModeless.
+	top openModeless.
 
 
     two-way connect:
     each field updates the other (notice, that we have to turn off
     onChange: notification, to avoid an endless notification cycle)
 
-        |application top field1 field2 value1 value2|
+	|application top field1 field2 value1 value2|
 
-        application := Plug new.
-        application respondTo:#value1Changed
-                         with:[value2 retractInterestsFor:application.
-                               value2 value:(value1 value isNil ifTrue:[nil]
-                                                                ifFalse:[value1 value squared]).
-                               value2 onChangeSend:#value2Changed to:application.
-                              ].
-        application respondTo:#value2Changed
-                         with:[value1 retractInterestsFor:application.
-                               value1 value:(value2 value isNil ifTrue:[nil]
-                                                                ifFalse:[value2 value sqrt]).
-                               value1 onChangeSend:#value1Changed to:application.
-                              ].
+	application := Plug new.
+	application respondTo:#value1Changed
+			 with:[value2 retractInterestsFor:application.
+			       value2 value:(value1 value isNil ifTrue:[nil]
+								ifFalse:[value1 value squared]).
+			       value2 onChangeSend:#value2Changed to:application.
+			      ].
+	application respondTo:#value2Changed
+			 with:[value1 retractInterestsFor:application.
+			       value1 value:(value2 value isNil ifTrue:[nil]
+								ifFalse:[value2 value sqrt]).
+			       value1 onChangeSend:#value1Changed to:application.
+			      ].
 
-        value1 := 1 asValue.
-        value2 := 1 asValue.
+	value1 := 1 asValue.
+	value2 := 1 asValue.
 
-        top := Dialog new.
-        top extent:200@200.
+	top := Dialog new.
+	top extent:200@200.
 
-        (top addTextLabel:'some number:') layout:#left.
-        top addVerticalSpace.
+	(top addTextLabel:'some number:') layout:#left.
+	top addVerticalSpace.
 
-        (top addInputFieldOn:value1 tabable:false) 
-            converter:(PrintConverter new initForNumberOrNil);
-            immediateAccept:true.
-        top addVerticalSpace.
+	(top addInputFieldOn:value1 tabable:false) 
+	    converter:(PrintConverter new initForNumberOrNil);
+	    immediateAccept:true.
+	top addVerticalSpace.
 
-        (top addTextLabel:'squared:') layout:#left.
-        top addVerticalSpace.
-        (top addInputFieldOn:value2 tabable:false) 
-            converter:(PrintConverter new initForNumberOrNil);
-            immediateAccept:true.
+	(top addTextLabel:'squared:') layout:#left.
+	top addVerticalSpace.
+	(top addInputFieldOn:value2 tabable:false) 
+	    converter:(PrintConverter new initForNumberOrNil);
+	    immediateAccept:true.
 
-        value1 onChangeSend:#value1Changed to:application.
-        value2 onChangeSend:#value2Changed to:application.
+	value1 onChangeSend:#value1Changed to:application.
+	value2 onChangeSend:#value2Changed to:application.
 
-        top openModeless.
+	top openModeless.
 "
 ! !
 
@@ -553,6 +657,23 @@
     "
 ! !
 
+!EditField methodsFor:'accepting'!
+
+accept
+    ""
+    |val string|
+
+    super accept.
+    converter notNil ifTrue:[
+	val := self editValue.
+	string := converter printStringFor:val.
+	string ~= self contents ifTrue:[
+	    self contents:string.
+	    self flash
+	]
+    ].
+! !
+
 !EditField methodsFor:'accessing-behavior'!
 
 acceptOnLeave:aBoolean
@@ -576,6 +697,13 @@
     "Modified: 16.12.1995 / 16:25:34 / cg"
 !
 
+autoScroll:aBoolean
+    "turn on/off automatic scrolling upon keyboard entry
+     to make the cursor visible."
+
+    autoScrollHorizontally := aBoolean
+!
+
 crAction:aBlock
     "define an action to be evaluated when the return key is pressed."
 
@@ -585,9 +713,9 @@
 cursorMovementWhenUpdating:aSymbol
     "define what should be done with the cursor, when I update
      my contents from the model. Allowed arguments are:
-        #keep / nil     -> stay where it was
-        #endOfLine      -> position cursor after the string
-        #beginOfLine    -> position cursor to the beginning
+	#keep / nil     -> stay where it was
+	#endOfLine      -> position cursor after the string
+	#beginOfLine    -> position cursor to the beginning
      The default is #endOfLine.
      This may be useful for fields which get new values assigned from
      the program (i.e. not from the user)"
@@ -601,8 +729,8 @@
     "disable the field; hide the cursor and ignore input"
 
     enabled ifTrue:[
-        enabled := false.
-        self hideCursor
+	enabled := false.
+	self hideCursor
     ]
 
     "Modified: 16.12.1995 / 16:28:05 / cg"
@@ -615,8 +743,8 @@
 "/        enableAction notNil ifTrue:[
 "/            enableAction value
 "/        ].
-        enabled := true.
-        super showCursor
+	enabled := true.
+	super showCursor
     ]
 
     "Modified: 16.12.1995 / 16:28:09 / cg"
@@ -682,15 +810,15 @@
     |wasEnabled|
 
     enableChannel notNil ifTrue:[
-        wasEnabled := enableChannel value.
-        enableChannel retractInterestsFor:self. 
+	wasEnabled := enableChannel value.
+	enableChannel retractInterestsFor:self. 
     ] ifFalse:[
-        wasEnabled := enabled
+	wasEnabled := enabled
     ].
     enableChannel := aValueHolder.
     aValueHolder onChangeSend:#enableStateChange to:self.
     enableChannel value ~~ wasEnabled ifTrue:[
-        self enableStateChange
+	self enableStateChange
     ]
 
     "Created: 16.12.1995 / 16:35:32 / cg"
@@ -854,10 +982,14 @@
     "set the maximum number of characters that are allowed in
      the field. Additional input will be ignored by the field.
      A limit of nil means: unlimited. This is the default.
+     If set, a lengthLimit must be defined before any contents is placed
+     into the field, because the contents is not cut when the max is
+     changed later. I.e. it should be set early after creation of the field.
+
      This method has been renamed from #lengthLimit: for ST-80
      compatibility."
 
-    lengthLimit := aNumberOrNil
+    lengthLimit := aNumberOrNil.
 !
 
 passwordCharacter
@@ -970,9 +1102,9 @@
 
 enableStateChange
     enableChannel value ifTrue:[
-        self enable
+	self enable
     ] ifFalse:[
-        self disable
+	self disable
     ].
 
     "Created: 16.12.1995 / 16:35:39 / cg"
@@ -999,56 +1131,56 @@
 
     <resource: #keyboard (#DeleteLine #EndOfText)>
 
-    |leave xCol newOffset oldWidth newWidth s|
+    |leave xCol newOffset newWidth s|
 
     enabled ifFalse:[
-        ^ self
+	^ self
     ].
 
     (key == #DeleteLine) ifTrue:[
-        Smalltalk at:#CopyBuffer put:(self contents).
-        self contents:''. ^ self
+	Smalltalk at:#CopyBuffer put:(self contents).
+	self contents:''. ^ self
     ].
 
     (key == #Tab) ifTrue:[
-        tabAction notNil ifTrue:[tabAction value. ^ self].
-        entryCompletionBlock notNil ifTrue:[
-            s := self contents.
-            s isNil ifTrue:[
-                s := ''
-            ] ifFalse:[
-                s := s asString
-            ].
-            entryCompletionBlock value:s. ^ self
-        ]
+	tabAction notNil ifTrue:[tabAction value. ^ self].
+	entryCompletionBlock notNil ifTrue:[
+	    s := self contents.
+	    s isNil ifTrue:[
+		s := ''
+	    ] ifFalse:[
+		s := s asString
+	    ].
+	    entryCompletionBlock value:s. ^ self
+	]
     ].
     (key == #Return) ifTrue:[
-        crAction notNil ifTrue:[crAction value. ^ self].
+	crAction notNil ifTrue:[crAction value. ^ self].
     ].
     leave := leaveKeys includes:key.
     leave ifTrue:[
 
-        ((key == #Return and:[acceptOnReturn])
-        or:[key ~~ #Return and:[acceptOnLeave]]) ifTrue:[
-            self accept.
-        ].
+	((key == #Return and:[acceptOnReturn])
+	or:[key ~~ #Return and:[acceptOnLeave]]) ifTrue:[
+	    self accept.
+	].
 
-        leaveAction notNil ifTrue:[
-            ^ leaveAction value:key
-        ].
+	leaveAction notNil ifTrue:[
+	    ^ leaveAction value:key
+	].
 
-        x >= 0 ifTrue:[
-            "
-             let superview know about the leave ...
-             This is a temporary kludge for the tableWidget -
-             it is no clean coding style. Should make the tableWidget
-             a proper model and handle it via the changed mechanism ....
-            "
-            (superView notNil and:[superView canHandle:key from:self]) ifTrue:[
-                superView keyPress:key x:x y:y.
-            ].
-        ].
-        ^ self
+	x >= 0 ifTrue:[
+	    "
+	     let superview know about the leave ...
+	     This is a temporary kludge for the tableWidget -
+	     it is no clean coding style. Should make the tableWidget
+	     a proper model and handle it via the changed mechanism ....
+	    "
+	    (superView notNil and:[superView canHandle:key from:self]) ifTrue:[
+		superView keyPress:key x:x y:y.
+	    ].
+	].
+	^ self
     ].
 
     "
@@ -1062,15 +1194,26 @@
     "
      a normal key - let superclass's method insert it
     "
-    oldWidth := self widthOfContents.
     super keyPress:key x:x y:y.
 
     "
      for end-of-text, also move to end-of-line
     "
     key == #EndOfText ifTrue:[
-        super keyPress:#EndOfLine x:x y:y.
+	super keyPress:#EndOfLine x:x y:y.
     ].
+
+    self resizeOrScroll.
+
+    "Modified: 16.1.1996 / 19:39:14 / cg"
+!
+
+resizeOrScroll
+    "helper for keyPress.
+     Extracted for easier subclass redefinition."
+
+    |xCol newOffset newWidth|
+
     newWidth := self widthOfContents.
 
     "
@@ -1078,33 +1221,32 @@
     "
     xCol := (self xOfCol:cursorCol inVisibleLine:cursorLine) - leftOffset.
     (xCol > (width * (5/6))) ifTrue:[
-        self changed:#preferredExtent
+	self changed:#preferredExtent
     ] ifFalse:[
-        newWidth < (width * (1/6)) ifTrue:[
-            self changed:#preferredExtent
-        ]
+	newWidth < (width * (1/6)) ifTrue:[
+	    self changed:#preferredExtent
+	]
     ].
 
-    "
-     did someone react (i.e. has my extent changed) ?
-     (if not, we scroll horizontally)
-    "
-    xCol := (self xOfCol:cursorCol inVisibleLine:cursorLine) - leftOffset.
-    (xCol > (width * (5/6))) ifTrue:[
-        newOffset := leftOffset + (width // 2).
-    ] ifFalse:[
-        (xCol < (width * (1/6))) ifTrue:[
-            newOffset := 0 max: leftOffset - (width // 2).
-        ] ifFalse:[
-            newOffset := leftOffset
-        ]
+    autoScrollHorizontally ifTrue:[
+	"
+	 did someone react (i.e. has my extent changed) ?
+	 (if not, we scroll horizontally)
+	"
+	xCol := (self xOfCol:cursorCol inVisibleLine:cursorLine) - leftOffset.
+	(xCol > (width * (5/6))) ifTrue:[
+	    newOffset := leftOffset + (width // 2).
+	] ifFalse:[
+	    (xCol < (width * (1/6))) ifTrue:[
+		newOffset := 0 max: leftOffset - (width // 2).
+	    ] ifFalse:[
+		newOffset := leftOffset
+	    ]
+	].
+	newOffset ~~ leftOffset ifTrue:[
+	    self scrollHorizontalTo:newOffset.
+	]
     ].
-    newOffset ~~ leftOffset ifTrue:[
-        self scrollHorizontalTo:newOffset.
-"/        leftOffset := newOffset.
-"/        self clear.
-"/        self redraw
-    ]
 ! !
 
 !EditField methodsFor:'initialization'!
@@ -1166,6 +1308,7 @@
     self height:(font height + font descent + (topMargin * 2)).
     enabled := true.
     fixedSize := true.
+    autoScrollHorizontally := true.
     nFullLinesShown := 1.
     nLinesShown := 1.
     immediateAccept := false.
@@ -1318,5 +1461,5 @@
 !EditField class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.37 1996-01-10 14:48:41 ca Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.38 1996-01-16 19:07:53 cg Exp $'
 ! !
--- a/ListView.st	Tue Jan 16 03:04:32 1996 +0100
+++ b/ListView.st	Tue Jan 16 20:07:57 1996 +0100
@@ -248,6 +248,22 @@
     ^ height - (2 * margin) - topMargin
 !
 
+innerHorizontalMargin
+    "return the margin between the left border and the 1st col"
+
+    ^ leftMargin
+
+    "Created: 16.1.1996 / 19:28:23 / cg"
+!
+
+innerVerticalMargin
+    "return the margin between the top border and the 1st line"
+
+    ^ topMargin
+
+    "Created: 16.1.1996 / 19:28:00 / cg"
+!
+
 leftMargin
     "return the margin to left of 1st col"
 
@@ -2754,5 +2770,5 @@
 !ListView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg/ListView.st,v 1.55 1996-01-16 00:15:43 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg/ListView.st,v 1.56 1996-01-16 19:07:57 cg Exp $'
 ! !