| # |
| # Panedwindow |
| # ---------------------------------------------------------------------- |
| # Implements a multiple paned window widget capable of orienting the panes |
| # either vertically or horizontally. Each pane is itself a frame acting |
| # as a child site for other widgets. The border separating each pane |
| # contains a sash which allows user positioning of the panes relative to |
| # one another. |
| # |
| # ---------------------------------------------------------------------- |
| # AUTHOR: Mark L. Ulferts EMAIL: mulferts@austin.dsccc.com |
| # |
| # @(#) $Id: panedwindow.itk,v 1.7 2001/09/06 15:12:46 smithc 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. |
| # ====================================================================== |
| |
| # |
| # Usual options. |
| # |
| itk::usual Panedwindow { |
| keep -background -cursor -sashcursor |
| } |
| |
| # ------------------------------------------------------------------ |
| # PANEDWINDOW |
| # ------------------------------------------------------------------ |
| itcl::class iwidgets::Panedwindow { |
| inherit itk::Widget |
| |
| constructor {args} {} |
| |
| itk_option define -orient orient Orient horizontal |
| itk_option define -sashborderwidth sashBorderWidth SashBorderWidth 2 |
| itk_option define -sashcursor sashCursor SashCursor crosshair |
| itk_option define -sashwidth sashWidth SashWidth 10 |
| itk_option define -sashheight sashHeight SashHeight 10 |
| itk_option define -thickness thickness Thickness 3 |
| itk_option define -sashindent sashIndent SashIndent -10 |
| itk_option define -showhandle showHandle ShowHandle 1 |
| |
| public method index {index} |
| public method childsite {args} |
| public method fraction {args} |
| public method add {tag args} |
| public method insert {index tag args} |
| public method delete {index} |
| public method hide {index} |
| public method show {index} |
| public method paneconfigure {index args} |
| public method reset {} |
| |
| protected method _pwConfigureEventHandler {width height} |
| protected method _startGrip {where num} |
| protected method _endGrip {where num} |
| protected method _configGrip {where num} |
| protected method _handleGrip {where num} |
| protected method _moveSash {where num} |
| |
| private method _setFracArray {} |
| private method _setActivePanes {} |
| private method _calcFraction {where num} |
| private method _makeSashes {} |
| private method _placeSash {i} |
| private method _placePanes {{start 0} {end end}} |
| |
| private variable _initialized 0 ;# Denotes initialized state. |
| private variable _panes {} ;# List of panes. |
| private variable _activePanes {} ;# List of active panes. |
| private variable _sashes {} ;# List of sashes. |
| private variable _separators {} ;# List of separators. |
| private variable _frac ;# Array of fraction percentages. |
| private variable _lowerlimit ;# Margin distance above/left of sash. |
| private variable _upperlimit ;# Margin distance below/right of sash. |
| private variable _dimension ;# Width/Height at start of drag. |
| private variable _sashloc ;# Array of dist of sash from above/left. |
| private variable _pixels ;# Array of dist of sash from above/left. |
| private variable _minheight ;# Array of min heights for panes. |
| private variable _minsashmoved ;# Lowest sash moved during dragging. |
| private variable _maxsashmoved ;# Highest sash moved during dragging. |
| private variable _dragging 0 ;# Boolean for dragging enabled. |
| private variable _movecount 0 ;# Kludge counter to get sashes to |
| ;# display without calling update |
| ;# idletasks too often. |
| private variable _width 0 ;# hull's width. |
| private variable _height 0 ;# hull's height. |
| private variable _unique -1 ;# Unique number for pane names. |
| |
| private variable _relief ;# relief for -showhandle |
| } |
| |
| # |
| # Provide a lowercased access method for the Panedwindow class. |
| # |
| proc ::iwidgets::panedwindow {pathName args} { |
| uplevel ::iwidgets::Panedwindow $pathName $args |
| } |
| |
| # |
| # Use option database to override default resources of base classes. |
| # |
| option add *Panedwindow.width 10 widgetDefault |
| option add *Panedwindow.height 10 widgetDefault |
| |
| # ------------------------------------------------------------------ |
| # CONSTRUCTOR |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::constructor {args} { |
| itk_option add hull.width hull.height |
| |
| pack propagate $itk_component(hull) no |
| |
| # |
| # Add binding for the configure event. |
| # |
| bind pw-config-$this <Configure> [itcl::code $this _pwConfigureEventHandler %w %h] |
| bindtags $itk_component(hull) \ |
| [linsert [bindtags $itk_component(hull)] 0 pw-config-$this] |
| |
| array set _relief {0 sunken 1 raised} |
| |
| eval itk_initialize $args |
| } |
| |
| # ------------------------------------------------------------------ |
| # OPTIONS |
| # ------------------------------------------------------------------ |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -orient |
| # |
| # Specifies the orientation of the sashes. Once the paned window |
| # has been mapped, set the sash bindings and place the panes. |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::orient { |
| if {$_initialized} { |
| switch $itk_option(-orient) { |
| vertical { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| bind $itk_component(sash$i) <Button-1> \ |
| [itcl::code $this _startGrip %x $i] |
| bind $itk_component(sash$i) <B1-Motion> \ |
| [itcl::code $this _handleGrip %x $i] |
| bind $itk_component(sash$i) <B1-ButtonRelease-1> \ |
| [itcl::code $this _endGrip %x $i] |
| bind $itk_component(sash$i) <Configure> \ |
| [itcl::code $this _configGrip %x $i] |
| } |
| |
| _setFracArray |
| _makeSashes |
| _placePanes |
| } |
| |
| horizontal { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| bind $itk_component(sash$i) <Button-1> \ |
| [itcl::code $this _startGrip %y $i] |
| bind $itk_component(sash$i) <B1-Motion> \ |
| [itcl::code $this _handleGrip %y $i] |
| bind $itk_component(sash$i) <B1-ButtonRelease-1> \ |
| [itcl::code $this _endGrip %y $i] |
| bind $itk_component(sash$i) <Configure> \ |
| [itcl::code $this _configGrip %y $i] |
| } |
| |
| _setFracArray |
| _makeSashes |
| _placePanes |
| } |
| |
| default { |
| error "bad orientation option \"$itk_option(-orient)\":\ |
| should be horizontal or vertical" |
| } |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -sashborderwidth |
| # |
| # Specifies a non-negative value indicating the width of the 3-D |
| # border to draw around the outside of the sash. |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::sashborderwidth { |
| set pixels [winfo pixels $itk_component(hull) \ |
| $itk_option(-sashborderwidth)] |
| set itk_option(-sashborderwidth) $pixels |
| |
| if {$_initialized} { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| $itk_component(sash$i) configure \ |
| -borderwidth $itk_option(-sashborderwidth) |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -sashcursor |
| # |
| # Specifies the type of cursor to be used when over the sash. |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::sashcursor { |
| if {$_initialized} { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| $itk_component(sash$i) configure -cursor $itk_option(-sashcursor) |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -sashwidth |
| # |
| # Specifies the width of the sash. |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::sashwidth { |
| set pixels [winfo pixels $itk_component(hull) \ |
| $itk_option(-sashwidth)] |
| set itk_option(-sashwidth) $pixels |
| |
| if {$_initialized} { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| $itk_component(sash$i) configure \ |
| -width $itk_option(-sashwidth) |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -sashheight |
| # |
| # Specifies the height of the sash, |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::sashheight { |
| set pixels [winfo pixels $itk_component(hull) \ |
| $itk_option(-sashheight)] |
| set itk_option(-sashheight) $pixels |
| |
| if {$_initialized} { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| $itk_component(sash$i) configure \ |
| -height $itk_option(-sashheight) |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -showhandle |
| # |
| # Specifies whether or not to show the sash handle. If not, then the |
| # whole separator becomes the handle. Valid values are 0 or 1. |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::showhandle { |
| switch $itk_option(-showhandle) { |
| 0 - 1 { |
| # Update the sashes. |
| _makeSashes |
| _placePanes |
| } |
| default { |
| error "Invalid option for -showhandle: $itk_option(-showhandle).\ |
| Must be 1 or 0." |
| } |
| } |
| } |
| |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -thickness |
| # |
| # Specifies the thickness of the separators. It sets the width and |
| # height of the separator to the thickness value and the borderwidth |
| # to half the thickness. |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::thickness { |
| set pixels [winfo pixels $itk_component(hull) \ |
| $itk_option(-thickness)] |
| set itk_option(-thickness) $pixels |
| |
| if {$_initialized} { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| $itk_component(separator$i) configure \ |
| -height $itk_option(-thickness) |
| $itk_component(separator$i) configure \ |
| -width $itk_option(-thickness) |
| $itk_component(separator$i) configure \ |
| -borderwidth [expr {$itk_option(-thickness) / 2}] |
| } |
| |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| _placeSash $i |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # OPTION: -sashindent |
| # |
| # Specifies the placement of the sash along the panes. A positive |
| # value causes the sash to be offset from the near (left/top) side |
| # of the pane, and a negative value causes the sash to be offset from |
| # the far (right/bottom) side. If the offset is greater than the |
| # width, then the sash is placed flush against the side. |
| # ------------------------------------------------------------------ |
| itcl::configbody iwidgets::Panedwindow::sashindent { |
| set pixels [winfo pixels $itk_component(hull) \ |
| $itk_option(-sashindent)] |
| set itk_option(-sashindent) $pixels |
| |
| if {$_initialized} { |
| for {set i 1} {$i < [llength $_activePanes]} {incr i} { |
| _placeSash $i |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHODS |
| # ------------------------------------------------------------------ |
| |
| # ------------------------------------------------------------------ |
| # METHOD: index index |
| # |
| # Searches the panes in the paned window for the one with the |
| # requested tag, numerical index, or keyword "end". Returns the pane's |
| # numerical index if found, otherwise error. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::index {index} { |
| if {[llength $_panes] > 0} { |
| if {[regexp {(^[0-9]+$)} $index]} { |
| if {$index < [llength $_panes]} { |
| return $index |
| } else { |
| error "Panedwindow index \"$index\" is out of range" |
| } |
| |
| } elseif {$index == "end"} { |
| return [expr {[llength $_panes] - 1}] |
| |
| } else { |
| if {[set idx [lsearch $_panes $index]] != -1} { |
| return $idx |
| } |
| |
| error "bad Panedwindow index \"$index\": must be number, end,\ |
| or pattern" |
| } |
| |
| } else { |
| error "Panedwindow \"$itk_component(hull)\" has no panes" |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: childsite ?index? |
| # |
| # Given an index return the specifc childsite path name. Invoked |
| # without an index return a list of all the child site panes. The |
| # list is ordered from the near side (left/top). |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::childsite {args} { |
| if {! $_initialized} { |
| set _initialized 1 |
| reset |
| } |
| |
| if {[llength $args] == 0} { |
| set children {} |
| |
| foreach pane $_panes { |
| lappend children [$itk_component($pane) childSite] |
| } |
| |
| return $children |
| |
| } else { |
| set index [index [lindex $args 0]] |
| return [$itk_component([lindex $_panes $index]) childSite] |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: fraction percentage percentage ?percentage ...? |
| # |
| # Sets the visible percentage of the panes. Specifies a list of |
| # percentages which are applied to the currently visible panes from |
| # the near side (left/top). The number of percentages must be equal |
| # to the current number of visible (mapped) panes and add up to 100. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::fraction {args} { |
| #set args [linsert $args 0 $percentage1 $percentage2] |
| |
| |
| if {[llength $args] == [llength $_activePanes]} { |
| set sum 0 |
| |
| for {set i 0} {$i < [llength $args]} {incr i} { |
| set sum [expr {$sum + [lindex $args $i]}] |
| } |
| |
| if {$sum == 100} { |
| set perc 0.0 |
| |
| for {set i 0} {$i < [llength $_activePanes]} {incr i} { |
| set _frac($i) $perc |
| set perc [expr {$perc + [expr {[lindex $args $i] / 100.0}]}] |
| } |
| |
| set _frac($i) 1.0 |
| |
| if {[winfo ismapped $itk_component(hull)]} { |
| _placePanes |
| } |
| |
| } else { |
| error "bad fraction arguments \"$args\": they should add\ |
| up to 100" |
| } |
| |
| } elseif {[llength $args] == 0} { |
| |
| for {set i 0; set j 1} {$j < [llength $_activePanes]} {incr i; incr j} { |
| lappend _ret [expr {round(($_frac($j) - $_frac($i))*100)}] |
| } |
| lappend _ret [eval expr {100 - ([join $_ret +])}] |
| |
| return $_ret |
| } else { |
| error "wrong # args: should be \"$itk_component(hull)\ |
| fraction percentage percentage ?percentage ...?\",\ |
| where the number of percentages is\ |
| [llength $_activePanes] and equal 100 |
| or \"$itk_component(hull) fraction\" |
| which will return a list of the current percentages" |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: add tag ?option value option value ...? |
| # |
| # Add a new pane to the paned window to the far (right/bottom) side. |
| # The method takes additional options which are passed on to the |
| # pane constructor. These include -margin, and -minimum. The path |
| # of the pane is returned. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::add {tag args} { |
| # |
| # Create panes. |
| # |
| itk_component add $tag { |
| eval iwidgets::Pane $itk_interior.pane[incr _unique] $args |
| } { |
| keep -background -cursor |
| } |
| |
| lappend _panes $tag |
| lappend _activePanes $tag |
| |
| reset |
| |
| return $itk_component($tag) |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: insert index tag ?option value option value ...? |
| # |
| # Insert the specified pane in the paned window just before the one |
| # given by index. Any additional options which are passed on to the |
| # pane constructor. These include -margin, -minimum. The path of |
| # the pane is returned. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::insert {index tag args} { |
| # |
| # Create panes. |
| # |
| itk_component add $tag { |
| eval iwidgets::Pane $itk_interior.pane[incr _unique] $args |
| } { |
| keep -background -cursor |
| } |
| |
| set index [index $index] |
| set _panes [linsert $_panes $index $tag] |
| lappend _activePanes $tag |
| |
| reset |
| |
| return $itk_component($tag) |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: delete index |
| # |
| # Delete the specified pane. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::delete {index} { |
| set index [index $index] |
| set tag [lindex $_panes $index] |
| |
| destroy $itk_component($tag) |
| |
| set _panes [lreplace $_panes $index $index] |
| |
| reset |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: hide index |
| # |
| # Remove the specified pane from the paned window. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::hide {index} { |
| set index [index $index] |
| set tag [lindex $_panes $index] |
| |
| if {[set idx [lsearch -exact $_activePanes $tag]] != -1} { |
| set _activePanes [lreplace $_activePanes $idx $idx] |
| } |
| |
| reset |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: show index |
| # |
| # Display the specified pane in the paned window. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::show {index} { |
| set index [index $index] |
| set tag [lindex $_panes $index] |
| |
| if {[lsearch -exact $_activePanes $tag] == -1} { |
| lappend _activePanes $tag |
| } |
| |
| reset |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: paneconfigure index ?option? ?value option value ...? |
| # |
| # Configure a specified pane. This method allows configuration of |
| # panes from the Panedwindow level. The options may have any of the |
| # values accepted by the add method. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::paneconfigure {index args} { |
| set index [index $index] |
| set tag [lindex $_panes $index] |
| |
| return [uplevel $itk_component($tag) configure $args] |
| } |
| |
| # ------------------------------------------------------------------ |
| # METHOD: reset |
| # |
| # Redisplay the panes based on the default percentages of the panes. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::reset {} { |
| if {$_initialized && [llength $_panes]} { |
| _setActivePanes |
| _setFracArray |
| |
| _makeSashes |
| _placePanes |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PROTECTED METHOD: _pwConfigureEventHandler |
| # |
| # Performs operations necessary following a configure event. This |
| # includes placing the panes. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_pwConfigureEventHandler {width height} { |
| set _width $width |
| set _height $height |
| if {$_initialized} { |
| _placePanes |
| } else { |
| set _initialized 1 |
| reset |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PROTECTED METHOD: _startGrip where num |
| # |
| # Starts the sash drag and drop operation. At the start of the drag |
| # operation all the information is known as for the upper and lower |
| # limits for sash movement. The calculation is made at this time and |
| # stored in protected variables for later access during the drag |
| # handling routines. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_startGrip {where num} { |
| if {$itk_option(-orient) == "horizontal"} { |
| set _dimension $_height |
| } else { |
| set _dimension $_width |
| } |
| |
| set _minsashmoved $num |
| set _maxsashmoved $num |
| set totMinHeight 0 |
| set cnt [llength $_activePanes] |
| set _sashloc(0) 0 |
| set _pixels($cnt) [expr {int($_dimension)}] |
| for {set i 0} {$i < $cnt} {incr i} { |
| set _pixels($i) [expr {int($_frac($i) * $_dimension)}] |
| set margaft [$itk_component([lindex $_activePanes $i]) cget -margin] |
| set minaft [$itk_component([lindex $_activePanes $i]) cget -minimum] |
| set _minheight($i) [expr {$minaft + (2 * $margaft)}] |
| incr totMinHeight $_minheight($i) |
| } |
| set _dragging [expr {$_dimension > $totMinHeight}] |
| |
| grab $itk_component(sash$num) |
| raise $itk_component(separator$num) |
| raise $itk_component(sash$num) |
| |
| $itk_component(sash$num) configure -relief sunken |
| } |
| |
| # ------------------------------------------------------------------ |
| # PROTECTED METHOD: _endGrip where num |
| # |
| # Ends the sash drag and drop operation. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_endGrip {where num} { |
| $itk_component(sash$num) configure -relief $_relief($itk_option(-showhandle)) |
| grab release $itk_component(sash$num) |
| if {$_dragging} { |
| _calcFraction [expr {$_sashloc($num) + $where}] $num |
| _placePanes [expr {$_minsashmoved - 1}] $_maxsashmoved |
| set _dragging 0 |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PROTECTED METHOD: _configGrip where num |
| # |
| # Configure action for sash. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_configGrip {where num} { |
| set _sashloc($num) $where |
| } |
| |
| # ------------------------------------------------------------------ |
| # PROTECTED METHOD: _handleGrip where num |
| # |
| # Motion action for sash. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_handleGrip {where num} { |
| if {$_dragging} { |
| _moveSash [expr {$where + $_sashloc($num)}] $num |
| incr _movecount |
| if {$_movecount>4} { |
| set _movecount 0 |
| update idletasks |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PROTECTED METHOD: _moveSash where num |
| # |
| # Move the sash to the absolute pixel location |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_moveSash {where num} { |
| set _minsashmoved [expr {($_minsashmoved<$num)?$_minsashmoved:$num}] |
| set _maxsashmoved [expr {($_maxsashmoved>$num)?$_maxsashmoved:$num}] |
| set oldfrac $_frac($num) |
| _calcFraction $where $num |
| if {$_frac($num)!=$oldfrac} { _placeSash $num } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PRIVATE METHOD: _setFracArray |
| # |
| # Calculates the percentages for the fraction array which lists the |
| # percentages for each pane. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_setFracArray {} { |
| set perc 0.0 |
| if {[llength $_activePanes] != 0} { |
| set percIncr [expr {1.0 / [llength $_activePanes]}] |
| } |
| |
| for {set i 0} {$i < [llength $_activePanes]} {incr i} { |
| set _frac($i) $perc |
| set perc [expr {$perc + $percIncr}] |
| } |
| |
| set _frac($i) 1.0 |
| } |
| |
| # ------------------------------------------------------------------ |
| # PRIVATE METHOD: _setActivePanes |
| # |
| # Resets the active pane list. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_setActivePanes {} { |
| set _prevActivePanes $_activePanes |
| |
| set _activePanes {} |
| |
| foreach pane $_panes { |
| if {[lsearch -exact $_prevActivePanes $pane] != -1} { |
| lappend _activePanes $pane |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PRIVATE METHOD: _calcFraction where num |
| # |
| # Determines the fraction for the sash. Make sure the fraction does |
| # not go past the minimum for the pane on each side of the separator. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_calcFraction {where num} { |
| |
| set numi [expr {$num + 1}] |
| set numd [expr {$num - 1}] |
| |
| set _lowerlimit [expr {$_pixels($numd) + $_minheight($numd)}] |
| set _upperlimit [expr {$_pixels($numi) - $_minheight($num)}] |
| |
| set dir [expr {$where - $_pixels($num)}] |
| |
| if {$where < $_lowerlimit && $dir <= 0} { |
| if {$num == 1} { |
| set _pixels($num) $_lowerlimit |
| } { |
| _moveSash [expr {$where - $_minheight($numd)}] $numd |
| set _pixels($num) [expr {$_pixels($numd) + $_minheight($numd)}] |
| } |
| } elseif {$where > $_upperlimit && $dir >= 0} { |
| if {$numi == [llength $_activePanes]} { |
| set _pixels($num) $_upperlimit |
| } { |
| _moveSash [expr {$where + $_minheight($num)}] $numi |
| set _pixels($num) \ |
| [expr {$_pixels($numi) - $_minheight($num)}] |
| } |
| } else { |
| set _pixels($num) $where |
| } |
| set _frac($num) [expr $_pixels($num).0 / $_dimension] |
| } |
| |
| # ------------------------------------------------------------------ |
| # PRIVATE METHOD: _makeSashes |
| # |
| # Removes any previous sashes and separators and creates new one. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_makeSashes {} { |
| # |
| # Remove any existing sashes and separators. |
| # |
| foreach sash $_sashes { |
| destroy $itk_component($sash) |
| } |
| |
| foreach separator $_separators { |
| destroy $itk_component($separator) |
| } |
| |
| set _sashes {} |
| set _separators {} |
| |
| # |
| # Create one less separator and sash than the number of panes. |
| # |
| for {set id 1} {$id < [llength $_activePanes]} {incr id} { |
| itk_component add sash$id { |
| frame $itk_interior.sash$id -relief $_relief($itk_option(-showhandle)) \ |
| -borderwidth $itk_option(-sashborderwidth) \ |
| -cursor $itk_option(-sashcursor) \ |
| -width $itk_option(-sashwidth) \ |
| -height $itk_option(-sashheight) |
| } { |
| keep -background |
| } |
| |
| lappend _sashes sash$id |
| |
| switch $itk_option(-orient) { |
| vertical { |
| bind $itk_component(sash$id) <Button-1> \ |
| [itcl::code $this _startGrip %x $id] |
| bind $itk_component(sash$id) <B1-Motion> \ |
| [itcl::code $this _handleGrip %x $id] |
| bind $itk_component(sash$id) <B1-ButtonRelease-1> \ |
| [itcl::code $this _endGrip %x $id] |
| bind $itk_component(sash$id) <Configure> \ |
| [itcl::code $this _configGrip %x $id] |
| } |
| |
| horizontal { |
| bind $itk_component(sash$id) <Button-1> \ |
| [itcl::code $this _startGrip %y $id] |
| bind $itk_component(sash$id) <B1-Motion> \ |
| [itcl::code $this _handleGrip %y $id] |
| bind $itk_component(sash$id) <B1-ButtonRelease-1> \ |
| [itcl::code $this _endGrip %y $id] |
| bind $itk_component(sash$id) <Configure> \ |
| [itcl::code $this _configGrip %y $id] |
| } |
| } |
| |
| itk_component add separator$id { |
| frame $itk_interior.separator$id -relief sunken \ |
| -height $itk_option(-thickness) \ |
| -width $itk_option(-thickness) \ |
| -borderwidth [expr {$itk_option(-thickness) / 2}] |
| } { |
| keep -background -cursor |
| } |
| |
| lappend _separators separator$id |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PRIVATE METHOD: _placeSash i |
| # |
| # Places the position of the sash and separator. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_placeSash {i} { |
| if {$itk_option(-orient) == "horizontal"} { |
| place $itk_component(separator$i) -in $itk_component(hull) \ |
| -x 0 -relwidth 1 -rely $_frac($i) -anchor w \ |
| -height $itk_option(-thickness) |
| |
| if {$itk_option(-sashindent) < 0} { |
| set sashPos [expr {$_width + $itk_option(-sashindent)}] |
| set sashAnchor e |
| } else { |
| set sashPos $itk_option(-sashindent) |
| set sashAnchor w |
| } |
| |
| if {$itk_option(-showhandle)} { |
| place $itk_component(sash$i) -in $itk_component(hull) \ |
| -x $sashPos -rely $_frac($i) -anchor $sashAnchor |
| } else { |
| place $itk_component(sash$i) -in $itk_component(hull) \ |
| -x 0 -relwidth 1 -rely $_frac($i) -anchor w \ |
| -height $itk_option(-thickness) |
| } |
| |
| } else { |
| place $itk_component(separator$i) -in $itk_component(hull) \ |
| -y 0 -relheight 1 -relx $_frac($i) -anchor n \ |
| -width $itk_option(-thickness) |
| |
| if {$itk_option(-sashindent) < 0} { |
| set sashPos [expr {$_height + $itk_option(-sashindent)}] |
| set sashAnchor s |
| } else { |
| set sashPos $itk_option(-sashindent) |
| set sashAnchor n |
| } |
| |
| if {$itk_option(-showhandle)} { |
| |
| place $itk_component(sash$i) -in $itk_component(hull) \ |
| -y $sashPos -relx $_frac($i) -anchor $sashAnchor |
| } else { |
| place $itk_component(sash$i) -in $itk_component(hull) \ |
| -y 0 -relheight 1 -relx $_frac($i) -anchor n \ |
| -width $itk_option(-thickness) |
| } |
| } |
| } |
| |
| # ------------------------------------------------------------------ |
| # PRIVATE METHOD: _placePanes |
| # |
| # Resets the panes of the window following movement of the sash. |
| # ------------------------------------------------------------------ |
| itcl::body iwidgets::Panedwindow::_placePanes {{start 0} {end end}} { |
| if {$end=="end"} { set end [expr {[llength $_activePanes] - 1}] } |
| set _updatePanes [lrange $_activePanes $start $end] |
| if {$_updatePanes == $_activePanes} { |
| set _forgetPanes $_panes |
| } { |
| set _forgetPanes $_updatePanes |
| } |
| foreach pane $_forgetPanes { |
| place forget $itk_component($pane) |
| } |
| |
| |
| if {$itk_option(-orient) == "horizontal"} { |
| set i $start |
| foreach pane $_updatePanes { |
| place $itk_component($pane) -in $itk_component(hull) \ |
| -x 0 -rely $_frac($i) -relwidth 1 \ |
| -relheight [expr {$_frac([expr {$i + 1}]) - $_frac($i)}] |
| incr i |
| } |
| |
| } else { |
| set i $start |
| foreach pane $_updatePanes { |
| place $itk_component($pane) -in $itk_component(hull) \ |
| -y 0 -relx $_frac($i) -relheight 1 \ |
| -relwidth [expr {$_frac([expr {$i + 1}]) - $_frac($i)}] |
| incr i |
| } |
| |
| } |
| |
| for {set i [expr {$start+1}]} {$i <= $end} {incr i} { |
| if {[array names itk_component separator$i] != ""} { |
| _placeSash $i |
| raise $itk_component(separator$i) |
| raise $itk_component(sash$i) |
| } |
| } |
| } |