# scroll.tcl
#
# Copyright 2001 Digi International (www.digi.com)
#    Jeff Adamczak <jeff_adamczak@digi.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the 
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
# PURPOSE.  See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

## This widget implements a frame with a vertical scrollbar that can be
## placed in a toplevel widget with other frames.  Widgets can be added
## and removed from the scrolled frame at run time and the toplevel
## will dynamically resize. The frame will begin to scroll a preset max 
## height is reached. The trick is to pass the height of the other
## frames so that the toplevel can be correctly resized when widgets are
## added and removed from the scrolled frame.
## This is accomplished using a windowed frame in a canvas.  The main proc
## returns the names of the outer frame and the inner frame.  Pack (grid etc.)
## the outer frame but put widgets in the inner frame.
## KNOWN BUG:
## On Windows it works fine.  But on UNIXes the toplevel will shrink a little if 
## the user moves the toplevel.  After that happens, it will only get correctly 
## resized if the scrollbar is moved or if a widget is added/removed.  I think 
## it is because the window manager is unaware of the menu or titlebar height. 
package provide Tools 1.0
namespace eval Scroll {
proc scrolledframe {w heightOtherFrameName heightMaxName} {

	set frameOuter [frame $w.f ]
	set scrollY [scrollbar $frameOuter.yscroll -command [list $frameOuter.c yview] -orient vertical]
	set c [canvas $frameOuter.c -yscrollcommand [list $frameOuter.yscroll set] ]

	pack $scrollY -side right -fill y
	pack $c -side left -expand true -fill both 
	set frameInner [frame $c.fc ]
	$c create window 0 0 -anchor nw -window $frameInner
	set scrollbarWidth [winfo reqwidth $scrollY]   
	bind $frameInner <Configure> "[list Scroll::resize $w $frameInner $c $scrollbarWidth $heightOtherFrameName $heightMaxName]"
    
    return [list $frameOuter $frameInner]
}

proc resize {w frameInner c scrollbarWidth heightOtherFrameName heightMaxName} {
	# Get the value of the global variables
	upvar #0 $heightOtherFrameName heightOtherFrame
	upvar #0 $heightMaxName heightMax
	set width [expr {[winfo reqwidth $frameInner] + $scrollbarWidth}]
	set height [winfo reqheight $frameInner]
	set winWidth [winfo reqwidth $w]
	if {$width > $winWidth} {
		set winWidth $width
	}	
	if {[expr {$height + $heightOtherFrame}] > $heightMax} {
		set winHeight $heightMax
	} else {
		set winHeight [expr {$height + $heightOtherFrame}]		
	}
	$c configure -scrollregion "0 0 $width $height"
	if { [winfo width $w] == $winWidth && [winfo height $w] == $winHeight } {
		## The new size needed is the same as the current size, do nothing
	} else {
		wm geometry $w "$winWidth\x$winHeight"
	}
    return
}


} ;# end namespace Scroll