DataSetColumn.st
author ca
Wed, 12 Nov 1997 17:27:30 +0100
changeset 614 8316c869d4df
parent 607 a5e0c2bf1370
child 621 620553e6a537
permissions -rw-r--r--
support of readSelector with arguments

"
 COPYRIGHT (c) 1997 by Claus Gittinger / eXept Software AG
              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.
"




Object subclass:#DataSetColumn
	instanceVariableNames:'columnNumber dataSet label minWidth width description form form2
		formInset textInset writeSelector drawableAction backgroundColor
		foregroundColor'
	classVariableNames:''
	poolDictionaries:''
	category:'Views-DataSet'
!

!DataSetColumn class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1997 by Claus Gittinger / eXept Software AG
              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
"
    represent one single column description of a DataSetView

    [Instance variables:]

        description     <DataSetColumnSpec>     the column description
        dataSet         <DSVColumnView>         the view it belongs to
        width           <Integer>               width of column
        minWidth        <Integer>               minimum required width by the column
        formInset       <Integer>               top inset of a form
        textInset       <Integer>               top inset of a string
        form            <Form>                  a form drawn when a cell is unselected
        form2           <Form>                  a second form (used by Toggle off).
        label           <misc>                  cellLabel on device

    [author:]
        Claus Atzkern

    [see also:]
        DataSetColumnSpec
        DSVColumnView
        DataSetView
"


! !

!DataSetColumn methodsFor:'accessing'!

at:aRowNr
    "get the value of the raw at an index, aRowNr
    "
    ^ description row:(dataSet at:aRowNr) at:columnNumber
!

at:aRowNr put:something
    "set the value of the raw at an index, aRowNr
    "
    description row:(dataSet at:aRowNr) at:columnNumber put:something
!

backgroundColor
    ^ backgroundColor
!

foregroundColor
    ^ foregroundColor
!

label
    "get the label assigned to the column
    "
    ^ label


!

width
    "returns the width in pixels
    "
    |end|

    width notNil ifTrue:[ ^ width ].                            "/ already computed

    (    (width := description width)    ~~ 0                   "/ fixed size
     or:[(width := description minWidth) ~~ 0]                  "/ start size
    ) ifFalse:[
        drawableAction notNil ifTrue:[
            "/ take maximum 10 entries to calculate the width;
            "/ can be resized later if neccessary

            end := 10 min:dataSet numberOfRows.

            1 to:end do:[:aRowNr||lbl|
                lbl := drawableAction value:aRowNr.

                (lbl respondsTo:#widthOn:) ifTrue:[
                    width := width max:(lbl widthOn:dataSet)
                ] ifFalse:[
                    lbl notNil ifTrue:[
                        width := width max:(lbl displayString widthOn:dataSet)
                    ]
                ]
            ].
            description editorType ~~ #None ifTrue:[
                width := width + (dataSet font widthOn:dataSet device)
            ].
            form notNil ifTrue:[
                width := width + form width
            ]
        ] ifFalse:[
            width := width + form2 width
        ].
        label notNil ifTrue:[
            width := width max:(label widthOn:dataSet)
        ].
    ].
    ^ width := minWidth := width + dataSet separatorSize + (2 * dataSet horizontalSpacing).
!

width:aWidth
    "set the width
    "
    |w|

    (w := description width) ~~ 0 ifTrue:[             "/ fixed size
        width := minWidth := w
    ] ifFalse:[
        width := aWidth max:minWidth
    ].

! !

!DataSetColumn methodsFor:'drawing'!

drawFrom:start to:stop yTop:yTop yBot:yBot with:fgColor and:bgColor
    "redraw rows between start and stop
    "
    |lgCol dkCol fg bg val drawColSep n isLast lblFg lblBg
     rowHeight "{ Class:SmallInteger }"
     nTimes    "{ Class:SmallInteger }"
     sepSize   "{ Class:SmallInteger }"
     y         "{ Class:SmallInteger }"
     y1        "{ Class:SmallInteger }"
     x         "{ Class:SmallInteger }"
     w         "{ Class:SmallInteger }"
    |
    rowHeight := dataSet rowHeight.
    nTimes    := stop - start + 1.
    sepSize   := dataSet separatorSize.

    (bg := backgroundColor) isNil ifTrue:[
        bg := bgColor
    ] ifFalse:[
        dataSet paint:bg.
        dataSet fillRectangleX:0 y:yTop width:width height:(nTimes * rowHeight - 1)
    ].
    (fg := foregroundColor) notNil ifTrue:[
        lgCol := fg
    ] ifFalse:[
        fg := fgColor.
        lgCol := dataSet hgLgFgColor.
    ].
    dkCol := dataSet hgLgBgColor.
    y     := yTop + textInset.
    x     := dataSet horizontalSpacing.
    val   := nil.

    start to:stop do:[:i|
        (dataSet isSelected:i inColumn:columnNumber) ifTrue:[
            dataSet paint:dkCol.
            dataSet fillRectangleX:0 y:(y - textInset) width:width height:(rowHeight - 1 - sepSize).
            lblFg := lgCol.
            lblBg := dkCol.

            description rendererType == #rowSelector ifTrue:[
                val := form2
            ]
        ] ifFalse:[
            lblFg := fg.
            lblBg := bg.
        ].        
        (val notNil or:[drawableAction notNil and:[(val := drawableAction value:i) notNil]]) ifTrue:[
            val isText ifTrue:[
                lblFg := self extractForegrounColorFromText:val ifAbsent:lblFg.
            ].
            dataSet paint:lblFg on:lblBg.
            val displayOn:dataSet x:x y:y.
            val := nil.
        ].
        y := y + rowHeight
    ].
    dataSet paint:fg on:bg.

    form notNil ifTrue:[
        y := yTop  + formInset.
        x := width - form width - sepSize.

        form2 isNil ifTrue:[
            nTimes timesRepeat:[
                dataSet displayForm:form x:x y:y.
                y := y + rowHeight.
            ]
        ] ifFalse:[
            x := x // 2.

            start to:stop do:[:i|
                val := (self at:i) == false ifTrue:[form2] ifFalse:[form].
                dataSet displayForm:val x:x y:y.
                y := y + rowHeight.
            ]
        ].
    ].

    "/ ************************** DRAW SEPARATORS **************************

    drawColSep := description showColSeparator.
    w          := width - 1.

    sepSize == 1 ifTrue:[
        dataSet paint:fgColor.

        drawColSep ifTrue:[
            dataSet displayLineFromX:w y:yTop toX:w y:yBot
        ].
        description showRowSeparator ifTrue:[
            y := yTop - 1.

            nTimes timesRepeat:[
                y := y + rowHeight.
                dataSet displayLineFromX:0 y:y toX:w y:y.
            ]
        ].
        ^ self
    ].

    "/ draw 3D separators

    dkCol := dataSet separatorDarkColor.
    lgCol := dataSet separatorLightColor.

    drawColSep ifTrue:[
        dataSet paint:lgCol.
        y := yBot - 1. dataSet displayLineFromX:w y:yTop toX:w y:y.
        w := w    - 1. dataSet displayLineFromX:w y:yTop toX:w y:y.
        dataSet paint:dkCol.
        y := y - 1.
        w := w - 1. dataSet displayLineFromX:w y:yTop toX:w y:y.
        w := w - 1. dataSet displayLineFromX:w y:yTop toX:w y:y.
        w := width - 1.
        isLast := dataSet lastColumn == self.
    ].

    description showRowSeparator ifTrue:[
        drawColSep ifTrue:[
            n := w - 2
        ] ifFalse:[
            n := w.
        ].
        dataSet paint:lgCol.
        y := yTop - 1.

        nTimes timesRepeat:[
            y  := y + rowHeight.
            y1 := y - 1.
            dataSet displayLineFromX:0 y:y  toX:w y:y.
            dataSet displayLineFromX:0 y:y1 toX:w y:y1.
        ].

        dataSet paint:dkCol.
        y := yTop.

        nTimes timesRepeat:[
            y  := y + rowHeight.
            y1 := y - 4. dataSet displayLineFromX:0 y:y1 toX:n y:y1.
            y1 := y - 3. dataSet displayLineFromX:0 y:y1 toX:n y:y1.

            drawColSep ifTrue:[
                dataSet displayPointX:n y:y - 1.
                isLast ifFalse:[
                    dataSet displayPointX:w y:y1
                ]
            ]
        ].

        dataSet size == stop ifTrue:[
            dataSet paint:lgCol.
            dataSet displayPointX:n y:y - 1.
        ]
    ]

!

extractForegrounColorFromText:aText ifAbsent:aDefColor
    "extract foreground color from a text object; if no color
     detected, the default color is returned.
    "
    |run color|

    run := aText emphasis.

    run size == 0 ifFalse:[
        run := run first.

        run size == 0 ifTrue:[
            (color := run value) isColor ifTrue:[^ color]
        ] ifFalse:[
            run do:[:r| (color := r value) isColor ifTrue:[^ color]]
        ]
    ].
  ^ aDefColor

!

invalidate
    "set to invalidate; forces a recomputation
    "
    minWidth := width := nil.

! !

!DataSetColumn methodsFor:'editing'!

editorAt:aRowNr in:aView with:fg bg:bg

    ^ description editorOn:(dataSet at:aRowNr)
                     value:(self at:aRowNr)
                        in:aView
                      with:fg
                        bg:bg.


! !

!DataSetColumn methodsFor:'event handling'!

doesNotUnderstand:aMessage

    (description respondsTo:(aMessage selector)) ifTrue:[
        ^ aMessage sendTo:description
    ].
    ^ super doesNotUnderstand:aMessage

!

textInsetChanged:aTextInset
    "recompute all attributes
    "
    |lbl img|

    drawableAction notNil ifTrue:[
        textInset := dataSet verticalSpacing.

        dataSet numberOfRows ~~ 0 ifTrue:[
            lbl := drawableAction value:1.

            (lbl isString or:[lbl isNumber]) ifTrue:[
                textInset := aTextInset
            ] ifFalse:[
                (lbl isNil and:[description printSelector isNil]) ifTrue:[
                    textInset := aTextInset.
                ]
            ]
        ]
    ].

    (img := form2 ? form) isNil ifTrue:[
        formInset := 0
    ] ifFalse:[        
        formInset := ( (dataSet rowHeight)
                      - img height
                      - (dataSet separatorSize)
                     ) // 2.

        drawableAction isNil ifTrue:[
            textInset := formInset
        ]        
    ].


! !

!DataSetColumn methodsFor:'grow & degrow'!

growWidth:n
    "grow the width for n pixels
    "
    width := width + n.


!

minWidth
    "get my minimum width required by the entries into the column
    "
    ^ minWidth notNil ifTrue:[minWidth] ifFalse:[self width]


!

setMinWidth
    "set the width to the required width. returns the psitive delta width
    "
    |deltaX|

    deltaX := width - minWidth.
    width  := minWidth.
  ^ deltaX.


! !

!DataSetColumn methodsFor:'initialization'!

on:aDSVColumnView description:aDescription columnNumber:aNumber
    "instance creation; set attributes dependent on the description
    "
    |rendererType device selector format idx type|

    columnNumber    := aNumber.
    dataSet         := aDSVColumnView.
    description     := aDescription.
    rendererType    := description rendererType.
    form            := width := form2 := nil.
    device          := dataSet device.
    label           := description rawLabel.
    drawableAction  := nil.
    backgroundColor := description backgroundColor.
    foregroundColor := description foregroundColor.

    backgroundColor notNil ifTrue:[
        backgroundColor := backgroundColor on:aDSVColumnView device
    ].
    foregroundColor notNil ifTrue:[
        foregroundColor := foregroundColor on:aDSVColumnView device
    ].

    label isImage ifTrue:[
        label := label onDevice:device
    ].

    rendererType == #CheckToggle ifTrue:[
        form  := dataSet toggleOnButton.
        form2 := dataSet toggleOffButton.
        ^ self
    ].

    rendererType == #rowSelector ifTrue:[
        form2 := dataSet rowSelectorButton.
        ^ self
    ].

    (rendererType == #ComboBox or:[rendererType == #ComboList]) ifTrue:[
        form := dataSet comboViewButton.
    ].

    selector := description printSelector.

    selector notNil ifTrue:[
        drawableAction := [:aRowNr|
            (dataSet at:aRowNr) perform:selector with:dataSet
        ].
        ^ self
    ].

    (     (format := description formatString) notNil
     and:[(type   := description type) == #number or:[type == #numberOrNil]]
    ) ifTrue:[
        "/ has a format string for number (supports only floats)

        (idx := format indexOf:$.) ~~ 0 ifTrue:[
            idx := format size - idx
        ].
        format := '%0.', idx printString, 'f'.

        drawableAction := [:aRowNr||num|
            (num := self at:aRowNr) isReal ifTrue:[
                num := num asFloat printfPrintString:format.
            ].
            num
        ]
    ] ifFalse:[                                         "/ default: no format string
        drawableAction := [:aRowNr| self at:aRowNr ]
    ]


! !

!DataSetColumn methodsFor:'queries'!

canSelect:aRowNr
    "returns true if cell in column is selectable
    "
    |s|

    description canSelect ifTrue:[
        ^ ((s := description selectSelector) isNil or:[(dataSet at:aRowNr) perform:s])
    ].
    ^ false

!

heightOfHighestRow
    "returns the height of the highest row in pixels
    "
    |hObj hMin end|

    hMin := (form ? dataSet font) heightOn:dataSet device.

    (hObj := description height) == 0 ifTrue:[
        drawableAction notNil ifTrue:[
            "/ search first none empty drawable object
            end := 10 min:dataSet numberOfRows.

            1 to:end do:[:aRowNr| |lbl|
                lbl := drawableAction value:aRowNr.

                lbl notNil ifTrue:[
                    (lbl respondsTo:#heightOn:) ifTrue:[
                        hObj := lbl heightOn:dataSet
                    ] ifFalse:[
                        hObj := lbl displayString heightOn:dataSet
                    ].
                    ^ hMin max:hObj
                ]
            ]
        ]
    ].
    ^ hMin max:hObj.
! !

!DataSetColumn methodsFor:'searching'!

findRowNrStartingWithChar:aChar start:start stop:stop
    "find the first row starting at start to stop, which drawable label
     starts with the character, aChar. The index of the detected row is
     returned or if no row is found 0.
    "
    |char|

    drawableAction notNil ifTrue:[
        char  := aChar asLowercase.

        start to:stop do:[:aRowNr| |lbl|
            lbl := drawableAction value:aRowNr.

            lbl isString ifTrue:[
                (lbl size ~~ 0 and:[(lbl at:1) asLowercase == char]) ifTrue:[
                    ^ aRowNr
                ]
            ] ifFalse:[
                lbl isNil ifFalse:[
                    ^ 0
                ]
            ]
        ]
    ].
    ^ 0

! !

!DataSetColumn class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libwidg2/DataSetColumn.st,v 1.10 1997-11-12 16:27:30 ca Exp $'
! !