# # Scrolledcanvas # ---------------------------------------------------------------------- # Implements horizontal and vertical scrollbars around a canvas childsite # Includes options to control display of scrollbars. The standard # canvas options and methods are supported. # # ---------------------------------------------------------------------- # AUTHOR: Mark Ulferts mulferts@spd.dsccc.com # Sue Yockey syockey@spd.dsccc.com # # @(#) $Id: scrolledcanvas.itk,v 1.3 2006/09/11 20:35:55 irby Exp $ # ---------------------------------------------------------------------- # Copyright (c) 1995 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. # ====================================================================== # # Default resources. # option add *Scrolledcanvas.borderWidth 2 widgetDefault option add *Scrolledcanvas.relief sunken widgetDefault option add *Scrolledcanvas.scrollMargin 3 widgetDefault option add *Scrolledcanvas.vscrollMode static widgetDefault option add *Scrolledcanvas.hscrollMode static widgetDefault option add *Scrolledcanvas.labelPos n widgetDefault option add *Scrolledcanvas.autoResize 1 widgetDefault # # Usual options. # itk::usual Scrolledcanvas { keep -activebackground -activerelief -background -borderwidth -cursor \ -elementborderwidth -foreground -highlightcolor -highlightthickness \ -insertbackground -insertborderwidth -insertofftime -insertontime \ -insertwidth -jump -labelfont -selectbackground -selectborderwidth \ -selectforeground -textbackground -troughcolor } # ------------------------------------------------------------------ # SCROLLEDCANVAS # ------------------------------------------------------------------ class iwidgets::Scrolledcanvas { inherit iwidgets::Labeledwidget constructor {args} {} destructor {} itk_option define -autoresize autoResize AutoResize 1 itk_option define -automargin autoMargin AutoMargin 10 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 3i itk_option define -height height Height 3i public method childsite {} public method justify {direction} public method addtag {args} public method bbox {args} public method bind {args} public method canvasx {args} public method canvasy {args} public method coords {args} public method create {args} public method dchars {args} public method delete {args} public method dtag {args} public method find {args} public method focus {args} public method gettags {args} public method icursor {args} public method index {args} public method insert {args} public method itemconfigure {args} public method itemcget {args} public method lower {args} public method move {args} public method postscript {args} public method raise {args} public method scale {args} public method scan {args} public method select {args} public method type {args} public method xview {args} public method yview {args} protected method _scrollCanvas {wid first last} protected method _autoresize {{when -now}} private method _vertScrollbarDisplay {mode} private method _horizScrollbarDisplay {mode} protected variable _vmode off ;# Vertical scroll mode protected variable _hmode off ;# Vertical scroll mode protected variable _pending "" ;# non-null, filler update pending } # # Provide a lowercased access method for the Scrolledcanvas class. # proc ::iwidgets::scrolledcanvas {pathName args} { uplevel ::iwidgets::Scrolledcanvas $pathName $args } # ------------------------------------------------------------------ # CONSTRUCTOR # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::constructor {args} { component hull configure -borderwidth 0 grid propagate $itk_component(lwchildsite) no # # Create a canvas to scroll # itk_component add scrCanvas { canvas $itk_interior.scrCanvas \ -height 1.0 -width 1.0 \ -scrollregion "0 0 1 1" \ -highlightthickness 0 \ -xscrollcommand \ [code $this _scrollCanvas $itk_interior.hSB] \ -yscrollcommand \ [code $this _scrollCanvas $itk_interior.vSB] } { keep -closeenough -confine -cursor keep -insertbackground -insertborderwidth -insertofftime keep -insertontime -insertwidth -relief -borderwidth keep -selectbackground -selectborderwidth -selectforeground keep -xscrollincrement -yscrollincrement -scrollregion rename -background -textbackground textBackground Background } grid $itk_component(scrCanvas) -row 0 -column 0 -sticky nsew grid rowconfigure $itk_component(lwchildsite) 0 -weight 1 grid columnconfigure $itk_component(lwchildsite) 0 -weight 1 # # Create the vertical scroll bar # itk_component add vSB { scrollbar $itk_interior.vSB -orient vertical \ -command [code $itk_component(scrCanvas) yview] } { keep -activebackground -activerelief -background -borderwidth \ -cursor -elementborderwidth \ -highlightcolor -jump -highlightthickness -relief \ -repeatdelay -repeatinterval -troughcolor rename -highlightbackground -background background Background rename -width -sbwidth sbWidth Width } # # Create the horizontal scrollbar # itk_component add hSB { scrollbar $itk_interior.hSB -orient horizontal \ -command [code $itk_component(scrCanvas) xview] } { keep -activebackground -activerelief -background -borderwidth \ -cursor -elementborderwidth \ -highlightcolor -jump -highlightthickness -relief \ -repeatdelay -repeatinterval -troughcolor rename -highlightbackground -background background Background rename -width -sbwidth sbWidth Width } eval itk_initialize $args set itk_interior $itk_component(scrCanvas) } # ------------------------------------------------------------------ # DESTURCTOR # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::destructor {} { if {$_pending != ""} {after cancel $_pending} } # ------------------------------------------------------------------ # OPTIONS # ------------------------------------------------------------------ # ------------------------------------------------------------------ # OPTION: -autoresize # # Automatically adjusts the scrolled region to be the bounding # box covering all the items in the canvas following the execution # of any method which creates or destroys items. Thus, as new # items are added, the scrollbars adjust accordingly. # ------------------------------------------------------------------ configbody iwidgets::Scrolledcanvas::autoresize { _autoresize -eventually } # ------------------------------------------------------------------ # OPTION: -scrollmargin # # Set the distance between the scrollbars and the list box. # ------------------------------------------------------------------ configbody iwidgets::Scrolledcanvas::scrollmargin { if {$_vmode == "on"} { grid configure $itk_component(vSB) -padx $itk_option(-scrollmargin) } if {$_hmode == "on"} { grid configure $itk_component(hSB) -pady $itk_option(-scrollmargin) } } # ------------------------------------------------------------------ # OPTION: -vscrollmode # # Enable/disable display and mode of veritcal scrollbars. # ------------------------------------------------------------------ configbody iwidgets::Scrolledcanvas::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. # ------------------------------------------------------------------ configbody iwidgets::Scrolledcanvas::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 canvas. The value may be # specified in any of the forms acceptable to Tk_GetPixels. # ------------------------------------------------------------------ configbody iwidgets::Scrolledcanvas::width { set pixels [winfo pixels $itk_component(lwchildsite) $itk_option(-width)] $itk_component(lwchildsite) configure -width $pixels } # ------------------------------------------------------------------ # OPTION: -height # # Specifies the height of the scrolled canvas. The value may be # specified in any of the forms acceptable to Tk_GetPixels. # ------------------------------------------------------------------ configbody iwidgets::Scrolledcanvas::height { set pixels [winfo pixels $itk_component(lwchildsite) $itk_option(-height)] $itk_component(lwchildsite) configure -height $pixels } # ------------------------------------------------------------------ # METHODS # ------------------------------------------------------------------ # ------------------------------------------------------------------ # METHOD: childsite # # Returns the path name of the child site widget. # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::childsite {} { return $itk_component(scrCanvas) } # ------------------------------------------------------------------ # METHOD: justify # # Justifies the canvas scrolled region in one of four directions: top, # bottom, left, or right. # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::justify {direction} { if {[winfo ismapped $itk_component(scrCanvas)]} { update idletasks switch $direction { left { $itk_component(scrCanvas) xview moveto 0 } right { $itk_component(scrCanvas) xview moveto 1 } top { $itk_component(scrCanvas) yview moveto 0 } bottom { $itk_component(scrCanvas) yview moveto 1 } default { error "bad justify argument \"$direction\": should be\ left, right, top, or bottom" } } } } # ------------------------------------------------------------------ # CANVAS METHODS: # # The following methods are thin wraps of standard canvas methods. # Consult the Tk canvas man pages for functionallity and argument # documentation # ------------------------------------------------------------------ # ------------------------------------------------------------------ # METHOD: addtag tag searchSpec ?arg arg ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::addtag {args} { return [eval $itk_component(scrCanvas) addtag $args] } # ------------------------------------------------------------------ # METHOD: bbox tagOrId ?tagOrId tagOrId ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::bbox {args} { return [eval $itk_component(scrCanvas) bbox $args] } # ------------------------------------------------------------------ # METHOD: bind tagOrId ?sequence? ?command? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::bind {args} { return [eval $itk_component(scrCanvas) bind $args] } # ------------------------------------------------------------------ # METHOD: canvasx screenx ?gridspacing? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::canvasx {args} { return [eval $itk_component(scrCanvas) canvasx $args] } # ------------------------------------------------------------------ # METHOD: canvasy screeny ?gridspacing? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::canvasy {args} { return [eval $itk_component(scrCanvas) canvasy $args] } # ------------------------------------------------------------------ # METHOD: coords tagOrId ?x0 y0 ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::coords {args} { return [eval $itk_component(scrCanvas) coords $args] } # ------------------------------------------------------------------ # METHOD: create type x y ?x y ...? ?option value ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::create {args} { set retval [eval $itk_component(scrCanvas) create $args] _autoresize -eventually return $retval } # ------------------------------------------------------------------ # METHOD: dchars tagOrId first ?last? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::dchars {args} { return [eval $itk_component(scrCanvas) dchars $args] } # ------------------------------------------------------------------ # METHOD: delete tagOrId ?tagOrId tagOrId ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::delete {args} { set retval [eval $itk_component(scrCanvas) delete $args] _autoresize -eventually return $retval } # ------------------------------------------------------------------ # METHOD: dtag tagOrId ?tagToDelete? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::dtag {args} { eval $itk_component(scrCanvas) dtag $args _autoresize -eventually } # ------------------------------------------------------------------ # METHOD: find searchCommand ?arg arg ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::find {args} { return [eval $itk_component(scrCanvas) find $args] } # ------------------------------------------------------------------ # METHOD: focus ?tagOrId? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::focus {args} { return [eval $itk_component(scrCanvas) focus $args] } # ------------------------------------------------------------------ # METHOD: gettags tagOrId # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::gettags {args} { return [eval $itk_component(scrCanvas) gettags $args] } # ------------------------------------------------------------------ # METHOD: icursor tagOrId index # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::icursor {args} { eval $itk_component(scrCanvas) icursor $args } # ------------------------------------------------------------------ # METHOD: index tagOrId index # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::index {args} { return [eval $itk_component(scrCanvas) index $args] } # ------------------------------------------------------------------ # METHOD: insert tagOrId beforeThis string # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::insert {args} { eval $itk_component(scrCanvas) insert $args } # ------------------------------------------------------------------ # METHOD: itemconfigure tagOrId ?option? ?value? ?option value ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::itemconfigure {args} { set retval [eval $itk_component(scrCanvas) itemconfigure $args] _autoresize -eventually return $retval } # ------------------------------------------------------------------ # METHOD: itemcget tagOrId ?option? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::itemcget {args} { set retval [eval $itk_component(scrCanvas) itemcget $args] return $retval } # ------------------------------------------------------------------ # METHOD: lower tagOrId ?belowThis? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::lower {args} { eval $itk_component(scrCanvas) lower $args } # ------------------------------------------------------------------ # METHOD: move tagOrId xAmount yAmount # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::move {args} { eval $itk_component(scrCanvas) move $args _autoresize -eventually } # ------------------------------------------------------------------ # METHOD: postscript ?option value ...? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::postscript {args} { return [eval $itk_component(scrCanvas) postscript $args] } # ------------------------------------------------------------------ # METHOD: raise tagOrId ?aboveThis? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::raise {args} { eval $itk_component(scrCanvas) raise $args } # ------------------------------------------------------------------ # METHOD: scale tagOrId xOrigin yOrigin xScale yScale # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::scale {args} { eval $itk_component(scrCanvas) scale $args _autoresize -eventually } # ------------------------------------------------------------------ # METHOD: scan option args # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::scan {args} { eval $itk_component(scrCanvas) scan $args } # ------------------------------------------------------------------ # METHOD: select option ?tagOrId arg? # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::select {args} { eval $itk_component(scrCanvas) select $args } # ------------------------------------------------------------------ # METHOD: type tagOrId # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::type {args} { return [eval $itk_component(scrCanvas) type $args] } # ------------------------------------------------------------------ # METHOD: xview index # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::xview {args} { eval $itk_component(scrCanvas) xview $args } # ------------------------------------------------------------------ # METHOD: yview index # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::yview {args} { eval $itk_component(scrCanvas) yview $args } # ------------------------------------------------------------------ # PROTECTED METHOD: _autoresize # # Automatically adjusts the scrolled region to be the bounding # box covering all the items in the canvas following the execution # of any method which creates or destroys items. Thus, as new # items are added, the scrollbars adjust accordingly. # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::_autoresize {{when -now}} { if {$when == "-eventually"} { if {$_pending == ""} { set _pending [after idle [code $this _autoresize -now]] } return } elseif {$when != "-now"} { error "bad option \"$when\": should be -now or -eventually" } set _pending "" if {$itk_option(-autoresize)} { set bbox [$itk_component(scrCanvas) bbox all] if {$bbox != {}} { set marg $itk_option(-automargin) set bbox [lreplace $bbox 0 0 [expr [lindex $bbox 0] - $marg]] set bbox [lreplace $bbox 1 1 [expr [lindex $bbox 1] - $marg]] set bbox [lreplace $bbox 2 2 [expr [lindex $bbox 2] + $marg]] set bbox [lreplace $bbox 3 3 [expr [lindex $bbox 3] + $marg]] set bbox [lreplace $bbox 2 2 [expr [lindex $bbox 2] + $marg]] set bbox [lreplace $bbox 3 3 [expr [lindex $bbox 3] + $marg]] } $itk_component(scrCanvas) configure -scrollregion $bbox } } # ------------------------------------------------------------------ # PRIVATE METHOD: _vertScrollbarDisplay mode # # Displays the vertical scrollbar based on the input mode. # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::_vertScrollbarDisplay {mode} { switch $mode { on { set _vmode on grid $itk_component(vSB) -row 0 -column 1 -sticky ns \ -padx $itk_option(-scrollmargin) } off { set _vmode off grid forget $itk_component(vSB) } default { error "invalid argument \"$mode\": should be on or off" } } } # ------------------------------------------------------------------ # PRIVATE METHOD: _horizScrollbarDisplay mode # # Displays the horizontal scrollbar based on the input mode. # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::_horizScrollbarDisplay {mode} { switch $mode { on { set _hmode on grid $itk_component(hSB) -row 1 -column 0 -sticky ew \ -pady $itk_option(-scrollmargin) } off { set _hmode off grid forget $itk_component(hSB) } default { error "invalid argument \"$mode\": should be on or off" } } } # ------------------------------------------------------------------ # PRIVATE METHOD: _scrollCanvas 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. # ------------------------------------------------------------------ body iwidgets::Scrolledcanvas::_scrollCanvas {wid first last} { $wid set $first $last if {$wid == $itk_component(vSB)} { if {$itk_option(-vscrollmode) == "dynamic"} { if {($first == 0) && ($last == 1)} { if {$_vmode != "off"} { _vertScrollbarDisplay off } } else { if {$_vmode != "on"} { _vertScrollbarDisplay on } } } } elseif {$wid == $itk_component(hSB)} { if {$itk_option(-hscrollmode) == "dynamic"} { if {($first == 0) && ($last == 1)} { if {$_hmode != "off"} { _horizScrollbarDisplay off } } else { if {$_hmode != "on"} { _horizScrollbarDisplay on } } } } }