DANGER WILL ROBINSON. Something's not right with the following code. It defines a proc named set (ring any bells, anyone?), and exports it. When I cut and paste the following code it fails with too many nested calls to "set" (gee, that's a surprise, since the proc set uses the set command).
namespace eval pane {
namespace export create set
proc create {f1 f2 args} {
### Map optional arguments into array values ###
set t(-orient) horizontal rray values ###
set t(-percent) 0.5
set t(-in) [winfo parent $f1]
array set t $args
### Keep state in an array associated with the master frame ###
set master $t(-in)
pack $master -expand true -fill both
pack propagate $master off
upvar #0 [namespace current]::Pane$master pane
array set pane [array get t]
set pane(1) $f1
set pane(2) $f2
set pane(grip) $master.grip
frame $pane(grip) -background gray75 -width 10 -height 10 -bd 1 -relief raised
if {[string match vert* $pane(-orient)]} {
### Adjust boundary in Y direction ###
set pane(D) Y
place $pane(1) -in $master -x 0 -rely 0.0 -anchor nw -relwidth 1.0 -height -1
place $pane(2) -in $master -x 0 -rely 1.0 -anchor sw -relwidth 1.0 -height -1
place $pane(grip) -in $master -anchor c -relx 0.8
$pane(grip) configure -cursor sb_v_double_arrow
} else {
### Adjust boundary in X direction ###
set pane(D) X
place $pane(1) -in $master -relx 0.0 -y 0 -anchor nw -relheight 1.0 -width -1
place $pane(2) -in $master -relx 1.0 -y 0 -anchor ne -relheight 1.0 -width -1
place $pane(grip) -in $master -anchor c -rely 0.2
$pane(grip) configure -cursor sb_h_double_arrow
}
$master configure -background grey75
### bindings for resize AKA <Configure>, and dragging the grip. ###
bind $master <Configure> [namespace code [list Geometry $master]]
bind $pane(grip) <B1-Motion> [namespace code [list Drag $master %$pane(D)]]
bind $pane(grip) <ButtonRelease-1> [namespace code [list Stop $master]]
### Do the initial layout ###
Geometry $master
}
proc set {master value} {
set [namespace current]::Pane${master}(-percent) $value
Geometry $master
}
proc Drag {master D} {
upvar #0 [namespace current]::Pane$master pane
if [info exists pane(lastD)] {
set delta [expr {double($pane(lastD)-$D)/$pane(size)}]
set pane(-percent) [expr {$pane(-percent) - $delta}]
if {$pane(-percent) < 0.0} {
set pane(-percent) 0.0
} elseif {$pane(-percent) > 1.0} {
set pane(-percent) 1.0
}
Geometry $master
}
set pane(lastD) $D
}
proc Stop {master} {
upvar #0 [namespace current]::Pane$master pane
catch {unset pane(lastD)}
}
proc Geometry {master} {
upvar #0 [namespace current]::Pane$master pane
if {$pane(D) == "X"} {
place $pane(1) -relwidth $pane(-percent)
place $pane(2) -relwidth [expr {1.0 - $pane(-percent)}]
place $pane(grip) -relx $pane(-percent)
set pane(size) [winfo width $master]
} else { # $pane(D) == "Y"
place $pane(1) -relheight $pane(-percent)
place $pane(2) -relheight [expr {1.0 - $pane(-percent)}]
place $pane(grip) -rely $pane(-percent)
set pane(size) [winfo height $master]
}
}
}Here's a usage example with horiz and vertical panes: proc pane::test {{p .p} {orient hori}} {
catch {destroy $p}
frame $p -width 200 -height 200 ;# needed: no propagation
message $p.1 -bg bisque -text [info procs] -relief ridge
frame $p.2
label $p.2.foo -bg pink -text foo -relief ridge
label $p.2.bar -bg grey75 -text bar -relief ridge
pack $p -expand true -fill both
pack propagate $p off
pane::create $p.2.foo $p.2.bar -orient vert
pane::create $p.1 $p.2 -orient $orient -percent 0.7
raise .
}Wow - that's a lot of code up there. Here's a simpler example written by Stephen Uhler. - DL
# 2 panes, one on top of the other (>= Tk4.0)
frame .top
frame .bottom
frame .handle -borderwidth 2 -relief raised
-bg orange -cursor sb_v_double_arrow
. configure -bg black
# fixed placement parameters
place .top -relwidth 1 -height -1
place .bottom -relwidth 1 -rely 1 -anchor sw -height -1
place .handle -relx 0.9 -anchor e -width 10 -height 10
bind . <Configure> {set H [winfo height .]; set Y0 [winfo rooty .]}
bind .handle <B1-Motion> {Place [expr {(%Y-$Y0)/double($H)}]}
proc Place {fract} {
place .top -relheight $fract
place .handle -rely $fract
place .bottom -relheight [expr {1.0 - $fract}]
}
Place .5 ;# initialization
# now "pack" whatever you like in ".top" and ".bottom"I like the simpler one but I kept losing the pane when I dragged it off of the window. Change the "Place" proc to be
proc Place {fract} {
if { ($fract>=0.01) && ($fract<=0.99) } {
place .top -relheight $fract
place .handle -rely $fract
place .bottom -relheight [expr {1.0 - $fract}]
}
}Notice the if statement. Once this was added I could not drag the panes off of the window.EKB April 9, 2005A simple change to the simpler version lets you grab the divider line at any point. Replace:
place .handle -relx 0.9 -anchor e -width 10 -height 10with
place .handle -relwidth 1 -x 0 -anchor w -height 5Then if you turn off "-bg orange" when creating .handle, it looks a lot like pane dividers in most programs.

