15 package require Tk 8.4
16 package require msgcat
66 namespace eval ::tooltip {
67 namespace export -clear tooltip
72 if {![
info exists G]} {
83 if {[tk windowingsystem] eq "x11"} {
87 if {![
info exists labelOpts]} {
91 set labelOpts [list -highlightthickness 0 -relief solid -bd 1 \
92 -background lightyellow -fg black]
97 bind Tooltip <Enter> [
namespace code {
102 if {$G(enabled) && [info exists tooltip(%W)]} {
104 [after $G(DELAY) [namespace code [list show %W $tooltip(%W) cursor]]]
108 bind Menu <<MenuSelect>> [
namespace code { menuMotion %W }]
109 bind Tooltip <Leave> [
namespace code [list hide 1]]
110 bind Tooltip <Any-KeyPress> [
namespace code hide]
111 bind Tooltip <Any-Button> [
namespace code hide]
114 proc ::tooltip::tooltip {w args} {
119 if {[
llength $args]==0} {
set args .*}
123 if {[
llength $args]} {
124 if {![
string is integer -strict $args] || $args<50} {
125 return -code error "tooltip delay must be an\
126 integer greater than 50 (delay is in millisecs)"
128 return [
set G(DELAY) $args]
134 if {[
llength $args]} {
135 set G(fade) [
string is true -strict [
lindex $args 0]]
148 if {[
llength $args]} {
149 set i [uplevel 1 [
namespace code "register [list $w] $args"]]
152 if {![
winfo exists $b]} {
155 toplevel $b -class Tooltip
156 if {[tk windowingsystem] eq "aqua"} {
157 ::tk::unsupported::MacWindowStyle style $b help none
159 wm overrideredirect $b 1
161 catch {
wm attributes $b -topmost 1}
163 catch {
wm attributes $b -alpha 0.99}
164 wm positionfrom $b program
166 eval [
linsert $labelOpts 0 label $b.label]
167 pack $b.label -ipadx 1
169 if {[
info exists tooltip($i)]} {
return $tooltip($i)}
174 proc ::tooltip::register {w args} {
176 set key [
lindex $args 0]
177 while {[
string match -* $key]} {
180 if {[
catch {$w entrycget 1 -label}]} {
181 return -code error "widget \"$w\" does not seem to be a\
182 menu, which is required for the -index switch"
184 set index [
lindex $args 1]
185 set args [
lreplace $args 0 1]
188 if {[
winfo class $w] eq "Listbox"} {
189 set items [
lindex $args 1]
191 set namedItem [
lindex $args 1]
192 if {[
catch {$w find withtag $namedItem} items]} {
193 return -code error "widget \"$w\" is not a canvas, or\
194 item \"$namedItem\" does not exist in the canvas"
197 set args [
lreplace $args 0 1]
200 set tag [
lindex $args 1]
201 set r [
catch {lsearch -exact [$w tag names] $tag} ndx]
202 if {$r || $ndx == -1} {
203 return -code error "widget \"$w\" is not a text widget or\
204 \"$tag\" is not a text tag"
206 set args [
lreplace $args 0 1]
212 set key [
lindex $args 0]
214 if {[
llength $args] != 1} {
215 return -code error "wrong # args: should be \"tooltip widget\
216 ?-index index? ?-items item? ?-tag tag? message\""
221 if {![
winfo exists $w]} {
222 return -code error "bad window path name \"$w\""
224 if {[
info exists index]} {
225 set tooltip($w,$index) $key
227 }
elseif {[
info exists items]} {
228 foreach item $items {
229 set tooltip($w,$item) $key
230 if {[
winfo class $w] eq "Listbox"} {
238 return $w,[
lindex $items 0]
239 }
elseif {[
info exists tag]} {
240 set tooltip($w,t_$tag) $key
246 set tags [
bindtags $w]
247 if {[lsearch -exact $tags "Tooltip"] == -1} {
248 bindtags $w [
linsert $tags end "Tooltip"]
255 proc ::tooltip::clear {{pattern .*}} {
258 set ptrw [
winfo containing [
winfo pointerx .] [
winfo pointery .]]
259 foreach w [
array names tooltip $pattern] {
261 if {[
winfo exists $w]} {
262 set tags [
bindtags $w]
263 if {[
set i [lsearch -exact $tags "Tooltip"]] != -1} {
264 bindtags $w [
lreplace $tags $i $i]
270 if {$ptrw eq $w} {
hide}
275 proc ::tooltip::show {w msg {i {}}} {
276 if {![
winfo exists $w]} {
return}
280 if {([
winfo class $w] ne "Menu")
281 && ![
string match $w* [
eval [list winfo containing] \
282 [
winfo pointerxy $w]]]} {
288 after cancel $G(FADEID)
292 $b.label configure -text [::msgcat::mc $msg] -justify left
294 set screenw [
winfo screenwidth $w]
295 set screenh [
winfo screenheight $w]
296 set reqw [
winfo reqwidth $b]
297 set reqh [
winfo reqheight $b]
300 if {$i eq "cursor"} {
301 set y [
expr {[winfo pointery $w]+20}]
302 if {($y < $screenh) && ($y+$reqh) > $screenh} {
303 set y [
expr {[winfo pointery $w]-$reqh-5}]
305 }
elseif {$i ne ""} {
306 set y [
expr {[winfo rooty $w]+[winfo vrooty $w]+[$w yposition $i]+25}]
307 if {($y < $screenh) && ($y+$reqh) > $screenh} {
309 set y [
expr {[winfo rooty $w]+[$w yposition $i]-$reqh-5}]
312 set y [
expr {[winfo rooty $w]+[winfo vrooty $w]+[winfo height $w]+5}]
313 if {($y < $screenh) && ($y+$reqh) > $screenh} {
315 set y [
expr {[winfo rooty $w]-$reqh-5}]
318 if {$i eq "cursor"} {
319 set x [
winfo pointerx $w]
321 set x [
expr {[winfo rootx $w]+[winfo vrootx $w]+
322 ([winfo width $w]-$reqw)/2}]
325 if {$x<0 && ($x+$reqw)>0} {
327 }
elseif {($x < $screenw) && ($x+$reqw) > $screenw} {
328 set x [
expr {$screenw-$reqw}]
330 if {[tk windowingsystem] eq "aqua"} {
334 catch {
wm attributes $b -alpha 0.99}
335 wm geometry $b +$x+$y
338 if {[tk windowingsystem] eq "aqua" && $focus ne ""} {
340 after idle [list focus -force $focus]
344 proc ::tooltip::menuMotion {w} {
351 set m [
string map {"#" "."} [
winfo name $w]]
352 set cur [$w index active]
356 if {$cur == $G(LAST)}
return 359 after cancel $G(AFTERID)
360 catch {
wm withdraw $G(TOPLEVEL)}
361 if {[
info exists tooltip($m,$cur)] || \
362 (![
catch {$w entrycget $cur -label} cur] && \
363 [
info exists tooltip($m,$cur)])} {
364 set G(AFTERID) [after $G(DELAY) \
365 [
namespace code [list show $w $tooltip($m,$cur) cursor]]]
370 proc ::tooltip::hide {{fadeOk 0}} {
373 after cancel $G(AFTERID)
374 after cancel $G(FADEID)
375 if {$fadeOk && $G(fade)} {
376 fade $G(TOPLEVEL) $G(FADESTEP)
378 catch {
wm withdraw $G(TOPLEVEL)}
382 proc ::tooltip::fade {w step} {
383 if {[
catch {
wm attributes $w -alpha} alpha] || $alpha <= 0.0} {
384 catch {
wm withdraw $w}
385 catch {
wm attributes $w -alpha 0.99}
388 wm attributes $w -alpha [
expr {$alpha-$step}]
389 set G(FADEID) [after 50 [
namespace code [list fade $w $step]]]
393 proc ::tooltip::wname {{w {}}} {
395 if {[
llength [
info level 0]] > 1} {
397 if {$w ne $G(TOPLEVEL)} {
406 proc ::tooltip::listitemTip {w x y} {
411 set item [$w index @$x,$y]
412 if {$G(enabled) && [
info exists tooltip($w,$item)]} {
413 set G(AFTERID) [after $G(DELAY) \
414 [
namespace code [list show $w $tooltip($w,$item) cursor]]]
419 proc ::tooltip::listitemMotion {w x y} {
423 set item [$w index @$x,$y]
424 if {$item ne $G(LAST)} {
426 after cancel $G(AFTERID)
427 catch {
wm withdraw $G(TOPLEVEL)}
428 if {[
info exists tooltip($w,$item)]} {
429 set G(AFTERID) [after $G(DELAY) \
430 [
namespace code [list show $w $tooltip($w,$item) cursor]]]
437 proc ::tooltip::enableListbox {w args} {
438 if {[
string match *listitemTip* [
bind $w <Enter>]]} {
return}
439 bind $w <Enter> +[
namespace code [list listitemTip %W %x %y]]
440 bind $w <Motion> +[
namespace code [list listitemMotion %W %x %y]]
441 bind $w <Leave> +[
namespace code [list hide 1]]
442 bind $w <Any-KeyPress> +[
namespace code hide]
443 bind $w <Any-Button> +[
namespace code hide]
446 proc ::tooltip::itemTip {w args} {
451 set item [$w find withtag current]
452 if {$G(enabled) && [
info exists tooltip($w,$item)]} {
453 set G(AFTERID) [after $G(DELAY) \
454 [
namespace code [list show $w $tooltip($w,$item) cursor]]]
458 proc ::tooltip::enableCanvas {w args} {
459 if {[
string match *itemTip* [$w bind all <Enter>]]} {
return}
460 $w bind all <Enter> +[
namespace code [list itemTip $w]]
461 $w bind all <Leave> +[
namespace code [list hide 1]]
462 $w bind all <Any-KeyPress> +[
namespace code hide]
463 $w bind all <Any-Button> +[
namespace code hide]
466 proc ::tooltip::tagTip {w tag} {
470 if {$G(enabled) && [
info exists tooltip($w,t_$tag)]} {
471 if {[
info exists G(AFTERID)]} { after cancel $G(AFTERID)}
472 set G(AFTERID) [after $G(DELAY) \
473 [
namespace code [list show $w $tooltip($w,t_$tag) cursor]]]
477 proc ::tooltip::enableTag {w tag} {
478 if {[
string match *tagTip* [$w tag bind $tag]]} {
return}
479 $w tag bind $tag <Enter> +[
namespace code [list tagTip $w $tag]]
480 $w tag bind $tag <Leave> +[
namespace code [list hide 1]]
481 $w tag bind $tag <Any-KeyPress> +[
namespace code hide]
482 $w tag bind $tag <Any-Button> +[
namespace code hide]
485 package provide tooltip 1.4.6