#
# $Header: /home/rockware/cvs-main/operator/tcl/opSCanvas.tcl,v 1.9 1995/03/16 12:43:21 erez Exp $
# Written by: Erez Strauss (C) All Rights Reserved 1994, 1995.
#

# The OpSCanvas class, no instances only two proc.
itcl_class OpSCanvas {
    proc create {work_space} {
        set canvas $work_space.u.c
        # the following code was copied from the scrl_can
        # first create two parts (up, down)
        frame $work_space.u
        frame $work_space.d

        # create canvas and vertical scrollbar in the upper frame.
        canvas $work_space.u.c -relief sunken -xscroll "$work_space.d.s set" -yscroll "$work_space.u.s set" -scrollincrement 1
        scrollbar $work_space.u.s -orient v -relief sunken -command "$canvas yview"

        # create the horizontal scrollbar and the frame in the corner.
        scrollbar $work_space.d.s -orient h -relief sunken -command "$canvas xview"
        set siz [expr [lindex [$work_space.u.s config -width] 4] + 2]
        frame $work_space.d.f -width $siz -height $siz -relief flat

        # first pack the bottom frame.
        ::pack $work_space.d   -side bottom -fill x
        ::pack $work_space.d.f -side right
        ::pack $work_space.d.s -side left   -fill x    -expand on

        # as last part, pack the top frame.
        ::pack $work_space.u   -side top    -fill both -expand on
        ::pack $work_space.u.s -side right  -fill y
        ::pack $work_space.u.c -side left   -fill both -expand on

        # add general bindings.
        bind $canvas <2> "+%W scan mark %x %y"
        bind $canvas <B2-Motion> "+%W scan dragto %x %y"
        bind $work_space <Configure> "+[bind [winfo class $work_space] <ResizeRequest>]"
        bind $work_space <Configure> "+OpSCanvas :: update $work_space"
        ::update ;# This update, garentee that the windows sizes of the scrollbars will be the right ones.
        # OpSCanvas :: drag $work_space 1 - by default no dragging
    }
    # the update procedure check whether the scroll bars are needed.
    # if any of them is not needed the update proc will use pack forget
    # for the appropriate work space part.
    # *** check which frame retain is size through packing of forgetting of
    #     the scrollbar/ down frame. the $work_space or the $canvas.
    #
    # The update function assumes that there are no other windows inside the
    # work_space frame besides .u .d !!!

    proc update {work_space} {
        ::update
        # puts "OpSCanvas::update $work_space"
        set pad 4
        set canvas $work_space.u.c
        set need [$canvas bbox all]
        if {$need != {}} {
            set need "[expr [lindex $need 0] - $pad] [expr [lindex $need 1] - $pad] [expr [lindex $need 2] + $pad] [expr [lindex $need 3] + $pad]"
        }
        set box_all $need
        $canvas config -scrollregion $box_all
        if !$removable_sb {
            # $canvas config -scrollregion $box_all
            return
        }
        if {$need != {}} {
            # change the need box from coordinates to absolute size.
            set all "0 0 [expr [lindex $need 2] - [lindex $need 0]] [expr [lindex $need 3] - [lindex $need 1]]"
            set canv_x [lindex $need 2]
            set canv_y [lindex $need 3]
            set ws_x [winfo width  $work_space]
            set ws_y [winfo height $work_space]
            set view_x [winfo width  $canvas]
            set view_y [winfo height $canvas]
            # as the size of the horizontal scrollbar we take the size of whole down frame.
            # in both cases we need the width scrollbar parameter because the height is always zero (if I remember correctly).
            set hs_y [winfo height $work_space.d]   ;# we need the height of the frame.
            set vs_x [winfo width  $work_space.u.s] ;# we need the width of the scrollbar.

            if {$fixed_size == "x"} {
                set need_hs [expr $canv_x > $ws_x]
                set need_vs [expr $canv_y > $ws_y]
            } {
                # elsif {$fixed_size == "c"}
                set need_hs [expr $canv_x > $view_x]
                set need_vs [expr $canv_y > $view_y]
            }
        } {
            set need_hs 0
            set need_vs 0
        }
        if {$need_hs ^ $need_vs} {
            # check interrelationship between the scrollbars
            set new_nhs $need_hs
            set new_nvs $need_vs
            if {$fixed_size == "x"} {
                # horizontal
                set new_nhs [expr $need_hs || ($need_vs && $canv_x >= ($ws_x - $vs_x))]
                # vertical
                set new_vhs [expr $need_vs || ($need_hs && $canv_y >= ($ws_y - $hs_y))]
            } { # check $fixed_size == "c"
            }
            set need_hs $new_nhs
            set need_vs $new_nvs
        }
        
        # check X coordinate ($work_space.u.s, $work_space.d.f).
        if $need_hs {
            # need horizontal scrollbar
            ::pack $work_space.d -before $work_space.u  -side bottom -fill x
        } { # no need for horizontal scrollbar.
            ::pack forget $work_space.d
        }
        if {$box_all != {}} {$work_space.u.c xview [lindex $box_all 0]}
        
        # Check Y Coordinate ($work_space.d).
        if $need_vs {
            # need vertical scrollbar
            ::pack $work_space.u.s -before $work_space.u.c -side right  -fill y
            ::pack $work_space.d.f -before $work_space.d.s -side right
        } { # no need for vertical scrollbar.
            ::pack forget $work_space.u.s
            ::pack forget $work_space.d.f
        }
        if {$box_all != {}} {
            $work_space.u.c yview [lindex $box_all 1]
        }
        ::update
    }

    proc drag {ws state} {
        set canv $ws.u.c
        if $state {
            bind $canv <ButtonPress-1> "+itemStartDrag %W %x %y"
            bind $canv <B1-Motion> "+itemDrag %W %x %y"
            bind $canv <B1-ButtonRelease> "+OpSCanvas :: update $ws"
            $canv bind all <ButtonPress-1> "+itemStartDrag %W %x %y"
            $canv bind all <B1-Motion> "+itemDrag %W %x %y"
            $canv bind all <B1-ButtonRelease> "+OpSCanvas :: update $ws"
        } {
            # The setting of non dragable after setting drag 1,
            #  will be presented, on Operator-2.0 with tags.
        }
    }

    common removable_sb 1  ; # by default the scroll bars are removables.
    common fixed_size x    ; # x - external frame has constat size, c - canvas has fixed size view.
}

proc itemStartDrag {c x y} {
    global lastX lastY
    set lastX [$c canvasx $x]
    set lastY [$c canvasy $y]

    set cur [$c find withtag current]
}

proc itemDrag {c x y} {
    global lastX lastY
    set x [$c canvasx $x]
    set y [$c canvasy $y]
    $c move current [expr $x-$lastX] [expr $y-$lastY]
    set lastX $x
    set lastY $y
}
# End of the OpSCanvas class.
