blob: a9496c74e0235dd193fb680edef0bf4052c53617 [file] [log] [blame]
# util-tk.tcl --
#
# This file implements package ::Utility::tk, which ...
#
# Copyright (c) 1997-8 Jeffrey Hobbs
#
# See the file "license.terms" for information on usage and
# redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
package require Tk
package require ::Utility
package provide ::Utility::tk 1.0
namespace eval ::Utility::tk {;
namespace export -clear *
## PROBLEM HERE
##
## Only uncomment one of the following namespace import lines
##
## This is what I theoretically need, but it causes the Abort in
## regular wish. This works for wish with TCL_MEM_DEBUG.
#namespace import -force ::Utility::get_opts ::Utility::highlight
## This works, but is essentially useless in my situation
#namespace import -force ::Utility::expand::* ::Utility::dump::*
## This works too, but is silly
after idle [namespace code [list namespace import -force \
::Utility::highlight ::Utility::get_opts]]
## This causes constant Bus Error on startup with regular wish
## but the Abort with debugging wish.
#namespace import -force ::Utility::*
## The abort message mentioned above is:
#DeleteImportedCmd: did not find cmd in real cmd's list of import references
#Abort
## If I try loading the above interactively as opposed to the tour at
## command line, I get a seg fault instead of a bus error.
##
## YOU CAN IGNORE THE REST
##
# warn --
#
# Simple warning alias to ease programming
#
# Arguments:
# msg The warning message to display
# Results:
# Returns nothing important.
#
proc warn {msg} {
bell
tk_dialog .__warning Warning $msg warning 0 OK
}
# place_window --
# place a toplevel at a particular position
# Arguments:
# toplevel name of toplevel window
# ?placement? pointer ?center? ; places $w centered on the pointer
# widget widget_name ; centers $w over widget_name
# defaults to placing toplevel in the middle of the screen
# ?anchor?
# Results:
# Returns nothing
#
proc place_window {w {placement ""} {anchor ""}} {
wm withdraw $w
update idletasks
switch -glob -- $placement {
p* { ## place at POINTER (centered is $anchor == center)
if {[string match "c*" $anchor]} {
wm geometry $w +[expr \
{[winfo pointerx $w]-[winfo width $w]/2}]+[expr \
{[winfo pointery $w]-[winfo height $w]/2}]
} else {
wm geometry $w +[winfo pointerx $w]+[winfo pointery $w]
}
}
w* { ## center about WIDGET $anchor
wm geometry $w +[expr {[winfo rootx $anchor]+([winfo width \
$anchor]-[winfo width $w])/2}]+[expr {[winfo rooty \
$anchor]+([winfo height $anchor]-[winfo height $w])/2}]
}
default {
wm geometry $w +[expr {([winfo screenwidth $w]-\
[winfo reqwidth $w])/2}]+[expr \
{([winfo screenheight $w]-[winfo reqheight $w])/2}]
}
}
wm deiconify $w
}
## Centers the canvas around points x & y
##
## Unoptimized, this looks like:
## set xtenth [expr .10 * [winfo width $w]]
## set ytenth [expr .10 * [winfo height $w]]
## set X [expr [winfo width $w] / 2]
## set Y [expr [winfo height $w] / 2]
## set x1 [expr round(($x-$X)/$xtenth)]
## set y1 [expr round(($y-$Y)/$ytenth)]
## $w xview scroll $x1 units
## $w yview scroll $y1 units
##
proc canvas_center {w x y} {
$w xview scroll [expr {round(10.0*$x/[winfo width $w]-5)}] units
$w yview scroll [expr {round(10.0*$y/[winfo height $w]-5)}] units
}
## "see" method alternative for canvas
## Aligns the named item as best it can in the middle of the screen
## Behavior depends on whether -scrollregion is set
##
## c - a canvas widget
## item - a canvas tagOrId
proc canvas_see {c item} {
set box [$c bbox $item]
if {[string match {} $box]} return
if {[string match {} [$c cget -scrollregion]]} {
## People really should set -scrollregion you know...
foreach {x y x1 y1} $box {
set x [expr {round(2.5*($x1+$x)/[winfo width $c])}]
set y [expr {round(2.5*($y1+$y)/[winfo height $c])}]
}
$c xview moveto 0
$c yview moveto 0
$c xview scroll $x units
$c yview scroll $y units
} else {
## If -scrollregion is set properly, use this
foreach {x y x1 y1} $box {top btm} [$c yview] {left right} [$c xview] \
{p q xmax ymax} [$c cget -scrollregion] {
set xpos [expr {(($x1+$x)/2.0)/$xmax - ($right-$left)/2.0}]
set ypos [expr {(($y1+$y)/2.0)/$ymax - ($btm-$top)/2.0}]
}
$c xview moveto $xpos
$c yview moveto $ypos
}
}
## Set cursor of widget $w and its descendants to $cursor
## Ignores {} cursors
proc cursor_set {w cursor} {
variable CURSOR
if {[string compare {} [set CURSOR($w) [$w cget -cursor]]]} {
$w config -cursor $cursor
} else {
unset CURSOR($w)
}
foreach child [winfo children $w] { cursor_set $child $cursor }
}
## Restore cursor based on CURSOR($w) for $w and its descendants
## $cursor is the default cursor (if none was cached)
proc cursor_restore {w {cursor {}}} {
variable CURSOR
if {[info exists CURSOR($w)]} {
$w config -cursor $CURSOR($w)
} else {
$w config -cursor $cursor
}
foreach child [winfo children $w] { cursor_restore $child $cursor }
}
# highlight_dialog --
#
# creates minimal dialog interface to highlight
#
# Arguments:
# w text widget
# str optional seed string for HIGHLIGHT(string)
# Results:
# Returns null.
#
proc highlight_dialog {w {str {}}} {
variable HIGHLIGHT
set namesp [namespace current]
set var ${namesp}::HIGHLIGHT
set base $w.__highlight
if {![winfo exists $base]} {
toplevel $base
wm withdraw $base
wm title $base "Find String"
pack [frame $base.f] -fill x -expand 1
label $base.f.l -text "Find:"
entry $base.f.e -textvariable ${var}($w,string)
pack [frame $base.opt] -fill x
checkbutton $base.opt.c -text "Case Sensitive" \
-variable ${var}($w,nocase)
checkbutton $base.opt.r -text "Use Regexp" -variable ${var}($w,regexp)
pack $base.f.l -side left
pack $base.f.e $base.opt.c $base.opt.r -side left -fill both -expand 1
pack [frame $base.sep -bd 2 -relief sunken -height 4] -fill x
pack [frame $base.btn] -fill both
button $base.btn.fnd -text "Find" -width 6
button $base.btn.clr -text "Clear" -width 6
button $base.btn.dis -text "Dismiss" -width 6
eval pack [winfo children $base.btn] -padx 4 -pady 2 \
-side left -fill both
focus $base.f.e
bind $base.f.e <Return> [list $base.btn.fnd invoke]
bind $base.f.e <Escape> [list $base.btn.dis invoke]
}
## FIX namespace
$base.btn.fnd config -command [namespace code \
"highlight [list $w] \[set ${var}($w,string)\] \
\[expr {\[set ${var}($w,nocase)\]?{}:{-nocase}}] \
\[expr {\[set ${var}($w,regexp)\]?{-regexp}:{}}] \
-tag __highlight -color [list yellow]"]
$base.btn.clr config -command \
"[list $w] tag remove __highlight 1.0 end;\
set [list ${var}($w,string)] {}"
$base.btn.dis config -command \
"[list $w] tag remove __highlight 1.0 end;\
wm withdraw [list $base]"
if {[string compare {} $str]} {
set ${var}($w,string) $str
$base.btn.fnd invoke
}
if {[string compare normal [wm state $base]]} {
wm deiconify $base
} else {
raise $base
}
$base.f.e select range 0 end
}
}; # end namespace ::Utility::Tk