Keith Vetter 2007-10-12 : I'd thought I'd share some new techniques I've created while adding a new feature to my KLIMB bike mapping program which lets you plan bike routes interactively on topo maps [L1 ].
The new feature is another way of printing out bike routes by collecting multiple, smaller map segments and laying them out on a page. The key problem, however, is that the smaller map segments, in order to better cover the bike route, can be at any angle.
I'm still working on this new feature, and would like feedback on it, especially on the user interaction in specifying the map segment--it's tricky because the user can move, rotate and resize the selection.
A selection box is drawn on the map. The user can grab and move it anywhere. Grabbing the SE corner or by using the 3rd button, the user can rotate the box. Grabbing either of two resize controls lets you change the size.
The second aspect of this problem is laying out the results, and I haven't really done much with that yet. The third aspect is printing the result--that's going to be real fun to solve.
I included demo code, including a sample map image (compressed to death jpeg so it doesn't look great).
Some technical details.
The hardest/funnest part was extracting an angled rectangle area off a canvas. Initially I used TclMagick to do it, but because of poor documentation (I ended up using the php doc) and a few programming snags, I realized that that was overkill. Instead I used xphoto from Enhanced photo image copy command.
I use Img to grab the whole window, then crop that image to the bounding box of the selection. Next, I use xphoto to rotate the image. Then, after some simple trig, I use Img again to crop down to the selected area.
##+##########################################################################
#
# Clipbox -- grabs rectangular region of an image at any angle or size
# by Keith Vetter, Sep, 2007
#
package require Tk
package require Img
set hasXPhoto 1
if {[catch {load xphoto.dll}]} {
wm withdraw .
set msg "ERROR: missing xphoto.dll\n\n"
append msg "This program requires the xphoto extension, which\n"
append msg "can be downloaded from https://wiki.tcl-lang.org/11924\n\n"
append msg "You can still run the program and interact with\n"
append msg "the map but you cannot take snapshots."
tk_messageBox -icon error -message $msg
set hasXPhoto 0
wm deiconify .
}
namespace eval ::ClipBox {
variable P ;# Box position
variable M ;# Mousing info
unset -nocomplain P
set P(clr,1) cyan
set P(clr,0) red
array set M {
xy {} minWidth 200 minHeight 200 mousing 0 resizeSize 8 cornerSize 15
cursor,corner exchange cursor,strip hand2 cursor,width fleur
cursor,height fleur
}
}
##+##########################################################################
#
# Go -- creates the initial instance of our clipping box
#
proc ::ClipBox::Go {W p0 angle width height} {
variable P
set P(0) $p0
set P(a,deg) $angle
set P(w) $width
set P(h) $height
$W delete BOX
$W create poly -tag {BOX clip} -fill cyan -stipple gray50 -width 2 \
-outline black -dash -
$W create poly -tag {BOX corner} -outline black -fill {} -width 2
$W create poly -tag {BOX width} -fill black
$W create poly -tag {BOX height} -fill black
$W create text -100 -100 -text "N" -font {Helvetica 20 bold} -fill red \
-anchor s -tag {BOX north northText}
$W create line -100 -100 -200 -200 -width 5 -tag {BOX north northLine} \
-fill red -arrow first -arrowshape {25 25 6}
foreach tag {clip corner width height} {
$W bind $tag <1> [list ::ClipBox::MouseDown %W $tag %x %y]
$W bind $tag <B1-Motion> [list ::ClipBox::MouseMove %W $tag %x %y]
$W bind $tag <ButtonRelease-1> [list ::ClipBox::MouseUp %W]
$W bind $tag <Enter> [list ::ClipBox::MouseEnter %W $tag]
$W bind $tag <Leave> [list ::ClipBox::MouseLeave %W $tag]
$W bind $tag <3> [list ::ClipBox::MouseDown %W corner %x %y]
$W bind $tag <B3-Motion> [list ::ClipBox::MouseMove %W corner %x %y]
$W bind $tag <ButtonRelease-3> [list ::ClipBox::MouseUp %W]
}
::ClipBox::DrawClipBox $W
}
##+##########################################################################
#
# DrawClipBox -- repositions all elements of our clipbox
#
proc ::ClipBox::DrawClipBox {W} {
set xy [::ClipBox::GetBoxCoords]
lassign [::ClipBox::GetSmallBoxCoords] bxy wxy hxy
lassign [::ClipBox::NorthArrow] top bot
$W coords clip $xy
$W coords corner $bxy
$W coords width $wxy
$W coords height $hxy
$W coords northText $top
$W coords northLine [concat $top $bot]
}
##+##########################################################################
#
# GetBoxCoords -- given topleft corner, width, height and angle
# returns coordinates of the box
#
proc ::ClipBox::GetBoxCoords {} {
variable P
set w $P(w)
set h $P(h)
set a $P(a,deg)
set a [expr {$a * acos(-1) / 180}] ;# Radians
lassign $P(0) x0 y0
set x1 [expr {$x0 + $w*cos($a)}]
set y1 [expr {$y0 + $w*sin($a)}]
set P(1) [list $x1 $y1]
set top [::Data::VSub $P(1) $P(0)]
set left [::Data::VNormalTo $top $h]
set P(3) [::Data::VAdd $P(0) $left]
set P(2) [::Data::VAdd $P(3) $top]
set xy [concat $P(0) $P(1) $P(2) $P(3)]
return $xy
}
##+##########################################################################
#
# GetSmallBoxCoords -- returns coords for rotate box and two sizing boxes
#
proc ::ClipBox::GetSmallBoxCoords {} {
variable P
variable M
# Assumes P(0-3) are correct
set top [::Data::VSub $P(1) $P(0)]
set left [::Data::VSub $P(3) $P(0)]
set nTop [::Data::VReScale $top 1]
set nLeft [::Data::VReScale $left 1]
set c2 $P(2)
set c1 [::Data::VAdd $c2 $nLeft -$M(cornerSize)]
set c0 [::Data::VAdd $c1 $nTop -$M(cornerSize)]
set c3 [::Data::VAdd $c0 $nLeft $M(cornerSize)]
set cxy [concat $c0 $c1 $c2 $c3]
# Width adjust box
set w [::Data::VAdd $P(1) $left .5]
set rSize2 [expr {$M(resizeSize)/2.0}]
set w1 [::Data::VAdd $w $nLeft -$rSize2]
set w0 [::Data::VAdd $w1 $nTop -$M(resizeSize)]
set w3 [::Data::VAdd $w0 $nLeft $M(resizeSize)]
set w2 [::Data::VAdd $w3 $nTop $M(resizeSize)]
set wxy [concat $w0 $w1 $w2 $w3]
# Height adjust box
set h [::Data::VAdd $P(3) $top .5]
set h2 [::Data::VAdd $h $nTop $rSize2]
set h1 [::Data::VAdd $h2 $nLeft -$M(resizeSize)]
set h0 [::Data::VAdd $h1 $nTop -$M(resizeSize)]
set h3 [::Data::VAdd $h0 $nLeft $M(resizeSize)]
set hxy [concat $h0 $h1 $h2 $h3]
return [list $cxy $wxy $hxy]
}
##+##########################################################################
#
# NorthArrow -- computes where north compass arrow should be positioned
#
proc ::ClipBox::NorthArrow {} {
variable P
set cornerOffset 35
set fudgeFactor {0 15}
set arrowLength {0 150}
set dir [expr {$P(a,deg) >= 0 ? 1 : -1}]
if {($P(a,deg) >= 0 && $P(a,deg) <= 90) || $P(a,deg) < -90} {
set bisect [::Data::VBisect $P(1) $P(0) $P(3)]
set pt $P(0)
} else {
set bisect [::Data::VBisect $P(2) $P(3) $P(0)]
set pt $P(3)
}
set pt1 [::Data::VAdd $pt $bisect $cornerOffset]
set top [::Data::VAdd $pt1 $fudgeFactor]
set bot [::Data::VAdd $top $arrowLength $dir]
if {$dir == -1} {lassign [list $bot $top] top bot}
return [list $top $bot]
}
proc ::ClipBox::MouseEnter {W who} {
variable M
if {[info exists M(cursor,$who)]} {
$W config -cursor $M(cursor,$who)
}
}
proc ::ClipBox::MouseLeave {W who} {
variable M
if {$M(mousing)} return ;# Mouse down, don't change
$W config -cursor {}
}
proc ::ClipBox::MouseDown {W who x y} {
variable M
variable P
set M(xy) [list [$W canvasx $x] [$W canvasy $y]]
set M(mousing) 1
if {$who eq "corner"} {
$W config -cursor $M(cursor,corner)
::ClipBox::FourCorners $W
# Create pivot
lassign $P(0) X Y
set xy [list [expr {$X-10}] [expr {$Y-10}] [expr {$X+10}] [expr {$Y+10}]]
$W create oval $xy -tag {BOX pivot} -fill black
::ClipBox::MouseMove $W $who $x $y
}
}
proc ::ClipBox::MouseUp {W} {
variable M
set M(mousing) 0
$W delete pivot
$W config -cursor {}
}
proc ::ClipBox::MouseMove {W who x y} {
variable M
set x [$W canvasx $x]
set y [$W canvasy $y]
if {$who eq "corner"} {
::ClipBox::MouseSpin $W $who $x $y
} elseif {$who eq "width" || $who eq "height"} {
::ClipBox::MouseResize $W $who $x $y
} else {
lassign $M(xy) bx by
set M(xy) [list $x $y]
set dx [expr {$x - $bx}]
set dy [expr {$y - $by}]
$W move BOX $dx $dy
::ClipBox::Onscreen $W
}
}
##+##########################################################################
#
# MouseSpin -- rotates clipbox to keep mouse point on the main diagonal
#
proc ::ClipBox::MouseSpin {W who x y} {
variable P
set v [::Data::VReScale [::Data::VSub [list $x $y] $P(0)] 1]
set n [::Data::VDot [list 1 0] $v]
set a1 [expr {acos($n)}]
if {[lindex $v 1] < 0} { set a1 [expr {-$a1}] } ;# Quadrant check
set a2 [expr {atan2($P(h), $P(w))}]
set a3 [expr {$a1 - $a2}]
set P(a,deg) [expr {$a3 * 180 / acos(-1)}]
::ClipBox::DrawClipBox $W
::ClipBox::Onscreen $W
}
##+##########################################################################
#
# MouseResize -- resizes clipbox vertically or horizontally
#
proc ::ClipBox::MouseResize {W who x y} {
variable P
variable M
::ClipBox::FourCorners $W
set top [::Data::VSub $P(1) $P(0)]
set left [::Data::VSub $P(3) $P(0)]
set nTop [::Data::VReScale $top 1]
set nLeft [::Data::VReScale $left 1]
if {$who eq "width"} {
set p0 [::Data::VAdd $P(0) $left .5]
set v [::Data::VSub [list $x $y] $p0]
set w [::Data::VDot $nTop $v]
if {$w < $M(minWidth)} return
set P(w) $w
} else {
set p0 [::Data::VAdd $P(0) $top .5]
set v [::Data::VSub [list $x $y] $p0]
set h [::Data::VDot $nLeft $v]
if {$h < $M(minHeight)} return
set P(h) $h
}
::ClipBox::DrawClipBox $W
::ClipBox::Onscreen $W
}
##+##########################################################################
#
# Onscreen -- figures out if clipbox is off the screen at all
#
proc ::ClipBox::Onscreen {W} {
variable P
lassign [$W coords clip] x0 y0 x1 y1 x2 y2 x3 y3
set l [expr {round([::Data::Min $x0 $x1 $x2 $x3])}]
set r [expr {round([::Data::Max $x0 $x1 $x2 $x3])}]
set t [expr {round([::Data::Min $y0 $y1 $y2 $y3])}]
set b [expr {round([::Data::Max $y0 $y1 $y2 $y3])}]
set cx0 [$W canvasx 0]
set cy0 [$W canvasy 0]
set cx1 [expr {$cx0 + [winfo width $W]}]
set cy1 [expr {$cy0 + [winfo height $W]}]
set onscreen 1
if {$l < $cx0 || $t < $cy0 || $r > $cx1 || $b > $cy1} {
set onscreen 0
}
$W itemconfig clip -fill $P(clr,$onscreen)
return $onscreen
}
proc ::ClipBox::PointOnscreen {W pt} {
lassign $pt x y
set cx0 [$W canvasx 0]
set cy0 [$W canvasy 0]
set cx1 [expr {$cx0 + [winfo width $W]}]
set cy1 [expr {$cy0 + [winfo height $W]}]
return [expr {$x >= $cx0 && $x <= $cx1 && $y >= $cy0 && $y <= $cy1}]
}
##+##########################################################################
#
# FourCorners -- fills in our data structures with clipbox's corners
#
proc ::ClipBox::FourCorners {W} {
variable P
foreach idx {0 1 2 3} {x y} [$W coords clip] {
set P($idx) [list $x $y]
}
}
##+##########################################################################
#
# GetClipBoxSizes -- computes parameters needed to crop, rotate
# and crop again the image
#
proc ::ClipBox::GetClipBoxSizes {W} {
variable P
::ClipBox::FourCorners $W
lassign $P(0) x0 y0; lassign $P(1) x1 y1; lassign $P(2) x2 y2; lassign $P(3) x3 y3
set l [expr {round([::Data::Min $x0 $x1 $x2 $x3])}]
set r [expr {round([::Data::Max $x0 $x1 $x2 $x3])}]
set t [expr {round([::Data::Min $y0 $y1 $y2 $y3])}]
set b [expr {round([::Data::Max $y0 $y1 $y2 $y3])}]
#set P(bbox) [list $l $t $r $b]
set P(bbox) [::ClipBox::World2Canvas $W $l $t $r $b]
set dy [expr {$y1 - $y0}]
set dx [expr {$x1 - $x0}]
set dx2 [expr {$x3 - $x0}]
set dy2 [expr {$y3 - $y0}]
# Question: use values from p or recompute from coordinates???
set P(a,rad) [expr {atan2($dy,$dx)}]
set P(a,deg) [expr {$P(a,rad)*180/acos(-1)}]
set P(w) [expr {round(hypot($dx,$dy))}]
set P(h) [expr {round(hypot($dx2,$dy2))}]
# R0 is topleft corner in the rotated image
# R1 is bottomright corner in the rotated image
set P(rx0) [expr {abs(round($dy2 * sin($P(a,rad))))}]
set P(ry0) [expr {abs(round($dx * sin($P(a,rad))))}]
set P(rx1) [expr {$P(rx0) + $P(w)}]
set P(ry1) [expr {$P(ry0) + $P(h)}]
}
##+##########################################################################
#
# World2Canvas -- translates world coordinates into canvas ones
#
proc ::ClipBox::World2Canvas {W args} {
set x0 [$W canvasx 0]
set y0 [$W canvasy 0]
set result {}
foreach {x y} $args {
set x [expr {round($x - $x0)}]
set y [expr {round($y - $y0)}]
lappend result $x $y
}
return $result
}
##+##########################################################################
#
# Snapshot -- extracts content of the clipbox, with the proper
# cropping and rotating.
#
proc ::ClipBox::Snapshot {W} {
variable P
# Hide everything except compass north
raise [winfo toplevel $W]
$W lower BOX ; $W raise north
update idletasks
::ClipBox::GetClipBoxSizes $W
set snap [image create photo -data $W]
set rot [image create photo]
set chop [image create photo]
$W raise BOX ; $W raise north
set crop [eval ::ClipBox::SafeCrop $snap $P(bbox)]
$rot copy $crop -rotate $P(a,deg)
$chop copy $rot -from $P(rx0) $P(ry0) $P(rx1) $P(ry1)
image delete $snap
image delete $crop
image delete $rot
if {[::ClipBox::PointOnscreen $W $P(1)]} { ;# Move clipbox forward
set P(0) $P(1)
::ClipBox::DrawClipBox $W
}
return $chop
}
##+##########################################################################
#
# SafeCrop -- crops image handling off image coordinates
#
proc ::ClipBox::SafeCrop {cimg left top right bottom} {
set w [image width $cimg]
set h [image height $cimg]
set pad(l) [expr {$left < 0 ? -$left : 0}]
set left [::Data::Max $left 0]
set pad(t) [expr {$top < 0 ? -$top : 0}]
set top [::Data::Max $top 0]
set pad(r) [expr {$right > $w ? $right-$w : 0}]
set right [::Data::Min $right $w]
set pad(b) [expr {$bottom > $h ? $bottom-$h : 0}]
set bottom [::Data::Min $bottom $h]
set crop [image create photo]
$crop copy $cimg -from $left $top $right $bottom
set pimg [::ClipBox::PadImage $crop $pad(l) $pad(t) $pad(r) $pad(b)]
return $pimg
}
##+##########################################################################
#
# PadImage -- adds requested borders to the image
#
proc ::ClipBox::PadImage {img left top right bottom} {
if {$left == 0 && $top == 0 && $right == 0 && $bottom == 0} {return $img}
set w [expr {[image width $img] + $left + $right}]
set h [expr {[image height $img] + $top + $bottom}]
set tmp [image create photo -width $w -height $h]
$tmp put yellow -to 0 0 $w $h
$tmp copy $img -to $left $top
image delete $img
return $tmp
}
namespace eval ::ShowPics {
variable S
unset -nocomplain S
image create bitmap ::bmp::up -data {
#define up_width 11
#define up_height 11
static char up_bits = {
0x00, 0x00, 0x20, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfc, 0x01, 0xfe,
0x03, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00
}
}
image create bitmap ::bmp::down -data {
#define down_width 11
#define down_height 11
static char down_bits = {
0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0xfe,
0x03, 0xfc, 0x01, 0xf8, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00
}
}
image create bitmap ::bmp::x -foreground white -data {
#define X_width 11
#define X_height 11
static char X_bits = {
0x04, 0x01, 0x8e, 0x03, 0xdf, 0x07, 0xfe, 0x03, 0xfc, 0x01, 0xf8,
0x00, 0xfc, 0x01, 0xfe, 0x03, 0xdf, 0x07, 0x8e, 0x03, 0x04, 0x01
}
}
}
proc ::ShowPics::ShowImg {W} {
variable S
global I
set img [::ClipBox::Snapshot $W]
if {! [winfo exists .show]} {
toplevel .show
wm protocol .show WM_DELETE_WINDOW ::ShowPics::Cleanup
wm title .show "Snap Shot Gallery"
RightWindow .show $W
#wm transient .show [winfo toplevel $W]
unset -nocomplain S
}
set id [expr {1 + [llength [grid slaves .show]]}]
set w .show.$id
frame $w
grid $w -sticky w
if {$id > 1} { grid config $w -pady {10 0}}
button $w.up -image ::bmp::up -takefocus 0 \
-command [list ::ShowPics::Swap up $id]
button $w.x -image ::bmp::x -bg red -takefocus 0 \
-command [list ::ShowPics::DeleteRow $id]
button $w.down -image ::bmp::down -takefocus 0 \
-command [list ::ShowPics::Swap down $id]
frame $w.right -bd 2 -relief solid
::ShowPics::OneImage $w.right $img $id
set S($id,img) $img
set S($id,txt) "<description for this map>"
::ShowPics::DoButtons
grid $w.up $w.right -sticky s
grid $w.x ^ -pady 5
grid $w.down ^ -sticky n -pady [list 0 [winfo reqheight $w.right.txt]]
grid rowconfigure $w {0 2} -weight 1
grid columnconfigure $w 0 -pad 10
raise .show
}
proc ::ShowPics::Cleanup {} {
variable S
destroy .show
foreach arr [array names S *,img] {
image delete $S($arr)
}
unset -nocomplain S
}
proc ::ShowPics::OneImage {w img id} {
variable S
set S($id,w) $w.img
label $w.img -image $img -bd 0
label $w.id -text "MAP $id" -font {Helvetica 12 bold} -anchor e
entry $w.txt -font {Helvetica 12 bold} -justify c -bd 0 \
-textvariable ::ShowPics::S($id,txt)
pack $w.img -side top -fill both -expand 1
pack $w.id -side right
pack $w.txt -side left -fill both -expand 1
}
proc ::ShowPics::SwapRows {row1 row2} {
variable S
set txt $S($row1,txt)
set S($row1,txt) $S($row2,txt)
set S($row2,txt) $txt
set img $S($row1,img)
set S($row1,img) $S($row2,img)
set S($row2,img) $img
$S($row1,w) config -image $S($row1,img)
$S($row2,w) config -image $S($row2,img)
}
proc ::ShowPics::Swap {dir which} {
set other [expr {$dir eq "up" ? $which-1 : $which+1}]
::ShowPics::SwapRows $which $other
}
proc ::ShowPics::DeleteRow {which} {
variable S
set len [llength [array names S *,img]]
for {set row $which} {$row < $len} {incr row} {
::ShowPics::SwapRows $row [expr {$row+1}]
}
destroy .show.$len
image delete $S($len,img)
array unset S $len,*
::ShowPics::DoButtons
if {$len == 1} ::ShowPics::Cleanup
}
proc ::ShowPics::DoButtons {} {
variable S
set len [llength [array names S *,img]]
if {$len == 0} return
for {set i 1} {$i <= $len} {incr i} {
.show.$i.up config -state normal
.show.$i.down config -state normal
}
.show.1.up config -state disabled
.show.$len.down config -state disabled
}
################################################################
#
# Utility routines
#
namespace eval ::Data {}
proc ::Data::Max {a args} {
foreach arg $args {if {$arg > $a} { set a $arg}}
return $a
}
proc ::Data::Min {a args} {
foreach arg $args {if {$arg < $a} { set a $arg}}
return $a
}
proc ::Data::VAdd {v1 v2 {scaling 1}} {
lassign $v1 x1 y1; lassign $v2 x2 y2
return [list [expr {$x1 + $scaling*$x2}] [expr {$y1 + $scaling*$y2}]]
}
proc ::Data::VSub {v1 v2} { return [::Data::VAdd $v1 $v2 -1] }
proc ::Data::VReScale {v scaling} {
lassign $v x y
set len [expr {hypot($x,$y)}]
return [list [expr {$x * $scaling / $len}] [expr {$y * $scaling / $len}]]
}
proc ::Data::VNormalTo {vv length} {
lassign $vv x y
set len [expr {hypot($x,$y)}]
set xx [expr {-$y * $length / $len}]
set yy [expr {$x * $length / $len}]
return [list $xx $yy]
}
proc ::Data::VBisect {p1 p2 p3} {
set v1 [::Data::VReScale [::Data::VSub $p1 $p2] 1]
set v2 [::Data::VReScale [::Data::VSub $p3 $p2] 1]
set v [::Data::VReScale [::Data::VAdd $v1 $v2] 1]
return $v
}
proc ::Data::VDot {v1 v2} {
lassign $v1 x1 y1; lassign $v2 x2 y2
return [expr {$x1*$x2 + $y1*$y2}]
}
proc RightWindow {w {W .}} {
update idletasks
set W [winfo toplevel $W]
set y [expr {3 + [winfo y $W]}] ;# Top of main window
set x [expr {15 + [winfo x $W] + [winfo width $W]}] ;# Right side
wm geom $w +$x+$y
}
################################################################
#
# DEMO CODE BELOW
#
image create photo ::img::img -data {
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAP//////////////////////////////////////////
////////////////////////////////////////////2wBDAf//////////////////////////
////////////////////////////////////////////////////////////wAARCALrBEADASIA
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
dgaAAAlZyjUoAka1KAAAAH//2Q==
}
proc About {} {
set msg "Route Map Selection\nby Keith Vetter\n\n"
append msg "This demonstrates a package that lets\n"
append msg "select arbitrary rectangular areas of\n"
append msg "canvas and to extract exactly that area.\n\n"
append msg "You can move the selection by dragging it,\n"
append msg "you can resize the selection by dragging\n"
append msg "a resize button, and you can rotate the\n"
append msg "selection by dragging the resize control\n"
append msg "or by dragging with the 3rd mouse button.\n"
tk_messageBox -icon info -message $msg
}
################################################################
#
# Demo code
proc DoDisplay {} {
bind all <F2> {console show}
wm title . "Clip Box Demo"
canvas .c -highlightthickness 0 -bd 0 \
-width [image width ::img::img] -height [image height ::img::img]
.c create image 0 0 -image ::img::img -anchor nw
.c config -scrollregion [.c bbox all]
button .chop -text "Take Snap Shot" -command [list ::ShowPics::ShowImg .c]
if {! $::hasXPhoto} { .chop config -state disabled }
button .about -text About -command About
pack .c -side top
#pack .chop .about -side left -pady 10 -expand 1 -padx 10
pack .about -side right -padx 10 -pady 10
pack .chop -side bottom -pady 10
bind .c <2> [bind Text <2>] ;# Enable dragging w/ <2>
bind .c <B2-Motion> [bind Text <B2-Motion>]
}
DoDisplay
wm geom . +1+1
::ClipBox::Go .c {35 135} -7 700 200
set W .c
return