You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
943 lines
31 KiB
Plaintext
943 lines
31 KiB
Plaintext
#
|
|
# 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)
|
|
}
|
|
}
|
|
}
|