OptionBox.st
author Stefan Vogel <sv@exept.de>
Fri, 28 Feb 2003 18:03:17 +0100
changeset 2700 d6bc43ddc80f
parent 2669 182aa7a00d83
child 2711 e18e9edca978
permissions -rw-r--r--
Spelling (du Dubl!)

"
 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.
"

"{ Package: 'stx:libwidg' }"

DialogBox subclass:#OptionBox
	instanceVariableNames:'formLabel textLabel buttons actions defaultButtonIndex'
	classVariableNames:'WarnBitmap'
	poolDictionaries:''
	category:'Views-DialogBoxes'
!

!OptionBox 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
"
   CAVEAT: this is a leftover - functionality has been merged into DialogBox
   PLEASE use one of the `Dialog chooseXXX' methods nstead of OptionBox.


   Historic note:
      originally, ST/X had separate classes for the various entry methods;
      there were YesNoBox, EnterBox, InfoBox and so on.
      In the meantime, the DialogBox class (and therefore its alias: Dialog)
      is going to duplicate most funcionality found in these classes.

      In the future, those existing subclasses' functionality is going to
      be moved fully into Dialog, and the subclasses will be replaced by dummy
      delegators. (They will be kept for backward compatibility, though).


    OptionBoxes are like YesNoBoxes but with as many buttons as you like;
    this will finally be a superclass of WarnBox and YesNoBox - or maybe merged
    all into DialogBox..
    Use them for multiway questions.
    For a consistent user interface, the rightmost button is the default return
    button (i.e. pressing return in the box performs this buttons function).

    [author:]
        Claus Gittinger

    [see also:]
        DialogBox
"
!

examples
"
                                                                        [exBegin]
    |box|

    box := OptionBox title:'hello' numberOfOptions:4.
    box showAtPointer
                                                                        [exEnd]


                                                                        [exBegin]
    |box|
    box := OptionBox title:'hello' numberOfOptions:3.
    box buttonTitles:#('one' 'two' 'three').
    box showAtPointer
                                                                        [exEnd]

 performing an action:

                                                                        [exBegin]
    |box|
    box := OptionBox title:'hello' numberOfOptions:3.
    box buttonTitles:#('one' 'two' 'three').
    box action:[:which | Transcript show:'button ';
                                    show: which;
                                    showCR:' was pressed'].
    box showAtPointer
                                                                        [exEnd]

 returning a value:
                                                                        [exBegin]
    |what|

    what := OptionBox 
                  request:('text has not been accepted.\\Your modifications will be lost when continuing.') withCRs
                  label:' Attention'
                  form:(WarningBox iconBitmap)
                  buttonLabels:#('abort' 'accept' 'continue')
                  values:#(#abort #accept #continue).
    Transcript showCR:what.
                                                                        [exEnd]
"
! !

!OptionBox class methodsFor:'instance creation'!

title:titleString numberOfOptions:nOptions
    "create a new optionBox with title, aTitleString and nOptions options"

    |box|

    box := (self basicNew) numberOfOptions:nOptions.
    box device:Screen current.
    box initialize.
    box title:titleString.
    ^ box
! !

!OptionBox class methodsFor:'easy startup'!

forRequest:title label:label form:aForm buttonLabels:labels values:values default:defaultValue
    "create a new optionBox and return it.
     Does not open the box."

    |box|

    box := OptionBox title:title numberOfOptions:(labels size).
    box buttonTitles:labels.
    box defaultButtonIndex:(values indexOf:defaultValue). 
    box label:label; form:aForm.
    ^ box

    "Modified: / 23.2.2000 / 11:59:32 / cg"
!

request:title buttonLabels:labels values:values 
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection."

    ^ self request:title label:title buttonLabels:labels values:values

    "
     OptionBox 
        request:'please select any'
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)   
    "
!

request:title buttonLabels:labels values:values default:defaultValue
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection. (nil if cancelled)"

    ^ self
        request:title label:title form:(YesNoBox iconBitmap) buttonLabels:labels values:values 
        default:defaultValue onCancel:defaultValue

    "
     OptionBox 
        request:'please select'
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)   
        default:3   
    "
!

request:title label:label buttonLabels:labels values:values 
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection."

    ^ self 
        request:title label:label form:(YesNoBox iconBitmap)
        buttonLabels:labels values:values default:nil onCancel:nil

    "
     OptionBox 
        request:'please select'
        label:'select any'
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)   
    "
!

request:title label:label buttonLabels:labels values:values default:defaultValue
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection. (nil if cancelled)"

    ^ self
        request:title label:label form:(YesNoBox iconBitmap) buttonLabels:labels values:values 
        default:defaultValue onCancel:defaultValue

    "
     OptionBox 
        request:'please select'
        label:'select any'
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)   
        default:3   
    "
!

request:title label:label buttonLabels:labels values:values default:defaultValue onCancel:cancelValue
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection. (nil if cancelled)"

    ^ self
        request:title label:label form:(YesNoBox iconBitmap) buttonLabels:labels values:values 
        default:defaultValue onCancel:cancelValue

    "
     OptionBox 
        request:'please select'
        label:'select any'
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)   
        default:3   
        onCancel:2   
    "
!

request:title label:label form:aForm buttonLabels:labels values:values 
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection."

    ^ self request:title label:label form:aForm buttonLabels:labels values:values default:nil onCancel:nil

    "
     OptionBox 
        request:'please select'
        label:'select any'
        form:(WarningBox iconBitmap)
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)
    "
!

request:title label:label form:aForm buttonLabels:labels values:values default:defaultValue
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection. (nil if cancelled)"

    ^ self
        request:title label:label form:aForm buttonLabels:labels values:values 
        default:defaultValue onCancel:defaultValue

    "
     OptionBox 
        request:'please select'
        label:'select any'
        form:(WarningBox iconBitmap)
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)
        default:3
    "
!

request:title label:label form:aForm buttonLabels:labels values:values default:defaultValue onCancel:cancelValue
    "create a new optionBox, open it modal and return the value of
     the corresponding values collection. (cancelValue if cancelled)"

    |box retVal|

    retVal := cancelValue.
    box := self
                forRequest:title 
                label:label 
                form:aForm 
                buttonLabels:labels 
                values:values 
                default:defaultValue.

    box action:[:n | retVal := values at:n].
    box showAtPointer.
    box destroy.

    ^ retVal

    "
     OptionBox 
        request:'please select'
        label:'select any'
        form:(WarningBox iconBitmap)
        buttonLabels:#('one' 'two' 'three')
        values:#(1 2 3)
        default:3
        onCancel:nil
    "

    "Modified: / 23.2.2000 / 11:59:32 / cg"
! !

!OptionBox methodsFor:'accessing'!

action:actionBlock
    "define a single the action for all buttons.
     The action will be evaluated with the button index as argument."

    buttons keysAndValuesDo:[:index :button |
	button action:[
		       button turnOffWithoutRedraw.
		       self hide.
		       actionBlock value:index
		      ]
    ].
!

actions:actionBlocks
    "define the actions"

    actions := actionBlocks
!

buttonTitles:titles actions:actionBlocks
    "define both button titles and actions"

    self buttonTitles:titles.
    actions := actionBlocks.
!

buttons
    "return the buttons collection"

    ^ buttons
!

defaultButtonIndex:index
    "define which button is the default (i.e. return-) button.
     By default, no returnButton is setup. The argument must be an
     index 1..nButtons, or nil"

    defaultButtonIndex notNil ifTrue:[
        (buttons at:defaultButtonIndex) isReturnButton:false
    ].
    (index notNil and:[index ~~ 0]) ifTrue:[
        defaultButtonIndex := index.
        defaultButtonIndex notNil ifTrue:[
            (buttons at:defaultButtonIndex) isReturnButton:true 
        ].
    ]

    "Modified: 18.10.1996 / 14:53:36 / cg"
!

numberOfOptions
    "return the number of options"

    ^ buttons size
!

numberOfOptions:nOptions
    "set the number of options - this is a private interface"

    buttons := (OrderedCollection new:nOptions) grow:nOptions.
    actions := (OrderedCollection new:nOptions) grow:nOptions

    "Modified: 18.10.1996 / 14:54:30 / cg"
! !

!OptionBox methodsFor:'accessing-look'!

buttonTitles:titles
    "set the button titles"

    titles keysAndValuesDo:[:index :aString |
	|b|

	(b := buttons at:index) label:aString.
	b resize.
    ].
    shown ifTrue:[self resize]
!

form:aFormOrImage
    "set the image shown in the label-view"

    |mm|

    mm := ViewSpacing.
    formLabel form:aFormOrImage.
    textLabel origin:((mm + formLabel width + mm) @ mm).

!

formLabel
    "return the label-view which displays a bitmap"

    ^ formLabel
!

image:aFormOrImage
    "set the image shown in the label-view"

    self form:aFormOrImage

    "Created: / 16.11.2001 / 15:20:02 / cg"
!

textLabel
    "return the label-view which displays a message string"

    ^ textLabel
!

title:aString
    "set the boxes title"

    aString ~= textLabel label ifTrue:[
	textLabel label:aString withoutSeparators.
	textLabel forceResize.
	shown ifTrue:[self resize]
    ]
!

title:aString numberOfOptions:nOptions
    "set the boxes title and number of options"

    self title:aString.
    buttons grow:nOptions.
    actions grow:nOptions
! !

!OptionBox methodsFor:'events'!

keyPress:aKey x:x y:y
    "return-key duplicates ok-function if acceptReturnAsOK is true"

    <resource: #keyboard (#Return)>

    |action|

    defaultButtonIndex notNil ifTrue:[
        (aKey == #Return) ifTrue:[
            self hide.
            action := actions at:defaultButtonIndex.
            action notNil ifTrue:[
                action value
            ]
        ]
    ].
    super keyPress:aKey x:x y:y

    "Modified: 7.3.1996 / 13:17:36 / cg"
! !

!OptionBox methodsFor:'initialization'!

initFormBitmap
    WarnBitmap isNil ifTrue:[
        WarnBitmap := WarningBox iconBitmap.
"/        WarnBitmap := Image fromFile:'bitmaps/Warning.xbm' resolution:100 on:Display 
    ].
    formLabel form:WarnBitmap

    "Modified: / 25.5.1999 / 16:08:06 / cg"
!

initialize
    |nButt mm|

    super initialize.

    mm := ViewSpacing.

    formLabel := Label in:self.
    self initFormBitmap.
    formLabel borderWidth:0.
    formLabel origin:(mm @ mm).

    textLabel := Label label:'Select' in:self.
    textLabel borderWidth:0.
    textLabel origin:((mm + formLabel width + mm) @ mm).

"/    buttonPanel isNil ifTrue:[
"/        buttonPanel := HorizontalPanelView origin:(0.0 @ 1.0) corner:(1.0 @ 1.0) in:self.
"/    ].
    buttonPanel 
        bottomInset:mm;
        topInset:(font height + mm * 2) negated.
    buttonPanel 
        borderWidth:0; 
        horizontalLayout:#fitSpace.

    nButt := buttons size.

    1 to:nButt do:[:index |
        |button|

        button := Button label:'press'.
        button action:[
                       |action|

                       (buttons at:index) turnOffWithoutRedraw.
                       self hide.
                       action := actions at:index.
                       action notNil ifTrue:[
                           action value
                       ]
                      ].
"/        index == nButt ifTrue:[
"/            button isReturnButton:true
"/        ].
        buttonPanel addSubView:button.
        buttons at:index put:button.
    ].

    "
     |box|

     box := OptionBox title:'hello' numberOfOptions:4.
     box open
    "

    "Modified: / 27.7.1998 / 19:37:17 / cg"
! !

!OptionBox methodsFor:'queries'!

preferredExtent 
    "return a size to make everything fit into myself"

    |w w1 h maxH prefPanel mm|

    "/ If I have an explicit preferredExtent ..

    preferredExtent notNil ifTrue:[
        ^ preferredExtent
    ].

    mm := ViewSpacing.

    w1 := (mm * 3) + formLabel width + textLabel width.
    prefPanel := buttonPanel preferredExtent.
    w := w1 max:prefPanel x.

"/    maxH := 0.
"/    buttons do:[:button |
"/        maxH := maxH max:(button preferredExtent y)
"/    ].
    maxH := prefPanel y.

    h := (mm * 4)
         + ((formLabel height) max:(textLabel height))
         + maxH.

    ^ w @ h

    "Modified: 19.7.1996 / 20:45:11 / cg"
! !

!OptionBox class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libwidg/OptionBox.st,v 1.55 2003-02-28 17:02:33 stefan Exp $'
! !