--- a/EFGroup.st Sat Apr 27 10:12:28 1996 +0200
+++ b/EFGroup.st Sat Apr 27 19:55:59 1996 +0200
@@ -11,7 +11,7 @@
"
Object subclass:#EnterFieldGroup
- instanceVariableNames:'fields currentField leaveAction wrap'
+ instanceVariableNames:'fields currentField leaveAction wrap leaveOnTabLast'
classVariableNames:''
poolDictionaries:''
category:'Interface-Support'
@@ -39,21 +39,29 @@
enabling the next/prev field when a field is left.
Instances of this class keep track of which field of the group is the
currentField (i.e. the one getting keyboard input) and forwards input
- to the active field (having the inputField delegate its input to me).
+ to that one.
+ This is done by arranging for all of my fields to delegate their
+ input to me, which is then forwarded to the active field).
The block accessable as leaveAction is evaluated when the last
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).
+ Usually this block triggers accept on the fields (if they did not already)
+ and/or performs some followup processing and possibly 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.
+ By default, tabbing via #Tab is disabled - to enable it, send the field
+ a #makeTabable or #makeAllTabable to the group.
+
+ All of this here is low level stuff, providing a lot of freedom in
+ which keys are handled and how they perform.
+ Normally, these are not required for most users - the DialogBox sets up
+ things correctly for most cases.
+
[Instance variables:]
@@ -71,8 +79,17 @@
This is ignored, if no leaveAction was
defined.
+ leaveOnTabLast <Boolean> if true, tabbing out of the last
+ field leaves the group.
+ The default is false.
+
[author:]
Claus Gittinger
+
+
+ [see also:]
+ DialogBox
+ EditField
"
!
@@ -80,233 +97,323 @@
"
without a group - user has to enter mouse into the next field to activate it;
Cursor-keys dont work:
-
- |top panel field1 field2 field3|
+ [exBegin]
+ |top panel field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ panel add:(field1 := EditField extent:(1.0 @ nil)).
+ panel add:(field2 := EditField extent:(1.0 @ nil)).
+ panel add:(field3 := EditField extent:(1.0 @ nil)).
- top open
+ top open
+ [exEnd]
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|
+ because the topView does not forward its input into the fields.
+ Also, tabbing is not possible here)
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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 := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
- top open
+ top open
+ [exEnd]
- same, enables tabbing via the Tab key:
+ same, enables tabbing within the group via the Tab key
+ (but still, the mouse pointer must be in one of the fields):
+ [exBegin]
+ |top panel group field1 field2 field3|
- |top panel group field1 field2 field3|
+ top := StandardSystemView new.
+ top extent:200@200.
- top := StandardSystemView new.
- top extent:200@200.
+ panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
- 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.
- panel add:(field1 := EditField extent:(1.0 @ nil)).
- panel add:(field2 := EditField extent:(1.0 @ nil)).
- panel add:(field3 := EditField extent:(1.0 @ nil)).
+ field1 makeTabable.
+ field2 makeTabable.
+ field3 makeTabable.
+ top open
+ [exEnd]
+ individual makeTabable messages to the fields allows single
+ fields to be sticky (i.e. explicit click is needed to get out
+ of it) - this is very seldom required.
+ To make all fields tabable (the usual case), there is a shortCut:
+ [exBegin]
+ |top panel group field1 field2 field3|
- group := EnterFieldGroup new.
- group add:field1; add:field2; add:field3.
+ top := StandardSystemView new.
+ top extent:200@200.
+
+ panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
- field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- top open
+ 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 makeAllTabable.
+
+ top open
+ [exEnd]
- with a group - Return-key or CursorKey enables next field:
- input into topView is forwarded to the group:
-
- |top panel group field1 field2 field3|
+ use a delagation from the outerView to the group -
+ Return-key or CursorKey enables next field:
+ input for topView is delegated to the group, which also behaves
+ as a unit w.r.t. keyboard focus (move pointer in and out).
+ Again, without tabbing:
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
+
+ panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
- 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.
- panel add:(field1 := EditField extent:(1.0 @ nil)).
- panel add:(field2 := EditField extent:(1.0 @ nil)).
- panel add:(field3 := EditField extent:(1.0 @ nil)).
+ top delegate:group.
+ top open
+ [exEnd]
+
+
+ and, with tabbing:
+ [exBegin]
+ |top panel group field1 field2 field3|
+
+ top := StandardSystemView new.
+ top extent:200@200.
- group := EnterFieldGroup new.
- group add:field1; add:field2; add:field3.
+ 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)).
- top delegate:group.
- top open
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group makeAllTabable.
+
+ top delegate:group.
+ top open
+ [exEnd]
- as above, but close the box when the last field is left:
-
- |top panel group field1 field2 field3|
+ as above, but close the box when the last field is left
+ via return - notice, that tabbing still wraps around:
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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].
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
- top delegate:group.
- top open
-
-
+ top delegate:group.
+ top open
+ [exEnd]
- same as above, with Tab-key stepping:
-
- |top panel group field1 field2 field3|
+ in the next example, tabbing out of the last field
+ closes the box as well:
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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].
+ panel add:(field1 := EditField extent:(1.0 @ nil)).
+ panel add:(field2 := EditField extent:(1.0 @ nil)).
+ panel add:(field3 := EditField extent:(1.0 @ nil)).
- field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
+ group leaveOnTabLast:true.
- top delegate:group.
- top open
-
+ top delegate:group.
+ top open
+ [exEnd]
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:
(i.e. you can arrange your fields in multiple framedBoxes, panels or
subviews - independent of the tab-stepping order)
-
- |top panel group field1 field2 field3|
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView label:'reverse'.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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].
+ group := EnterFieldGroup new.
+ group add:field3; add:field2; add:field1.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
- top delegate:group.
- top open
+ top delegate:group.
+ top open
+ [exEnd]
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|
+ [exBegin]
+ |top panel group field1 field2 field3 model
+ value1 value2 value3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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].
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
- value1 := 'one'. value2 := 'two'. value3 := 'three'.
+ 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].
+ 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:.
+ 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.
+ top delegate:group.
+ top openModal.
- Transcript showCr:'value1: ' , value1.
- Transcript showCr:'value2: ' , value2.
- Transcript showCr:'value3: ' , value3.
+ Transcript showCr:'value1: ' , value1.
+ Transcript showCr:'value2: ' , value2.
+ Transcript showCr:'value3: ' , value3.
+ [exEnd]
- the above is done automatically for you, if you add inputFields
- to a dialogBox:
+ all of the above is done automatically for you,
+ if you add inputFields to a dialogBox.
+ Here, all fields use the same model, but different aspects:
+ [exBegin]
+ |box model
+ value1 value2 value3|
+
+ box := DialogBox new.
+ box extent:200@200.
+
+ value1 := 'one'. value2 := 'two'. value3 := 'three'.
- |box model
- value1 value2 value3|
+ 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 := DialogBox new.
- box extent:200@200.
+ (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:.
- value1 := 'one'. value2 := 'two'. value3 := 'three'.
+ box addOkButton.
+
+ box open.
- 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].
+ Transcript showCr:'value1: ' , value1.
+ Transcript showCr:'value2: ' , value2.
+ Transcript showCr:'value3: ' , value3.
+ [exEnd]
+
+ Here, the fields use different models, but the same aspect:
+ [exBegin]
+ |box model
+ valueHolder1 valueHolder2 valueHolder3|
+
+ box := DialogBox new.
+ box extent:200@200.
+
+ valueHolder1 := 'one' asValue.
+ valueHolder2 := 'two' asValue.
+ valueHolder3 := 'three' asValue.
- (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 addInputFieldOn:valueHolder1.
+ box addVerticalSpace.
+ box addInputFieldOn:valueHolder2.
+ box addVerticalSpace.
+ box addInputFieldOn:valueHolder3.
+
+ box addOkButton.
- box open.
+ box open.
- Transcript showCr:'value1: ' , value1.
- Transcript showCr:'value2: ' , value2.
- Transcript showCr:'value3: ' , value3.
+ Transcript showCr:'value1: ' , valueHolder1 value.
+ Transcript showCr:'value2: ' , valueHolder2 value.
+ Transcript showCr:'value3: ' , valueHolder3 value.
+ [exEnd]
"
+
+ "Created: 27.4.1996 / 16:43:28 / cg"
! !
!EnterFieldGroup methodsFor:'accessing'!
@@ -325,13 +432,37 @@
leaveAction := aBlock
!
+leaveOnTabLast:aBoolean
+ "specifies if leaving the last field via Tab
+ should leave the group or stay in the group.
+ (if staying, either wrap or not, depending on the setting of wrap)
+ The default is to stay in the group"
+
+ leaveOnTabLast := aBoolean
+
+ "Created: 27.4.1996 / 17:22:30 / cg"
+ "Modified: 27.4.1996 / 17:22:44 / cg"
+!
+
+makeAllTabable
+ "make all fields tabable"
+
+ fields do:[:field |
+ field makeTabable
+ ]
+
+ "Created: 27.4.1996 / 17:11:41 / cg"
+!
+
wrap:aBoolean
"specifies if leaving the last field via non-Return
- should wrap back to the first, or leave the group.
- The default is to stay in the input sequence and wrap back to
- the first field."
+ (i.e. Tab or Cursor-Down) should wrap back to the first,
+ or leave the group.
+ The default is to not leave the group and wrap back to the first field."
wrap := aBoolean
+
+ "Modified: 27.4.1996 / 17:19:50 / cg"
! !
!EnterFieldGroup methodsFor:'adding / removing'!
@@ -340,7 +471,7 @@
|thisIndex action|
fields isNil ifTrue:[
- fields := OrderedCollection new
+ fields := OrderedCollection new
].
fields add:aField.
thisIndex := fields size.
@@ -352,75 +483,78 @@
"set the fields enableAction to disable active field"
aField clickAction:[:field |
- self makeActive:field
+ self makeActive:field
].
"set the fields leaveAction to enable next field"
aField leaveAction:[:key |
- |next wg explicit nFields nextField|
+ |next wg explicit nFields nextField|
"/ currentField notNil ifTrue:[
"/ currentField disable.
"/ currentField hideCursor.
"/ ].
"/
- action := key.
- nFields := fields size.
+ action := key.
+ nFields := fields size.
- ((key == #CursorUp) or:[key == #PreviousField]) ifTrue:[
- (thisIndex == 1) ifTrue:[
- next := nFields
- ] ifFalse:[
- next := thisIndex - 1
- ]
- ].
- ((key == #CursorDown)
- or:[key == #NextField
- or:[key == #Tab]]) ifTrue:[
- (thisIndex == nFields) ifTrue:[
- next := 1.
- wrap == false ifTrue:[
- action := #Return.
- ].
- ] ifFalse:[
- next := thisIndex + 1
- ]
- ].
- (action == #Return) ifTrue:[
- (thisIndex == nFields) ifTrue:[
- leaveAction notNil ifTrue:[
- currentField := nil.
- leaveAction value.
- next := nil
- ] ifFalse:[
- next := 1
- ]
- ] ifFalse:[
- next := thisIndex + 1
- ]
- ].
- next notNil ifTrue:[
- nextField := fields at:next.
+ ((key == #CursorUp) or:[key == #PreviousField]) ifTrue:[
+ (thisIndex == 1) ifTrue:[
+ next := nFields
+ ] ifFalse:[
+ next := thisIndex - 1
+ ]
+ ].
+ ((key == #CursorDown)
+ or:[key == #NextField
+ or:[key == #Tab]]) ifTrue:[
+ (thisIndex == nFields) ifTrue:[
+ next := 1.
+ wrap == false ifTrue:[
+ action := #Return.
+ ].
+ ] ifFalse:[
+ next := thisIndex + 1
+ ]
+ ].
+ ((action == #Return)
+ or:[key == #Tab and:[leaveOnTabLast == true]]) ifTrue:[
+ (thisIndex == nFields) ifTrue:[
+ leaveAction notNil ifTrue:[
+ currentField := nil.
+ leaveAction value.
+ next := nil
+ ] ifFalse:[
+ next := 1
+ ]
+ ] ifFalse:[
+ next := thisIndex + 1
+ ]
+ ].
+ next notNil ifTrue:[
+ nextField := fields at:next.
- explicit := false.
- (wg := currentField windowGroup) notNil ifTrue:[
- wg focusView == currentField ifTrue:[
- explicit := true.
- ]
- ].
- explicit ifTrue:[
- wg focusView:nextField.
- ] ifFalse:[
- self makeActive:nextField
- ]
- ]
+ explicit := false.
+ (wg := currentField windowGroup) notNil ifTrue:[
+ wg focusView == currentField ifTrue:[
+ explicit := true.
+ ]
+ ].
+ explicit ifTrue:[
+ wg focusView:nextField.
+ ] ifFalse:[
+ self makeActive:nextField
+ ]
+ ]
].
fields size == 1 ifTrue:[
- "the first one"
- self makeActive:aField
+ "the first one"
+ self makeActive:aField
]
+
+ "Modified: 27.4.1996 / 17:21:09 / cg"
! !
!EnterFieldGroup methodsFor:'event forwarding'!
@@ -487,6 +621,28 @@
currentField notNil ifTrue:[
currentField keyRelease:key x:-1 y:-1
]
+!
+
+showFocus:onOrOff
+ "forward focus display to the active field "
+
+ currentField notNil ifTrue:[
+ currentField showFocus:onOrOff
+ ]
+
+ "Modified: 4.3.1996 / 22:18:22 / cg"
+ "Created: 27.4.1996 / 16:41:38 / cg"
+!
+
+showNoFocus:onOrOff
+ "forward nofocus display to the active field "
+
+ currentField notNil ifTrue:[
+ currentField showNoFocus:onOrOff
+ ]
+
+ "Modified: 4.3.1996 / 22:18:22 / cg"
+ "Created: 27.4.1996 / 16:42:07 / cg"
! !
!EnterFieldGroup methodsFor:'misc'!
@@ -522,5 +678,5 @@
!EnterFieldGroup class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libwidg/Attic/EFGroup.st,v 1.21 1996-04-25 16:33:37 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libwidg/Attic/EFGroup.st,v 1.22 1996-04-27 17:55:59 cg Exp $'
! !
--- a/EnterFieldGroup.st Sat Apr 27 10:12:28 1996 +0200
+++ b/EnterFieldGroup.st Sat Apr 27 19:55:59 1996 +0200
@@ -11,7 +11,7 @@
"
Object subclass:#EnterFieldGroup
- instanceVariableNames:'fields currentField leaveAction wrap'
+ instanceVariableNames:'fields currentField leaveAction wrap leaveOnTabLast'
classVariableNames:''
poolDictionaries:''
category:'Interface-Support'
@@ -39,21 +39,29 @@
enabling the next/prev field when a field is left.
Instances of this class keep track of which field of the group is the
currentField (i.e. the one getting keyboard input) and forwards input
- to the active field (having the inputField delegate its input to me).
+ to that one.
+ This is done by arranging for all of my fields to delegate their
+ input to me, which is then forwarded to the active field).
The block accessable as leaveAction is evaluated when the last
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).
+ Usually this block triggers accept on the fields (if they did not already)
+ and/or performs some followup processing and possibly 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.
+ By default, tabbing via #Tab is disabled - to enable it, send the field
+ a #makeTabable or #makeAllTabable to the group.
+
+ All of this here is low level stuff, providing a lot of freedom in
+ which keys are handled and how they perform.
+ Normally, these are not required for most users - the DialogBox sets up
+ things correctly for most cases.
+
[Instance variables:]
@@ -71,8 +79,17 @@
This is ignored, if no leaveAction was
defined.
+ leaveOnTabLast <Boolean> if true, tabbing out of the last
+ field leaves the group.
+ The default is false.
+
[author:]
Claus Gittinger
+
+
+ [see also:]
+ DialogBox
+ EditField
"
!
@@ -80,233 +97,323 @@
"
without a group - user has to enter mouse into the next field to activate it;
Cursor-keys dont work:
-
- |top panel field1 field2 field3|
+ [exBegin]
+ |top panel field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ panel add:(field1 := EditField extent:(1.0 @ nil)).
+ panel add:(field2 := EditField extent:(1.0 @ nil)).
+ panel add:(field3 := EditField extent:(1.0 @ nil)).
- top open
+ top open
+ [exEnd]
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|
+ because the topView does not forward its input into the fields.
+ Also, tabbing is not possible here)
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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 := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
- top open
+ top open
+ [exEnd]
- same, enables tabbing via the Tab key:
+ same, enables tabbing within the group via the Tab key
+ (but still, the mouse pointer must be in one of the fields):
+ [exBegin]
+ |top panel group field1 field2 field3|
- |top panel group field1 field2 field3|
+ top := StandardSystemView new.
+ top extent:200@200.
- top := StandardSystemView new.
- top extent:200@200.
+ panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
- 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.
- panel add:(field1 := EditField extent:(1.0 @ nil)).
- panel add:(field2 := EditField extent:(1.0 @ nil)).
- panel add:(field3 := EditField extent:(1.0 @ nil)).
+ field1 makeTabable.
+ field2 makeTabable.
+ field3 makeTabable.
+ top open
+ [exEnd]
+ individual makeTabable messages to the fields allows single
+ fields to be sticky (i.e. explicit click is needed to get out
+ of it) - this is very seldom required.
+ To make all fields tabable (the usual case), there is a shortCut:
+ [exBegin]
+ |top panel group field1 field2 field3|
- group := EnterFieldGroup new.
- group add:field1; add:field2; add:field3.
+ top := StandardSystemView new.
+ top extent:200@200.
+
+ panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
- field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- top open
+ 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 makeAllTabable.
+
+ top open
+ [exEnd]
- with a group - Return-key or CursorKey enables next field:
- input into topView is forwarded to the group:
-
- |top panel group field1 field2 field3|
+ use a delagation from the outerView to the group -
+ Return-key or CursorKey enables next field:
+ input for topView is delegated to the group, which also behaves
+ as a unit w.r.t. keyboard focus (move pointer in and out).
+ Again, without tabbing:
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
+
+ panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
- 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.
- panel add:(field1 := EditField extent:(1.0 @ nil)).
- panel add:(field2 := EditField extent:(1.0 @ nil)).
- panel add:(field3 := EditField extent:(1.0 @ nil)).
+ top delegate:group.
+ top open
+ [exEnd]
+
+
+ and, with tabbing:
+ [exBegin]
+ |top panel group field1 field2 field3|
+
+ top := StandardSystemView new.
+ top extent:200@200.
- group := EnterFieldGroup new.
- group add:field1; add:field2; add:field3.
+ 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)).
- top delegate:group.
- top open
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group makeAllTabable.
+
+ top delegate:group.
+ top open
+ [exEnd]
- as above, but close the box when the last field is left:
-
- |top panel group field1 field2 field3|
+ as above, but close the box when the last field is left
+ via return - notice, that tabbing still wraps around:
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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].
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
- top delegate:group.
- top open
-
-
+ top delegate:group.
+ top open
+ [exEnd]
- same as above, with Tab-key stepping:
-
- |top panel group field1 field2 field3|
+ in the next example, tabbing out of the last field
+ closes the box as well:
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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].
+ panel add:(field1 := EditField extent:(1.0 @ nil)).
+ panel add:(field2 := EditField extent:(1.0 @ nil)).
+ panel add:(field3 := EditField extent:(1.0 @ nil)).
- field1 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field2 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
- field3 leaveKeys:(EditField defaultLeaveKeys copyWith:#Tab).
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
+ group leaveOnTabLast:true.
- top delegate:group.
- top open
-
+ top delegate:group.
+ top open
+ [exEnd]
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:
(i.e. you can arrange your fields in multiple framedBoxes, panels or
subviews - independent of the tab-stepping order)
-
- |top panel group field1 field2 field3|
+ [exBegin]
+ |top panel group field1 field2 field3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView label:'reverse'.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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].
+ group := EnterFieldGroup new.
+ group add:field3; add:field2; add:field1.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
- top delegate:group.
- top open
+ top delegate:group.
+ top open
+ [exEnd]
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|
+ [exBegin]
+ |top panel group field1 field2 field3 model
+ value1 value2 value3|
- top := StandardSystemView new.
- top extent:200@200.
+ top := StandardSystemView new.
+ top extent:200@200.
- panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
+ 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)).
+ 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].
+ group := EnterFieldGroup new.
+ group add:field1; add:field2; add:field3.
+ group leaveAction:[top destroy].
+ group makeAllTabable.
- value1 := 'one'. value2 := 'two'. value3 := 'three'.
+ 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].
+ 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:.
+ 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.
+ top delegate:group.
+ top openModal.
- Transcript showCr:'value1: ' , value1.
- Transcript showCr:'value2: ' , value2.
- Transcript showCr:'value3: ' , value3.
+ Transcript showCr:'value1: ' , value1.
+ Transcript showCr:'value2: ' , value2.
+ Transcript showCr:'value3: ' , value3.
+ [exEnd]
- the above is done automatically for you, if you add inputFields
- to a dialogBox:
+ all of the above is done automatically for you,
+ if you add inputFields to a dialogBox.
+ Here, all fields use the same model, but different aspects:
+ [exBegin]
+ |box model
+ value1 value2 value3|
+
+ box := DialogBox new.
+ box extent:200@200.
+
+ value1 := 'one'. value2 := 'two'. value3 := 'three'.
- |box model
- value1 value2 value3|
+ 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 := DialogBox new.
- box extent:200@200.
+ (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:.
- value1 := 'one'. value2 := 'two'. value3 := 'three'.
+ box addOkButton.
+
+ box open.
- 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].
+ Transcript showCr:'value1: ' , value1.
+ Transcript showCr:'value2: ' , value2.
+ Transcript showCr:'value3: ' , value3.
+ [exEnd]
+
+ Here, the fields use different models, but the same aspect:
+ [exBegin]
+ |box model
+ valueHolder1 valueHolder2 valueHolder3|
+
+ box := DialogBox new.
+ box extent:200@200.
+
+ valueHolder1 := 'one' asValue.
+ valueHolder2 := 'two' asValue.
+ valueHolder3 := 'three' asValue.
- (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 addInputFieldOn:valueHolder1.
+ box addVerticalSpace.
+ box addInputFieldOn:valueHolder2.
+ box addVerticalSpace.
+ box addInputFieldOn:valueHolder3.
+
+ box addOkButton.
- box open.
+ box open.
- Transcript showCr:'value1: ' , value1.
- Transcript showCr:'value2: ' , value2.
- Transcript showCr:'value3: ' , value3.
+ Transcript showCr:'value1: ' , valueHolder1 value.
+ Transcript showCr:'value2: ' , valueHolder2 value.
+ Transcript showCr:'value3: ' , valueHolder3 value.
+ [exEnd]
"
+
+ "Created: 27.4.1996 / 16:43:28 / cg"
! !
!EnterFieldGroup methodsFor:'accessing'!
@@ -325,13 +432,37 @@
leaveAction := aBlock
!
+leaveOnTabLast:aBoolean
+ "specifies if leaving the last field via Tab
+ should leave the group or stay in the group.
+ (if staying, either wrap or not, depending on the setting of wrap)
+ The default is to stay in the group"
+
+ leaveOnTabLast := aBoolean
+
+ "Created: 27.4.1996 / 17:22:30 / cg"
+ "Modified: 27.4.1996 / 17:22:44 / cg"
+!
+
+makeAllTabable
+ "make all fields tabable"
+
+ fields do:[:field |
+ field makeTabable
+ ]
+
+ "Created: 27.4.1996 / 17:11:41 / cg"
+!
+
wrap:aBoolean
"specifies if leaving the last field via non-Return
- should wrap back to the first, or leave the group.
- The default is to stay in the input sequence and wrap back to
- the first field."
+ (i.e. Tab or Cursor-Down) should wrap back to the first,
+ or leave the group.
+ The default is to not leave the group and wrap back to the first field."
wrap := aBoolean
+
+ "Modified: 27.4.1996 / 17:19:50 / cg"
! !
!EnterFieldGroup methodsFor:'adding / removing'!
@@ -340,7 +471,7 @@
|thisIndex action|
fields isNil ifTrue:[
- fields := OrderedCollection new
+ fields := OrderedCollection new
].
fields add:aField.
thisIndex := fields size.
@@ -352,75 +483,78 @@
"set the fields enableAction to disable active field"
aField clickAction:[:field |
- self makeActive:field
+ self makeActive:field
].
"set the fields leaveAction to enable next field"
aField leaveAction:[:key |
- |next wg explicit nFields nextField|
+ |next wg explicit nFields nextField|
"/ currentField notNil ifTrue:[
"/ currentField disable.
"/ currentField hideCursor.
"/ ].
"/
- action := key.
- nFields := fields size.
+ action := key.
+ nFields := fields size.
- ((key == #CursorUp) or:[key == #PreviousField]) ifTrue:[
- (thisIndex == 1) ifTrue:[
- next := nFields
- ] ifFalse:[
- next := thisIndex - 1
- ]
- ].
- ((key == #CursorDown)
- or:[key == #NextField
- or:[key == #Tab]]) ifTrue:[
- (thisIndex == nFields) ifTrue:[
- next := 1.
- wrap == false ifTrue:[
- action := #Return.
- ].
- ] ifFalse:[
- next := thisIndex + 1
- ]
- ].
- (action == #Return) ifTrue:[
- (thisIndex == nFields) ifTrue:[
- leaveAction notNil ifTrue:[
- currentField := nil.
- leaveAction value.
- next := nil
- ] ifFalse:[
- next := 1
- ]
- ] ifFalse:[
- next := thisIndex + 1
- ]
- ].
- next notNil ifTrue:[
- nextField := fields at:next.
+ ((key == #CursorUp) or:[key == #PreviousField]) ifTrue:[
+ (thisIndex == 1) ifTrue:[
+ next := nFields
+ ] ifFalse:[
+ next := thisIndex - 1
+ ]
+ ].
+ ((key == #CursorDown)
+ or:[key == #NextField
+ or:[key == #Tab]]) ifTrue:[
+ (thisIndex == nFields) ifTrue:[
+ next := 1.
+ wrap == false ifTrue:[
+ action := #Return.
+ ].
+ ] ifFalse:[
+ next := thisIndex + 1
+ ]
+ ].
+ ((action == #Return)
+ or:[key == #Tab and:[leaveOnTabLast == true]]) ifTrue:[
+ (thisIndex == nFields) ifTrue:[
+ leaveAction notNil ifTrue:[
+ currentField := nil.
+ leaveAction value.
+ next := nil
+ ] ifFalse:[
+ next := 1
+ ]
+ ] ifFalse:[
+ next := thisIndex + 1
+ ]
+ ].
+ next notNil ifTrue:[
+ nextField := fields at:next.
- explicit := false.
- (wg := currentField windowGroup) notNil ifTrue:[
- wg focusView == currentField ifTrue:[
- explicit := true.
- ]
- ].
- explicit ifTrue:[
- wg focusView:nextField.
- ] ifFalse:[
- self makeActive:nextField
- ]
- ]
+ explicit := false.
+ (wg := currentField windowGroup) notNil ifTrue:[
+ wg focusView == currentField ifTrue:[
+ explicit := true.
+ ]
+ ].
+ explicit ifTrue:[
+ wg focusView:nextField.
+ ] ifFalse:[
+ self makeActive:nextField
+ ]
+ ]
].
fields size == 1 ifTrue:[
- "the first one"
- self makeActive:aField
+ "the first one"
+ self makeActive:aField
]
+
+ "Modified: 27.4.1996 / 17:21:09 / cg"
! !
!EnterFieldGroup methodsFor:'event forwarding'!
@@ -487,6 +621,28 @@
currentField notNil ifTrue:[
currentField keyRelease:key x:-1 y:-1
]
+!
+
+showFocus:onOrOff
+ "forward focus display to the active field "
+
+ currentField notNil ifTrue:[
+ currentField showFocus:onOrOff
+ ]
+
+ "Modified: 4.3.1996 / 22:18:22 / cg"
+ "Created: 27.4.1996 / 16:41:38 / cg"
+!
+
+showNoFocus:onOrOff
+ "forward nofocus display to the active field "
+
+ currentField notNil ifTrue:[
+ currentField showNoFocus:onOrOff
+ ]
+
+ "Modified: 4.3.1996 / 22:18:22 / cg"
+ "Created: 27.4.1996 / 16:42:07 / cg"
! !
!EnterFieldGroup methodsFor:'misc'!
@@ -522,5 +678,5 @@
!EnterFieldGroup class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libwidg/EnterFieldGroup.st,v 1.21 1996-04-25 16:33:37 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libwidg/EnterFieldGroup.st,v 1.22 1996-04-27 17:55:59 cg Exp $'
! !