RadioButtonGroup.st
author Claus Gittinger <cg@exept.de>
Mon, 15 Jul 1996 16:42:09 +0200
changeset 791 f76f4541742f
parent 752 a5781b7ff8cb
child 1088 40de2fe27607
permissions -rw-r--r--
adding a button implies making it a radioButton

"
 COPYRIGHT (c) 1991 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

OrderedCollection subclass:#RadioButtonGroup
	instanceVariableNames:'valueChannel groupID'
	classVariableNames:''
	poolDictionaries:''
	category:'Views-Support'
!

!RadioButtonGroup  class methodsFor:'documentation '!

copyright
"
 COPYRIGHT (c) 1991 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    RadioButtonGroups control the interaction between RadioButtons
    turning off other button(s) when one of the group is pressed.
    To group some buttons (and have one-on behavior) use:

        |g|

        g := RadioButtonGroup new.
        ...
        b1 := RadioButton label:....
        g add:b1
        ...
        b2 := RadioButton label:....
        g add:b2
        ...

    A radioButtonGroup installs itself as the model of its toggles or
    radioButtons. Therefore, you can no longer operate the individual
    elements on models.
    Instead, the group now provides a valueHolder which takes as value 
    the index of the selected toggle. You can set/get this valueHolder
    via the valueChannel:/valueChannel messages.
    See the last example for how this is done.

    The groupID instance variable is not required for normal operation;
    the interface builder uses it to give a button-group some descriptive 
    (unique) name.

    [author:]
        Claus Gittinger
"

    "Modified: 25.4.1996 / 17:40:00 / cg"
!

examples 
"
    example (using Toggles for 'at most one-on behavior'):
                                                                        [exBegin]
        |top panel toggle b group|

        top := StandardSystemView new.
        panel := HorizontalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
        group := RadioButtonGroup new.
        b := Toggle label:'one' in:panel.
        group add:b.
        b := Toggle label:'two' in:panel.
        group add:b.
        b := Toggle label:'three' in:panel.
        group add:b.
        top extent:(panel preferredExtent).
        top open.
                                                                        [exEnd]


    example (using RadioButtons for 'one-on behavior'):
                                                                        [exBegin]
        |top panel toggle b group|

        top := StandardSystemView new.
        panel := HorizontalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
        group := RadioButtonGroup new.
        b := RadioButton label:'one' in:panel.
        group add:b.
        b := RadioButton label:'two' in:panel.
        group add:b.
        b := RadioButton label:'three' in:panel.
        group add:b.
        top extent:(panel preferredExtent).
        top open.
                                                                        [exEnd]


    example (using Buttons for 'none-on behavior'; but the groups value remembers the last button):
                                                                        [exBegin]
        |top panel toggle b group|

        top := StandardSystemView new.
        panel := HorizontalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
        group := RadioButtonGroup new.
        b := Button label:'one' in:panel.
        group add:b.
        b := Button label:'two' in:panel.
        group add:b.
        b := Button label:'three' in:panel.
        group add:b.
        top extent:(panel preferredExtent).
        top open.
        group valueChannel inspect
                                                                        [exEnd]


    example (same, with button 'two' initially on):
                                                                        [exBegin]
        |top panel toggle b group|

        top := StandardSystemView new.
        panel := HorizontalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
        group := RadioButtonGroup new.
        b := RadioButton label:'one' in:panel.
        group add:b.
        b := RadioButton label:'two' in:panel.
        group add:b.
        group value:2.
        b := RadioButton label:'three' in:panel.
        group add:b.
        top extent:(panel preferredExtent).
        top open.
                                                                        [exEnd]


    using checkBoxes (these have a label included):
                                                                        [exBegin]
        |top panel toggle b group|

        top := StandardSystemView new.
        panel := VerticalPanelView origin:0.0@0.0 corner:1.0@1.0 in:top.
        panel horizontalLayout:#left.
        group := RadioButtonGroup new.
        b := CheckBox label:'one' in:panel.
        group add:b.
        b := CheckBox label:'two' in:panel.
        group add:b.
        b := CheckBox label:'three' in:panel.
        group add:b.
        top extent:(panel preferredExtent).
        top open.
                                                                        [exEnd]


    example (operating on a model)
                                                                        [exBegin]
        |selected dialog group|

        selected := 2 asValue.
        dialog := Dialog new.
        group := RadioButtonGroup new.
        group add:(dialog addCheckBox:'one' on:nil) toggleView.
        group add:(dialog addCheckBox:'two' on:nil) toggleView.
        group add:(dialog addCheckBox:'three' on:nil) toggleView.
        group valueChannel:selected.
        dialog addAbortButton; addOkButton.
        dialog open.
        dialog accepted ifTrue:[
            Transcript showCR:'you selected: ' , selected value printString
        ] ifFalse:[
            Transcript showCR:'aborted'
        ]
                                                                        [exEnd]
"

    "Created: 15.11.1995 / 17:14:53 / cg"
    "Modified: 27.4.1996 / 19:27:37 / cg"
!

version
    ^ '$Header: /cvs/stx/stx/libwidg/RadioButtonGroup.st,v 1.24 1996-07-15 14:42:09 cg Exp $'
! !

!RadioButtonGroup methodsFor:'accessing'!

groupID
    ^ groupID

    "Modified: 5.9.1995 / 16:04:33 / claus"
!

groupID:aSymbol 
    groupID := aSymbol

    "Modified: 5.9.1995 / 16:04:28 / claus"
! !

!RadioButtonGroup methodsFor:'accessing-mvc'!

value
    ^ valueChannel value
!

value:anIndex
    valueChannel value:anIndex
!

valueChannel
    ^ valueChannel
!

valueChannel:aValueHolder
    |oldValue newValue|

    valueChannel notNil ifTrue:[oldValue := valueChannel value].
    valueChannel := aValueHolder.
    (newValue := valueChannel value) ~~ oldValue ifTrue:[
	(self at:newValue) turnOnWithAction
    ]
! !

!RadioButtonGroup methodsFor:'adding / removing'!

add:aRadioButton
    |c|

    super add:aRadioButton.

    "
     this would work, if dependencies were not weak ...
    "
"/    aRadioButton addDependent:self.


    "
     therefore, we have to install ourself as model of the buttons/toggles
     creating a valueChannel, if there is none yet.
    "
    valueChannel isNil ifTrue:[
        valueChannel := 0 asValue
    ].
    aRadioButton isOn ifTrue:[valueChannel value:self size].
    aRadioButton model:self; aspectMessage:#queryFrom:; changeMessage:#elementChanged:from:.

    (c := aRadioButton controller) notNil ifTrue:[
        c beRadioButton
    ] ifFalse:[    
        aRadioButton controller:(RadioButtonController new).
    ]

    "Modified: 15.7.1996 / 14:07:19 / cg"
! !

!RadioButtonGroup methodsFor:'update'!

elementChanged:aToggle
    "historic compatibility leftover - will vanish"

    ^ self elementChanged:true from:aToggle
!

elementChanged:value from:aToggle
    "some element changed its value - find it, turn the others off
     and update my value"

    |newValue|

    self keysAndValuesDo:[:index :aComponent |
       ((aToggle == aComponent) or:[aToggle isComponentOf:aComponent]) ifTrue:[
            value ifTrue:[newValue := index]   
        ] ifFalse:[
"/            aComponent isOn ifTrue:[
"/               aComponent turnOff
"/            ]
        ]
    ].
"/    aToggle turnOn.
    valueChannel value:newValue.
    self changed:#queryFrom:

    "Modified: 21.9.1995 / 13:42:06 / claus"
    "Modified: 5.6.1996 / 14:25:51 / cg"
!

queryFrom:aToggle
    "a query from a toggle, if its the selected one"

    self keysAndValuesDo:[:index :aComponent |
       ((aToggle == aComponent) or:[aToggle isComponentOf:aComponent]) ifTrue:[
            ^ valueChannel value == index
       ]
    ].
    ^ false

    "Modified: 5.6.1996 / 14:25:53 / cg"
!

update:something with:someArgument from:changedButton
    "
     a RadioButton in this group has changed - notify the others
    "

    self elementChanged:(changedButton isOn) from:changedButton
! !