EditField.st
changeset 125 3ffa271732f7
parent 122 04ec3fda7c11
child 127 462396b08e30
--- a/EditField.st	Mon May 08 17:19:27 1995 +0200
+++ b/EditField.st	Tue May 09 03:57:16 1995 +0200
@@ -10,14 +10,15 @@
  hereby transferred.
 "
 
-'From Smalltalk/X, Version:2.10.5 on 4-may-1995 at 8:46:55 am'!
+'From Smalltalk/X, Version:2.10.5 on 9-may-1995 at 12:09:38 pm'!
 
 EditTextView subclass:#EditField
-	 instanceVariableNames:'leaveAction enabled enableAction crAction tabAction
-		converter acceptAction leaveKeys alwaysAccept acceptOnLeave acceptOnReturn'
+	 instanceVariableNames:'leaveAction enabled enableAction crAction tabAction converter
+                leaveKeys immediateAccept acceptOnLeave acceptOnReturn
+                lengthLimit'
 	 classVariableNames:'DefaultForegroundColor DefaultBackgroundColor
-		DefaultSelectionForegroundColor DefaultSelectionBackgroundColor
-		DefaultFont'
+                DefaultSelectionForegroundColor DefaultSelectionBackgroundColor
+                DefaultFont'
 	 poolDictionaries:''
 	 category:'Views-Text'
 !
@@ -26,7 +27,7 @@
 COPYRIGHT (c) 1990 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.20 1995-05-07 00:15:56 claus Exp $
+$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.21 1995-05-09 01:55:33 claus Exp $
 '!
 
 !EditField class methodsFor:'documentation'!
@@ -47,7 +48,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.20 1995-05-07 00:15:56 claus Exp $
+$Header: /cvs/stx/stx/libwidg/EditField.st,v 1.21 1995-05-09 01:55:33 claus Exp $
 "
 !
 
@@ -56,9 +57,6 @@
     an editable text-field. Realized by using an EditTextView,
     and forcing its size to 1 line - disabling cursor movement
     in the vertical direction.
-    An action (leaveAction) is performed when the field is left
-    by either Return or a cursor movement, or if 'accept' is
-    performed from the menu.
 
     Instance variables:
 
@@ -70,7 +68,10 @@
 
       enabled        <Boolean>                  if false, input is ignored.
 
-      enableAction   <Block | nil>
+      enableAction   <Block | nil>              action performed if the field is
+						enabled via an explicit click.
+						(this is used by the group to
+						 set the active field to the clicked upon field)
 
       crAction       <Block | nil>              if non-nil, keyboard input of a cr are not
 						handled specially, instead this block is evaluated
@@ -85,15 +86,13 @@
 						the object and its printed representation.
 						Defaults to nil i.e. assume that strings are edited.
 
-      acceptAction   <Block | nil>              if non-nil, this is performed in addition to
-						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.
+      immediateAccept   <Boolean>               if true, every change of the text is immediately
+						forwarded to the model/acceptBlock. If false,
+						the changed value is only stored in the model
+						if the field is left or accepted.
+						Default is false.
 
       acceptOnLeave  <Boolean>                  if true, leaving the field (via cursor keys)
 						automatically accepts the value into the model.
@@ -123,7 +122,9 @@
 	top open
 
 
-    forward input in topView to field:
+    forward input in topView to the field:
+    (currently, the field does not know this - therefore,
+     its been told here ... this may change)
 
 	|top field|
 
@@ -134,10 +135,11 @@
 	field width:1.0.        'let its height as-is'.
 
 	top delegate:(KeyboardForwarder toView:field).
+	field hasKeyboardFocus:true.
 	top open
 
 
-    just to make it look better: set some inset:
+    to make it look better: set some inset:
 
 	|top field|
 
@@ -168,7 +170,7 @@
 	top open
 
 
-    and have it preselected:
+    have it preselected:
 
 	|top field|
 
@@ -201,8 +203,25 @@
 	top open
 
 
+    set a size limit:
+
+	|top field|
+
+	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';
+	      maxChars:8.
+
+	top open
+
+
     use a converter:
-      - numbers:
+      - numbers (default to 0):
 
 	|top field|
 
@@ -234,13 +253,14 @@
 
 	field converter:(PrintConverter new initForDate).
 	field editValue:Date today.
-	field acceptAction:[:value | Transcript show:value class name; space; showCr:value].
+	field acceptAction:[:value | Transcript showCr:value class name , ' ' , value printString].
 	field crAction:[field accept. top destroy].
 	top open.
 
 
-    setting alwaysAccept, makes the field update with every key:
-      - numbers:
+    setting immediateAccept, makes the field update with every key:
+
+      - immediate accept numbers, defaulting to nil:
 
 	|top field|
 
@@ -252,8 +272,8 @@
 	field leftInset:ViewSpacing;
 	      rightInset:ViewSpacing.
 
-	field converter:(PrintConverter new initForNumber).
-	field alwaysAccept:true.
+	field converter:(PrintConverter new initForNumberOrNil).
+	field immediateAccept:true.
 	field editValue:1234.
 	field acceptAction:[:value | Transcript showCr:value].
 	field crAction:[field accept. top destroy].
@@ -304,6 +324,27 @@
 	field2 model:model.
 	top2 open.
 
+    with immediate accept:
+
+	|top1 top2 field1 field2 model|
+
+	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.
+
+	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.
 
     just an example; a checkBox and an editField on the same model:
 
@@ -329,11 +370,97 @@
 	top2 open.
 
 	model inspect.
+
+
+    connecting fields:
+    update field2 wehenever field1 is changed.
+    (normally, the processing below (xChanged) is done in your application
+     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 := Plug new.
+	application respondTo:#value1Changed
+			 with:[value2 value:(value1 value isNil ifTrue:[nil]
+								ifFalse:[value1 value squared])].
+
+	value1 := 1 asValue.
+	value2 := 1 asValue.
+
+	top := Dialog new.
+	top extent:200@200.
+
+	(top addTextLabel:'some number:') layout:#left.
+	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).
+
+	value1 onChangeSend:#value1Changed to:application.
+
+	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 := Plug new.
+	application respondTo:#value1Changed
+			 with:[value2 retractInterrestFor:application.
+			       value2 value:(value1 value isNil ifTrue:[nil]
+								ifFalse:[value1 value squared]).
+			       value2 onChangeSend:#value2Changed to:application.
+			      ].
+	application respondTo:#value2Changed
+			 with:[value1 retractInterrestFor:application.
+			       value1 value:(value2 value isNil ifTrue:[nil]
+								ifFalse:[value2 value sqrt]).
+			       value1 onChangeSend:#value1Changed to:application.
+			      ].
+
+	value1 := 1 asValue.
+	value2 := 1 asValue.
+
+	top := Dialog new.
+	top extent:200@200.
+
+	(top addTextLabel:'some number:') layout:#left.
+	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).
+
+	value1 onChangeSend:#value1Changed to:application.
+	value2 onChangeSend:#value2Changed to:application.
+
+	top openModeless.
 "
 ! !
 
 !EditField class methodsFor:'defaults'!
 
+defaultLeaveKeys
+    ^ #(Return CursorUp CursorDown Next Previous Accept)
+!
+
 updateStyleCache
     DefaultForegroundColor := StyleSheet colorAt:'editFieldForegroundColor' default:Black.
     DefaultBackgroundColor := StyleSheet colorAt:'editFieldBackgroundColor' default:White.
@@ -346,32 +473,275 @@
     "
 !
 
-defaultLeaveKeys
-    ^ #(Return CursorUp CursorDown Next Previous Accept)
-!
-
 defaultNumberOfLines
     "the number of lines in the field"
 
     ^ 1
 ! !
 
-!EditField methodsFor:'initialization'!
+!EditField methodsFor:'private'!
+
+textChanged
+    "this is sent by mySelf (somewhere in a superclass) whenever
+     my contents has changed. 
+     A good place to add immediateAccept functionality and check for the
+     lengthLimit."
+
+    |string|
+
+    super textChanged.
+    string := self contents.
+    lengthLimit notNil ifTrue:[
+	string size > lengthLimit ifTrue:[
+	    self contents:(string := string copyTo:lengthLimit).
+	    self flash.
+	]
+    ].
+    immediateAccept ifTrue:[
+	self accept
+    ]
+!
+
+getListFromModel
+    "redefined to aquire the text via the aspectMsg - not the listMsg,
+     and to ignore updates resulting from my own change."
+
+    "
+     ignore updates from my own change
+    "
+    lockUpdates ifTrue:[
+	lockUpdates := false.
+	^ self
+    ].
+
+    (model notNil and:[aspectMsg notNil]) ifTrue:[
+	self editValue:(model perform:aspectMsg).
+    ]
+!
+
+startAutoScrollUp:y
+    "no vertical scrolling in editfields"
+
+    ^ self
+!
+
+startAutoScrollDown:y
+    "no vertical scrolling in editfields"
+
+    ^ self
+! !
+
+!EditField methodsFor:'accessing'!
+
+contents
+    "return contents as a string
+     - 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:[^ ''].
+    ^ list at:1
+!
+
+leaveAction:aBlock
+    "define an action to be evaluated when field is left by return key"
+
+    leaveAction := aBlock
+!
+
+list:someText
+    "redefined to force text to 1 line, and notify dependents
+     of any changed extent-wishes."
+
+    |l oldWidth|
+
+    l := someText.
+    l size > 1 ifTrue:[
+	l := OrderedCollection with:(l at:1)
+    ].
+    oldWidth := self widthOfContents.
+    super list:l.
+    self widthOfContents ~~ oldWidth ifTrue:[
+	self changed:#preferedExtent
+    ]
+!
+
+contents:someText
+    "set the contents from a string
+     - 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).
+!
+
+enable
+    "enable the field; show cursor and allow input"
+
+    enabled ifFalse:[
+"/        enableAction notNil ifTrue:[
+"/            enableAction value
+"/        ].
+	enabled := true.
+	super showCursor
+    ]
+!
+
+immediateAccept:aBoolean
+    "set/clear the immediateAccept flag. The default is false."
+
+     immediateAccept := aBoolean
+!
+
+editValue
+    "if the field edits a string, this is a name alias for #contents.
+     Otherwise, if there is a converter, return the edited string
+     converted to an appropriate object."
+
+    |string|
+
+    string := self contents.
+    converter isNil ifTrue:[^ string].
+    string isNil ifTrue:[string := ''].
+    ^ converter readValueFrom:string 
+!
 
-initialize
-    super initialize.
-    self height:(font height + font descent + (topMargin * 2)).
-    enabled := true.
-    fixedSize := true.
-    nFullLinesShown := 1.
-    nLinesShown := 1.
-    alwaysAccept := false.
-    acceptOnLeave := false.
-    acceptOnReturn := true.
-    leaveKeys := self class defaultLeaveKeys.
-    cursorShown := true
+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
+!
+
+initialText:aString selected:aBoolean
+    "set the initialText and select it if aBoolean is true"
+
+    |len s|
+
+    leftOffset := 0.
+    aString isNil ifTrue:[
+	s := nil
+    ] ifFalse:[
+	s := aString asString
+    ].
+    self contents:s.
+    aBoolean ifTrue:[
+	(len := s size) ~~ 0 ifTrue:[
+	    self selectFromLine:1 col:1 toLine:1 col:len
+	]
+    ]
+!
+
+crAction:aBlock
+    "define an action to be evaluated when the return key is pressed."
+
+    crAction := aBlock
+!
+
+tabAction:aBlock
+    "define an action to be evaluated when the tabulator key is pressed."
+
+    tabAction := aBlock
+!
+
+acceptOnReturn:aBoolean
+    "set/clear the acceptOnReturn flag. The default is true."
+
+     acceptOnReturn := aBoolean
+!
+
+initialText:aString
+    "set the initialText and select it"
+
+    self initialText:aString selected:true
+!
+
+editValue:aStringOrObject
+    "set the contents. If there is a converter, use it to convert
+     the object into a printed representation.
+     Otherwise, the argument is supposed to be a string like object,
+     and used directly (i.e. this is equivalent to sending #contents:)."
+
+    self editValue:aStringOrObject selected:false
 !
 
+disable
+    "disable the field; hide cursor and ignore input"
+
+    enabled ifTrue:[
+	enabled := false.
+	self hideCursor
+    ]
+!
+
+editValue:aStringOrObject selected:aBoolean
+    "set the contents. If there is a converter, use it to convert
+     the object into a printed representation.
+     Otherwise, the argument is supposed to be a string like object,
+     and used directly (i.e. this is equivalent to sending #contents:)."
+
+    |string|
+
+    converter notNil ifTrue:[
+	string := converter printStringFor:aStringOrObject
+    ] ifFalse:[
+	string :=  aStringOrObject.
+    ].
+    self contents:string.
+    aBoolean ifTrue:[
+	self selectFromLine:1 col:1 toLine:1 col:string size
+    ]
+!
+
+acceptOnLeave:aBoolean
+    "set/clear the acceptOnLeave flag. The default is false."
+
+     acceptOnLeave := aBoolean
+!
+
+converter:aConverter
+    "set the converter. If non-nil,
+     the converter is applied to the text to convert from the string
+     representation to the actual object value and vice versa.
+     The default converter is nil, meaning no-conversion
+     (i.e. the edited object is the string itself."
+
+    converter := aConverter
+!
+
+enableAction:aBlock
+    "define an action to be evaluated when enabled by clicking upon"
+
+    enableAction := aBlock
+!
+
+converter
+    "return the converter (if any)."
+
+    ^ converter
+!
+
+maxChars:aNumberOrNil
+    "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.
+     This method has been renamed from #lengthLimit: for ST-80
+     compatibility."
+
+    lengthLimit := aNumberOrNil
+!
+
+stringValue
+    "alias for #contents - for ST-80 compatibility"
+
+    ^ self contents
+! !
+
+!EditField methodsFor:'initialization'!
+
 initStyle
     super initStyle.
 
@@ -388,6 +758,19 @@
     ]
 !
 
+initialize
+    super initialize.
+    self height:(font height + font descent + (topMargin * 2)).
+    enabled := true.
+    fixedSize := true.
+    nFullLinesShown := 1.
+    nLinesShown := 1.
+    immediateAccept := acceptOnLeave := false.
+    acceptOnReturn := true.
+    cursorShown := true.
+    leaveKeys := self class defaultLeaveKeys.
+!
+
 editMenu
     |labels selectors m|
 
@@ -433,43 +816,6 @@
     super realize
 ! !
 
-!EditField methodsFor:'private'!
-
-getListFromModel
-    "redefined to aquire the text via the aspectMsg - not the listMsg"
-
-    |savedCursorCol|
-
-    (model notNil and:[aspectMsg notNil]) ifTrue:[
-	"
-	 kludge: editValue positions cursor to beginning
-	"
-	savedCursorCol := cursorCol.
-	self editValue:(model perform:aspectMsg).
-	savedCursorCol ~~ 1 ifTrue:[self cursorLine:1 col:savedCursorCol].
-	cursorVisibleLine := 1.
-    ]
-!
-
-textChanged
-    super textChanged.
-    alwaysAccept ifTrue:[
-	self accept
-    ]
-!
-
-startAutoScrollUp:y
-    "no vertical scrolling in editfields"
-
-    ^ self
-!
-
-startAutoScrollDown:y
-    "no vertical scrolling in editfields"
-
-    ^ self
-! !
-
 !EditField methodsFor:'queries'!
 
 preferedExtent
@@ -488,211 +834,6 @@
     ^ w @ self height
 ! !
 
-!EditField methodsFor:'accessing'!
-
-list:someText
-    "redefined to force text to 1 line, and notify dependents
-     of any changed extent-wishes."
-
-    |l oldWidth|
-
-    l := someText.
-    l size > 1 ifTrue:[
-	l := OrderedCollection with:(l at:1)
-    ].
-    oldWidth := self widthOfContents.
-    super list:l.
-    self widthOfContents ~~ oldWidth ifTrue:[
-	self changed:#preferedExtent
-    ]
-!
-
-contents:someText
-    "set the contents from a string
-     - 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).
-!
-
-contents
-    "return contents as a string
-     - 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:[^ ''].
-    ^ list at:1
-!
-
-enable
-    "enable the field; show cursor and allow input"
-
-    enabled ifFalse:[
-	enableAction notNil ifTrue:[
-	    enableAction value
-	].
-	enabled := true.
-	super showCursor
-    ]
-!
-
-leaveAction:aBlock
-    "define an action to be evaluated when field is left by return key"
-
-    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."
-
-    crAction := aBlock
-!
-
-acceptAction:aBlock
-    "define an action to be evaluated when accepted."
-
-    acceptAction := aBlock
-!
-
-tabAction:aBlock
-    "define an action to be evaluated when the tabulator key is pressed."
-
-    tabAction := aBlock
-!
-
-alwaysAccept:aBoolean
-    "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)."
-
-    ^ converter
-!
-
-editValue
-    "if the field edits a string, this is a name alias for #contents.
-     Otherwise, if there is a converter, return the edited string
-     converted to an appropriate object."
-
-    |text|
-
-    text := self contents.
-    converter isNil ifTrue:[^ text].
-    ^ converter readValueFrom:text withoutSpaces
-!
-
-editValue:aStringOrObject
-    "set the contents. If there is a converter, use it to convert
-     the object into a printed representation.
-     Otherwise, the argument is supposed to be a string like object,
-     and used directly (i.e. this is equivalent to sending #contents:)."
-
-    self editValue:aStringOrObject selected:false
-!
-
-editValue:aStringOrObject selected:aBoolean
-    "set the contents. If there is a converter, use it to convert
-     the object into a printed representation.
-     Otherwise, the argument is supposed to be a string like object,
-     and used directly (i.e. this is equivalent to sending #contents:)."
-
-    |text|
-
-    converter notNil ifTrue:[
-	text := converter printStringFor:aStringOrObject
-    ] ifFalse:[
-	text :=  aStringOrObject.
-    ].
-    self contents:text.
-    aBoolean ifTrue:[
-	self selectFromLine:1 col:1 toLine:1 col:text size
-    ]
-!
-
-converter:aConverter
-    "set the converter. If non-nil,
-     the converter is applied to the text to convert from the string
-     representation to the actual object value and vice versa.
-     The default converter is nil, meaning no-conversion
-     (i.e. the edited object is the string itself."
-
-    converter := aConverter
-!
-
-
-disable
-    "disable the field; hide cursor and ignore input"
-
-    enabled ifTrue:[
-	enabled := false.
-	self hideCursor
-    ]
-!
-
-enableAction:aBlock
-    "define an action to be evaluated when enabled by clicking upon"
-
-    enableAction := aBlock
-!
-
-initialText:aString selected:aBoolean
-    "set the initialText and select it if aBoolean is true"
-
-    |len s|
-
-    leftOffset := 0.
-    self contents:(s := aString asString).
-    aBoolean ifTrue:[
-	(len := s size) ~~ 0 ifTrue:[
-	    self selectFromLine:1 col:1 toLine:1 col:len
-	]
-    ]
-!
-
-initialText:aString
-    "set the initialText and select it"
-
-    self initialText:aString selected:true
-! !
-
-!EditField methodsFor:'editing'!
-
-paste:someText
-    "redefined to force text to 1 line"
-
-    super paste:someText.
-    list size > 1 ifTrue:[
-	self deleteFromLine:2 toLine:(list size)
-    ]
-! !
-
 !EditField methodsFor:'cursor drawing'!
 
 showCursor
@@ -704,6 +845,21 @@
 
 !EditField methodsFor:'cursor movement'!
 
+cursorCol:col
+    "redefined to lock the cursor at the end, if I have a lngthLimit"
+
+    |c sz|
+
+    c := col.
+    lengthLimit notNil ifTrue:[
+	sz := lengthLimit.
+	c > sz ifTrue:[
+	    c := sz+1.
+	]
+    ].
+    super cursorCol:c
+!
+
 cursorLine:line col:col
     "catch cursor movement"
 
@@ -720,19 +876,105 @@
 
 !EditField methodsFor:'event handling'!
 
-accept
-    "accept the fields contents - perform the leave action as if
-     return was pressed."
+keyPress:key x:x y:y
+    "if keyHandler is defined, pass input; otherwise check for leave
+     keys"
+
+    |leave xCol newOffset oldWidth newWidth|
+
+    enabled ifFalse:[
+        ^ self
+    ].
+
+    (key == #DeleteLine) ifTrue:[
+        Smalltalk at:#CopyBuffer put:(self contents).
+        self contents:''. ^ self
+    ].
 
-    |value|
+    (key == #Tab) ifTrue:[
+        tabAction notNil ifTrue:[tabAction value. ^ self].
+    ].
+    (key == #Return) ifTrue:[
+        crAction notNil ifTrue:[crAction value. ^ self].
+    ].
+    leave := leaveKeys includes:key.
+    leave ifTrue:[
+        leaveAction notNil ifTrue:[
+            leaveAction value:key
+        ].
 
-    value := self editValue.
-    acceptAction notNil ifTrue:[
-	acceptAction value:value
+        ((key == #Return and:[acceptOnReturn])
+        or:[key ~~ #Return and:[acceptOnLeave]]) ifTrue:[
+            self accept.
+        ].
+
+        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
     ].
 
-    "model-view behavior"
-    self sendChangeMessageWith:value.
+    "
+     ignore some keys (if not a leaveKey) ...
+    "
+    (key == #Find) ifTrue:[^self].
+    (key == #FindNext) ifTrue:[^self].
+    (key == #FindPrev) ifTrue:[^self].
+    (key == #GotoLine) ifTrue:[^self].
+
+    "
+     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.
+    ].
+    newWidth := self widthOfContents.
+
+    "
+     should (& can) we resize ?
+    "
+    xCol := (self xOfCol:cursorCol inVisibleLine:cursorLine) - leftOffset.
+    (xCol > (width * (5/6))) ifTrue:[
+        self changed:#preferedExtent
+    ] ifFalse:[
+        newWidth < (width * (1/6)) ifTrue:[
+            self changed:#preferedExtent
+        ]
+    ].
+
+    "
+     did someone react ?
+     (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:[
+        leftOffset := newOffset.
+        self clear.
+        self redraw
+    ]
 !
 
 buttonPress:button x:x y:y
@@ -749,98 +991,18 @@
     ]
 !
 
-keyPress:key x:x y:y
-    "if keyHandler is defined, pass input; otherwise check for leave
-     keys"
-
-    |leave xCol newOffset oldWidth newWidth|
+focusIn
+    "got the explicit focus"
 
     enabled ifFalse:[
-	^ self
-    ].
-
-    (key == #DeleteLine) ifTrue:[
-	Smalltalk at:#CopyBuffer put:(self contents).
-	self contents:''. ^ self
-    ].
-
-    (key == #Tab) ifTrue:[
-	tabAction notNil ifTrue:[tabAction value. ^ self].
-    ].
-    (key == #Return) ifTrue:[
-	crAction notNil ifTrue:[crAction value. ^ self].
-    ].
-    leave := leaveKeys includes:key.
-    leave ifTrue:[
-	leaveAction notNil ifTrue:[
-	    leaveAction value:key
-	].
-
-	((key == #Return and:[acceptOnReturn])
-	or:[key ~~ #Return and:[acceptOnLeave]]) ifTrue:[
-	    self accept.
-	].
-
-	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
+	enabled := true.
+	super focusIn.
+	enableAction notNil ifTrue:[
+	    enableAction value
+	]
+    ] ifTrue:[
+	super focusIn
     ].
-
-    "
-     ignore some keys (if not a leaveKey) ...
-    "
-    (key == #Find) ifTrue:[^self].
-    (key == #FindNext) ifTrue:[^self].
-    (key == #FindPrev) ifTrue:[^self].
-    (key == #GotoLine) ifTrue:[^self].
-
-    "
-     a normal key - let superclass's method insert it
-    "
-    oldWidth := self widthOfContents.
-    super keyPress:key x:x y:y.
-    newWidth := self widthOfContents.
-
-    "
-     should (& can) we resize ?
-    "
-    xCol := (self xOfCol:cursorCol inVisibleLine:cursorLine) - leftOffset.
-    (xCol > (width * (5/6))) ifTrue:[
-	self changed:#preferedExtent
-    ] ifFalse:[
-	newWidth < (width * (1/6)) ifTrue:[
-	    self changed:#preferedExtent
-	]
-    ].
-
-    "
-     did someone react ?
-     (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:[
-	leftOffset := newOffset.
-	self clear.
-	self redraw
-    ]
 !
 
 canHandle:aKey
@@ -848,7 +1010,20 @@
      (usually from another view, when the receiver is part of
       a more complex dialog box).
      We do return true here, since the editfield will handle
-     all keys."
+     all keys.
+     OBSOLETE: dont use this anymore - its a leftover for the tableWidget"
 
     ^ true
 ! !
+
+!EditField methodsFor:'editing'!
+
+paste:someText
+    "redefined to force text to 1 line"
+
+    super paste:someText.
+    list size > 1 ifTrue:[
+	self deleteFromLine:2 toLine:(list size)
+    ]
+! !
+