#
# Scrolledwidget
# ----------------------------------------------------------------------
# Implements a general purpose base class for scrolled widgets, by
# creating the necessary horizontal and vertical scrollbars and 
# providing protected methods for controlling their display.  The 
# derived class needs to take advantage of the fact that the grid
# is used and the vertical scrollbar is in row 0, column 2 and the
# horizontal scrollbar in row 2, column 0.
#
# ----------------------------------------------------------------------
#  AUTHOR: Mark Ulferts                        mulferts@austin.dsccc.com 
#
#  @(#) $Id: scrolledwidget.itk,v 1.2 2001/08/07 19:56:48 smithc Exp $
# ----------------------------------------------------------------------
#            Copyright (c) 1997 DSC Technologies Corporation
# ======================================================================
# Permission to use, copy, modify, distribute and license this software 
# and its documentation for any purpose, and without fee or written 
# agreement with DSC, is hereby granted, provided that the above copyright 
# notice appears in all copies and that both the copyright notice and 
# warranty disclaimer below appear in supporting documentation, and that 
# the names of DSC Technologies Corporation or DSC Communications 
# Corporation not be used in advertising or publicity pertaining to the 
# software without specific, written prior permission.
# 
# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
# SOFTWARE.
# ======================================================================

#
# Usual options.
#
itk::usual Scrolledwidget {
    keep -background -borderwidth -cursor -highlightcolor -highlightthickness 
    keep -activebackground -activerelief -jump -troughcolor
    keep -labelfont -foreground
}

# ------------------------------------------------------------------
#                            SCROLLEDWIDGET
# ------------------------------------------------------------------
itcl::class iwidgets::Scrolledwidget {
    inherit iwidgets::Labeledwidget

    constructor {args} {}
    destructor {}

    itk_option define -sbwidth sbWidth Width 15
    itk_option define -scrollmargin scrollMargin ScrollMargin 3 
    itk_option define -vscrollmode vscrollMode VScrollMode static 
    itk_option define -hscrollmode hscrollMode HScrollMode static 
    itk_option define -width width Width 30 
    itk_option define -height height Height 30 

    protected method _scrollWidget {wid first last} 
    protected method _vertScrollbarDisplay {mode} 
    protected method _horizScrollbarDisplay {mode} 
    protected method _configureEvent {}

    protected variable _vmode off            ;# Vertical scroll mode
    protected variable _hmode off            ;# Vertical scroll mode
    protected variable _recheckHoriz 1       ;# Flag to check need for 
                                             ;#  horizontal scrollbar
    protected variable _recheckVert 1        ;# Flag to check need for 
                                             ;#  vertical scrollbar

    protected variable _interior {}
}

#
# Provide a lowercased access method for the Scrolledwidget class.
# 
proc ::iwidgets::scrolledwidget {pathName args} {
    uplevel ::iwidgets::Scrolledwidget $pathName $args
}

#
# Use option database to override default resources of base classes.
#
option add *Scrolledwidget.labelPos n widgetDefault

# ------------------------------------------------------------------
#                        CONSTRUCTOR
# ------------------------------------------------------------------
itcl::body iwidgets::Scrolledwidget::constructor {args} {

    #
    # Turn off the borderwidth on the hull and save off the 
    # interior for later use.
    #
    component hull configure -borderwidth 0
    set _interior $itk_interior

    #
    # Check if the scrollbars need mapping upon a configure event.
    #
    bind $_interior <Configure> [itcl::code $this _configureEvent]

    #
    # Turn off propagation in the containing shell.
    #
    # Due to a bug in the tk4.2 grid, we have to check the 
    # propagation before setting it.  Setting it to the same
    # value it already is will cause it to toggle.
    #
    if {[grid propagate $_interior]} {
	grid propagate $_interior no
    }
	
    # 
    # Create the vertical scroll bar
    #
    itk_component add vertsb {
	scrollbar $itk_interior.vertsb -orient vertical 
    } {
	usual
	keep -borderwidth -elementborderwidth -jump -relief 
	rename -highlightbackground -background background Background
    }

    #
    # Create the horizontal scrollbar
    #
    itk_component add horizsb {
	scrollbar $itk_interior.horizsb -orient horizontal 
    } {
	usual
	keep -borderwidth -elementborderwidth -jump -relief 
	rename -highlightbackground -background background Background
    }
    
    #
    # Initialize the widget based on the command line options.
    #
    eval itk_initialize $args
}

# ------------------------------------------------------------------
#                           DESTURCTOR
# ------------------------------------------------------------------
itcl::body iwidgets::Scrolledwidget::destructor {} {
}

# ------------------------------------------------------------------
#                             OPTIONS
# ------------------------------------------------------------------

# ------------------------------------------------------------------
# OPTION: -sbwidth
#
# Set the width of the scrollbars.
# ------------------------------------------------------------------
itcl::configbody iwidgets::Scrolledwidget::sbwidth {
    $itk_component(vertsb) configure -width $itk_option(-sbwidth)
    $itk_component(horizsb) configure -width $itk_option(-sbwidth)
}

# ------------------------------------------------------------------
# OPTION: -scrollmargin
#
# Set the distance between the scrollbars and the list box.
# ------------------------------------------------------------------
itcl::configbody iwidgets::Scrolledwidget::scrollmargin {
    set pixels [winfo pixels $_interior	$itk_option(-scrollmargin)]
    	
    if {$_hmode == "on"} {
	grid rowconfigure $_interior 1 -minsize $pixels
    }
	
    if {$_vmode == "on"} {
	grid columnconfigure $_interior 1 -minsize $pixels
    }
}

# ------------------------------------------------------------------
# OPTION: -vscrollmode
#
# Enable/disable display and mode of veritcal scrollbars.
# ------------------------------------------------------------------
itcl::configbody iwidgets::Scrolledwidget::vscrollmode {
    switch $itk_option(-vscrollmode) {
    	static {
    	    _vertScrollbarDisplay on
    	}
	
    	dynamic -
    	none {
    	    _vertScrollbarDisplay off
    	}
	
    	default {
    	    error "bad vscrollmode option\
		    \"$itk_option(-vscrollmode)\": should be\
		    static, dynamic, or none"
    	}
    }
}

# ------------------------------------------------------------------
# OPTION: -hscrollmode
#
# Enable/disable display and mode of horizontal scrollbars.
# ------------------------------------------------------------------
itcl::configbody iwidgets::Scrolledwidget::hscrollmode {
    switch $itk_option(-hscrollmode) {
    	static {
    	    _horizScrollbarDisplay on
    	}
	
    	dynamic -
    	none {
    	    _horizScrollbarDisplay off
    	}
	
    	default {
    	    error "bad hscrollmode option\
		    \"$itk_option(-hscrollmode)\": should be\
		    static, dynamic, or none"
    	}
    }
}

# ------------------------------------------------------------------
# OPTION: -width
#
# Specifies the width of the scrolled widget.  The value may be 
# specified in any of the forms acceptable to Tk_GetPixels.  
# ------------------------------------------------------------------
itcl::configbody iwidgets::Scrolledwidget::width {
    $_interior configure -width \
	[winfo pixels $_interior $itk_option(-width)] 
}

# ------------------------------------------------------------------
# OPTION: -height
#
# Specifies the height of the scrolled widget.  The value may be 
# specified in any of the forms acceptable to Tk_GetPixels.  
# ------------------------------------------------------------------
itcl::configbody iwidgets::Scrolledwidget::height {
    $_interior configure -height \
	[winfo pixels $_interior $itk_option(-height)] 
}

# ------------------------------------------------------------------
#                            METHODS
# ------------------------------------------------------------------

# ------------------------------------------------------------------
# PROTECTED METHOD: _vertScrollbarDisplay mode
#
# Displays the vertical scrollbar based on the input mode.
# ------------------------------------------------------------------
itcl::body iwidgets::Scrolledwidget::_vertScrollbarDisplay {mode} {
    switch $mode  {
	on {
	    set _vmode on
	    
	    grid columnconfigure $_interior 1 -minsize \
		    [winfo pixels $_interior $itk_option(-scrollmargin)]
	    grid $itk_component(vertsb) -row 0 -column 2 -sticky ns
	}
	
	off {
	    set _vmode off
	    
	    grid columnconfigure $_interior 1 -minsize 0
	    grid forget $itk_component(vertsb) 
	}
	
	default {
	    error "invalid argument \"$mode\": should be on or off"
	}
    }
}

# ------------------------------------------------------------------
# PROTECTED METHOD: _horizScrollbarDisplay mode
#
# Displays the horizontal scrollbar based on the input mode.
# ------------------------------------------------------------------
itcl::body iwidgets::Scrolledwidget::_horizScrollbarDisplay {mode} {
    switch $mode  {
	on {
	    set _hmode on
	    
	    grid rowconfigure $_interior 1 -minsize \
		    [winfo pixels $_interior $itk_option(-scrollmargin)]
	    grid $itk_component(horizsb) -row 2 -column 0 -sticky ew
	}
	
	off {
	    set _hmode off
	    
	    grid rowconfigure $_interior 1 -minsize 0
	    grid forget $itk_component(horizsb) 
	}
	
	default {
	    error "invalid argument \"$mode\": should be on or off"
	}
    }
}

# ------------------------------------------------------------------
# PROTECTED METHOD: _scrollWidget wid first last
#
# Performs scrolling and display of scrollbars based on the total 
# and maximum frame size as well as the current -vscrollmode and 
# -hscrollmode settings.  Parameters are automatic scroll parameters.
# ------------------------------------------------------------------
itcl::body iwidgets::Scrolledwidget::_scrollWidget {wid first last} {
    $wid set $first $last

    if {$wid == $itk_component(vertsb)} {
	if {$itk_option(-vscrollmode) == "dynamic"} {
	    if {($_recheckVert != 1) && ($_vmode == "on")} {
		return
	    } else {
		set _recheckVert 0
	    }

	    if {($first == 0) && ($last == 1)} {
		if {$_vmode != "off"} {
		    _vertScrollbarDisplay off
		}
		
	    } else {
		if {$_vmode != "on"} {
		    _vertScrollbarDisplay on
		}
	    }
	}
	
    } elseif {$wid == $itk_component(horizsb)} {
	if {$itk_option(-hscrollmode) == "dynamic"} {
	    if {($_recheckHoriz != 1) && ($_hmode == "on")} {
		return
	    } else {
		set _recheckHoriz 0
	    }

	    if {($first == 0) && ($last == 1)} {
		if {$_hmode != "off"} {
		    _horizScrollbarDisplay off
		}
		
	    } else {
		if {$_hmode != "on"} {
		    _horizScrollbarDisplay on
		}
	    }
	}
    }
}

# ------------------------------------------------------------------
# PROTECTED METHOD: _configureEvent
#
# Resets the recheck flags which determine if we'll try and map
# the scrollbars in dynamic mode.  
# ------------------------------------------------------------------
itcl::body iwidgets::Scrolledwidget::_configureEvent {} {
    update idletasks
    set _recheckVert 1
    set _recheckHoriz 1
}
