VarHPanel.st
author claus
Wed, 24 Aug 1994 01:38:59 +0200
changeset 51 e895ac4cc7c8
parent 38 4b9b70b2cc87
child 59 450ce95a72a4
permissions -rw-r--r--
support non-string entries

"
 COPYRIGHT (c) 1992 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.
"

VariableVerticalPanel subclass:#VariableHorizontalPanel
         instanceVariableNames:''
         classVariableNames:''
         poolDictionaries:''
         category:'Views-Layout'
!

VariableHorizontalPanel comment:'
COPYRIGHT (c) 1992 by Claus Gittinger
              All Rights Reserved

$Header: /cvs/stx/stx/libwidg/Attic/VarHPanel.st,v 1.6 1994-08-07 13:23:35 claus Exp $
'!

!VariableHorizontalPanel class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1992 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.
"
!

version
"
$Header: /cvs/stx/stx/libwidg/Attic/VarHPanel.st,v 1.6 1994-08-07 13:23:35 claus Exp $
"
!

documentation
"
    a View to separate its subviews horizontally by a movable bar
    to adjust the size-ratios.
    The bar-handle is either an exposed knob (knobStyle == #motif)
    or the forms defined in Scroller (knobStyle ~~ #motif)
    or nothing.

    The subvies dimensions MUST be given as relative sizes;
    typically creation is done as:

        p := VariableHorizontalPanel in:superView.
        v1 := <someViewClass> origin:0.0 @ 0.0
                              corner:0.5 @ 1.0
                                  in:p.
        v2 := <someViewClass> origin:0.5 @ 0.0
                              corner:0.8 @ 1.0
                                  in:p.
        v3 := <someViewClass> origin:0.8 @ 0.0
                              corner:1.0 @ 1.0
                                  in:p.

   example:
        |top p v1 v2 v3|

        top := StandardSystemView new.
        top extent:300@200.

        p := VariableHorizontalPanel 
                 origin:0.0 @ 0.0
                 corner:1.0 @ 1.0
                 in:top.
        v1 := SelectionInListView 
                 origin:0.0 @ 0.0
                 corner:0.5 @ 1.0
                 in:p.
        v2 := EditTextView 
                 origin:0.5 @ 0.0
                 corner:0.8 @ 1.0
                 in:p.
        v3 := ScrollableView 
                 for:TextView 
                 in:p.
        v3 origin:0.8 @ 0.0 
           corner:1.0 @ 1.0.
        top open
"
! !

!VariableHorizontalPanel methodsFor:'initializing'!

initCursor
    "set the cursor - a horizontal double arrow"

    cursor := Cursor sourceForm:(Form fromFile:'VHPanel.xbm')
                     maskForm:(Form fromFile:'VHPanel_m.xbm')
                     hotX:8
                     hotY:8.
    "
     if bitmaps are not available, use a standard cursor
    "
    cursor isNil ifTrue:[
        "which one looks better ?"
        cursor := Cursor leftRightArrow
        "cursor := Cursor leftLimitArrow"
    ]
! !

!VariableHorizontalPanel methodsFor:'private'!

handleOriginsFrom:start to:stop do:aBlock
    "evaluate the argument block for some handle-origins"

    |y hh|

    subViews notNil ifTrue:[
        shadowForm notNil ifTrue:[
            hh := shadowForm height
        ] ifFalse:[
            hh := barHeight
        ].
        (handlePosition == #left) ifTrue:[
            y := hh * 2
        ] ifFalse:[
            (handlePosition == #right) ifTrue:[
                y := height - (2 * hh) - margin
            ] ifFalse:[
                y := height // 2
            ]
        ].
        (start + 1) to:stop do:[:index |
            |x view|

            view := subViews at:index.
            x := view origin x - barHeight + 1.
            aBlock value:(x @ y)
        ]
    ]
!

setupSubviewSizes
    "setup subviews sizes (in case of non-relative sizes)"

    |x w |

    self anyNonRelativeSubviews ifTrue:[
        "there is at least one subview without
         relative origin/extent - setup all subviews
         to spread evenly ..."

        x := 0.0.
        w := 1.0 / (subViews size).

        1 to:(subViews size) do:[:index |
            |view|

            view := subViews at:index.
            index == subViews size ifTrue:[
                view origin:(x @ 0.0) corner:(1.0 @ 1.0)
            ] ifFalse:[
                view origin:(x @ 0.0) corner:((x + w) @ 1.0)
            ].
            x := x + w
        ]
    ]
!

resizeSubviewsFrom:start to:stop
    "readjust size of some subviews"

    |step nSubviews|

    subViews notNil ifTrue:[
        (start <= stop) ifTrue:[
            step := 1
        ] ifFalse:[
            step := -1
        ].
        nSubviews := subViews size.
        start to:stop by:step do:[:index |
            |bw view o1 o2 relCorner relOrg newCorner newOrg|

            view := subViews at:index.
            bw := view borderWidth.

            index == 1 ifTrue:[
                o1 := 0.
            ] ifFalse:[
                o1 := barHeight // 2 - bw
            ].
            index ==  nSubviews ifTrue:[
                o2 := 0.
            ] ifFalse:[
                o2 := barHeight // 2 - bw
            ].

            relCorner := view relativeCorner.
            relCorner isNil ifTrue:[
                self error:'subview must have relative corner'
            ].
            newCorner := view cornerFromRelativeCorner.
            newCorner notNil ifTrue:[
                newCorner x:(newCorner x - o2)
            ].

            relOrg := view relativeOrigin.
            relOrg isNil ifTrue:[
                self error:'subview must have relative origin'
            ].
            newOrg := view originFromRelativeOrigin.
            newOrg notNil ifTrue:[
                (index ~~ 1) ifTrue:[  
                    newOrg x:(newOrg x + o1)
                ].
            ].
            view pixelOrigin:newOrg corner:newCorner
        ]
    ]
! !

!VariableHorizontalPanel methodsFor:'events'!

buttonPress:button x:bx y:by
    "button was pressed - if it hits a handle, start move"

    |handle|

    ((button == 1) or:[button == #select]) ifTrue:[
        handle := 1.
        self handleOriginsDo:[:hPoint |
            |hx|

            hx := hPoint x.
            (bx between:hx and:(hx + barHeight)) ifTrue:[
                movedHandle := handle.
                prev := hx.
                start := bx - hx.
                self noClipByChildren.
                self xoring:[
                    self fillRectangleX:hx y:0 width:barHeight height:height
                ].
                self clipByChildren.
                ^ self
            ].
            handle := handle + 1
        ].
        movedHandle := nil
    ] ifFalse:[
        super buttonPress:button x:bx y:by
    ]
!

buttonMotion:button x:bx y:by
    "mouse-button was moved while pressed;
     clear prev handleBar and draw handle bar at new position" 

    |xpos limitTop limitBot|

    movedHandle isNil ifTrue: [^ self].          "should not happen"

    "speedup - if there is already another movement, 
     ignore thisone ... "

    device synchronizeOutput.
    self buttonMotionEventPending ifTrue:[^ self].

    xpos := bx - start.
    limitTop := barHeight // 2.
    limitBot := self width - barHeight.
    movedHandle > 1 ifTrue:[
        limitTop := (subViews at:movedHandle) origin x + (barHeight // 2)
    ].
    movedHandle < (subViews size - 1) ifTrue:[
        limitBot := (subViews at:(movedHandle + 2)) origin x - barHeight
    ].
    limitBot := limitBot - barHeight.
    (xpos < limitTop) ifTrue:[ "check against view limits"
        xpos := limitTop
    ] ifFalse:[
        (xpos > limitBot) ifTrue:[
            xpos := limitBot
        ]
    ].

    self noClipByChildren.
    self xoring:[
        self fillRectangleX:prev y:0 width:barHeight height:height.
        self fillRectangleX:xpos y:0 width:barHeight height:height
    ].
    self clipByChildren.
    prev := xpos
!

buttonRelease:button x:x y:y
    "end bar-move"

    |aboveView belowView aboveIndex belowIndex newX|

    ((button == 1) or:[button == #select]) ifTrue:[
        movedHandle isNil ifTrue:[^ self].

        "undo the last xor"

        self noClipByChildren.
        self xoring:[
            self fillRectangleX:prev y:0 width:barHeight height:height
        ].
        self clipByChildren.

        "compute the new relative heights"

        aboveIndex := movedHandle.
        belowIndex := movedHandle + 1.
        aboveView := subViews at:aboveIndex.
        belowView := subViews at:belowIndex.

        newX := (prev + start / width) asFloat .
        aboveView relativeCorner:newX @ aboveView relativeCorner y.
        belowView relativeOrigin:newX @ belowView relativeOrigin y.
        self resizeSubviewsFrom:aboveIndex to:belowIndex.

        movedHandle := nil.

        "and redraw handles"

        self redrawHandlesFrom:aboveIndex to:belowIndex
    ] ifFalse:[
        super buttonRelease:button x:x y:y
    ]
! !

!VariableHorizontalPanel methodsFor:'drawing'!

drawHandleAtX:hx y:hy
    |w x m|

    (self is3D and:[shadowForm notNil]) ifTrue:[
        w := shadowForm height
    ] ifFalse:[
        w := barHeight - 4
    ].

    self paint:viewBackground.
    self fillRectangleX:hx y:margin 
                  width:barHeight
                 height:(height - margin - margin).

    self is3D ifTrue:[
         m := (barHeight - w) // 2.
         shadowForm isNil ifTrue:[
            x := hx + (barHeight // 2).
            separatingLine ifTrue:[
                self paint:shadowColor.
                self displayLineFromX:x y:margin toX:x y:(height - margin).
                x := x + 1.
                self paint:lightColor.
                self displayLineFromX:x y:margin toX:x y:(height - margin).
            ].
            self paint:viewBackground.
            self fillRectangleX:hx y:(hy - barWidth) 
                          width:w height:(barWidth + barWidth).

            "/ x := hx.    "old"
            x := hx - 1.   "2.10.3"
            self drawEdgesForX:(x + m)
                             y:(hy - barWidth)
                         width:w height:(barWidth + barWidth)
                         level:2
        ] ifFalse:[
            "/ x := hx.    "old"
            x := hx - 1.   "2.10.3"
            self drawHandleFormAtX:(x + m) y:hy
        ].
        style == #st80 ifTrue:[
            x := hx - 1.
            self paint:lightColor.
            self displayLineFromX:x y:margin toX:x y:(height - margin).
            x := hx + barHeight - 2.
            self paint:shadowColor.
            self displayLineFromX:x y:margin toX:x y:(height - margin).
        ].
    ] ifFalse:[
        x := hx + barHeight - 2.
        self paint:handleColor.
        separatingLine ifTrue:[
            self displayLineFromX:hx y:0 toX:hx y:height.
            self displayLineFromX:x y:0 toX:x y:height.
        ].
        self fillRectangleX:hx y:hy width:barHeight height:barHeight
    ]
!

redrawHandlesFrom:start to:stop
    "redraw some handles"

    subViews notNil ifTrue:[
        self handleOriginsFrom:start to:stop do:[:hPoint |
            self drawHandleAtX:(hPoint x) y:(hPoint y)
        ].
        movedHandle notNil ifTrue:[
            self noClipByChildren.
            self xoring:[
                self fillRectangleX:prev y:0 width:barHeight height:height
            ].
            self clipByChildren
        ]
    ]

! !