123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
- #
- # $Id: Balloon.tcl,v 1.7 2008/02/27 22:17:28 hobbs Exp $
- #
- # Balloon.tcl --
- #
- # The help widget. It provides both "balloon" type of help
- # message and "status bar" type of help message. You can use
- # this widget to indicate the function of the widgets inside
- # your application.
- #
- # Copyright (c) 1993-1999 Ioi Kim Lam.
- # Copyright (c) 2000-2001 Tix Project Group.
- # Copyright (c) 2004 ActiveState
- #
- # See the file "license.terms" for information on usage and redistribution
- # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- #
- tixWidgetClass tixBalloon {
- -classname TixBalloon
- -superclass tixShell
- -method {
- bind post unbind
- }
- -flag {
- -installcolormap -initwait -state -statusbar -cursor
- }
- -configspec {
- {-installcolormap installColormap InstallColormap false}
- {-initwait initWait InitWait 1000}
- {-state state State both}
- {-statusbar statusBar StatusBar ""}
- {-cursor cursor Cursor {}}
- }
- -default {
- {*background #ffff60}
- {*foreground black}
- {*borderWidth 0}
- {.borderWidth 1}
- {.background black}
- {*Label.anchor w}
- {*Label.justify left}
- }
- }
- # static seem to be -installcolormap -initwait -statusbar -cursor
- # Class Record
- #
- global tixBalloon
- set tixBalloon(bals) ""
- proc tixBalloon:InitWidgetRec {w} {
- upvar #0 $w data
- global tixBalloon
- tixChainMethod $w InitWidgetRec
- set data(isActive) 0
- set data(client) ""
- lappend tixBalloon(bals) $w
- }
- proc tixBalloon:ConstructWidget {w} {
- upvar #0 $w data
- tixChainMethod $w ConstructWidget
- if {[tk windowingsystem] eq "aqua"} {
- ::tk::unsupported::MacWindowStyle style $w help none
- } else {
- wm overrideredirect $w 1
- }
- catch {wm attributes $w -topmost 1}
- wm positionfrom $w program
- wm withdraw $w
- # Frame 1 : arrow
- frame $w.f1 -bd 0
- set data(w:label) [label $w.f1.lab -bd 0 -relief flat \
- -bitmap [tix getbitmap balarrow]]
- pack $data(w:label) -side left -padx 1 -pady 1
-
- # Frame 2 : Message
- frame $w.f2 -bd 0
- set data(w:message) [label $w.f2.message -padx 0 -pady 0 -bd 0]
- pack $data(w:message) -side left -expand yes -fill both -padx 10 -pady 1
- # Pack all
- pack $w.f1 -fill both
- pack $w.f2 -fill both
- # This is an event tag used by the clients
- #
- bind TixBal$w <Destroy> [list tixBalloon:ClientDestroy $w %W]
- }
- proc tixBalloon:Destructor {w} {
- global tixBalloon
- set bals ""
- foreach b $tixBalloon(bals) {
- if {$w != $b} {
- lappend bals $b
- }
- }
- set tixBalloon(bals) $bals
- tixChainMethod $w Destructor
- }
- #----------------------------------------------------------------------
- # Config:
- #----------------------------------------------------------------------
- proc tixBalloon:config-state {w value} {
- upvar #0 $w data
- set re {^(none|balloon|status|both)$}
- if {![regexp -- $re $value]} {
- error "invalid value $value, must be none, balloon, status, or both"
- }
- }
- #----------------------------------------------------------------------
- # "RAW" event bindings:
- #----------------------------------------------------------------------
- bind all <B1-Motion> "+tixBalloon_XXMotion %X %Y 1"
- bind all <B2-Motion> "+tixBalloon_XXMotion %X %Y 2"
- bind all <B3-Motion> "+tixBalloon_XXMotion %X %Y 3"
- bind all <B4-Motion> "+tixBalloon_XXMotion %X %Y 4"
- bind all <B5-Motion> "+tixBalloon_XXMotion %X %Y 5"
- bind all <Any-Motion> "+tixBalloon_XXMotion %X %Y 0"
- # Should %b be 0? %b is illegal
- bind all <Leave> "+tixBalloon_XXMotion %X %Y 0"
- bind all <Button> "+tixBalloon_XXButton %X %Y %b"
- bind all <ButtonRelease> "+tixBalloon_XXButtonUp %X %Y %b"
- proc tixBalloon_XXMotion {rootX rootY b} {
- global tixBalloon
- foreach w $tixBalloon(bals) {
- tixBalloon:XXMotion $w $rootX $rootY $b
- }
- }
- proc tixBalloon_XXButton {rootX rootY b} {
- global tixBalloon
- foreach w $tixBalloon(bals) {
- tixBalloon:XXButton $w $rootX $rootY $b
- }
- }
- proc tixBalloon_XXButtonUp {rootX rootY b} {
- global tixBalloon
- foreach w $tixBalloon(bals) {
- tixBalloon:XXButtonUp $w $rootX $rootY $b
- }
- }
- # return true if d is a descendant of w
- #
- proc tixIsDescendant {w d} {
- return [expr {$w eq "." || [string match $w.* $d]}]
- }
- # All the button events are fine if the ballooned widget is
- # a descendant of the grabbing widget
- #
- proc tixBalloon:GrabBad {w cw} {
- global tixBalloon
- set g [grab current $w]
- if {$g == ""} {
- return 0
- }
- if {[info exists tixBalloon(g_ignore,$g)]} {
- return 1
- }
- if {[info exists tixBalloon(g_ignore,[winfo class $g])]} {
- return 1
- }
- if {$g == $cw || [tixIsDescendant $g $cw]} {
- return 0
- }
- return 1
- }
- proc tixBalloon:XXMotion {w rootX rootY b} {
- upvar #0 $w data
- if {![info exists data(-state)]} {
- # puts "tixBalloon:XXMotion called without a state\n$w"
- set data(state) none
- return
- }
- if {$data(-state) eq "none"} {
- return
- }
- if {$b == 0} {
- if {[info exists data(b:1)]} {unset data(b:1)}
- if {[info exists data(b:2)]} {unset data(b:2)}
- if {[info exists data(b:3)]} {unset data(b:3)}
- if {[info exists data(b:4)]} {unset data(b:4)}
- if {[info exists data(b:5)]} {unset data(b:5)}
- }
- if {[llength [array names data b:*]]} {
- # Some buttons are down. Do nothing
- #
- return
- }
- set cw [winfo containing -displayof $w $rootX $rootY]
- if {[tixBalloon:GrabBad $w $cw]} {
- return
- }
- # Find the a client window that matches
- #
- if {$w eq $cw || [string match $w.* $cw]} {
- # Cursor moved over the balloon -- Ignore
- return
- }
- while {$cw != ""} {
- if {[info exists data(m:$cw)]} {
- set client $cw
- break
- } else {
- set cw [winfo parent $cw]
- }
- }
- if {![info exists client]} {
- # The cursor is at a position covered by a non-client
- # Popdown the balloon if it is up
- if {$data(isActive)} {
- tixBalloon:Deactivate $w
- }
- set data(client) ""
- if {[info exists data(cancel)]} {
- unset data(cancel)
- }
- return
- }
- if {$data(client) ne $client} {
- if {$data(isActive)} {
- tixBalloon:Deactivate $w
- }
- set data(client) $client
- after $data(-initwait) tixBalloon:SwitchToClient $w $client
- }
- }
- proc tixBalloon:XXButton {w rootX rootY b} {
- upvar #0 $w data
- tixBalloon:XXMotion $w $rootX $rootY $b
- set data(b:$b) 1
- if {$data(isActive)} {
- tixBalloon:Deactivate $w
- } else {
- set data(cancel) 1
- }
- }
- proc tixBalloon:XXButtonUp {w rootX rootY b} {
- upvar #0 $w data
- tixBalloon:XXMotion $w $rootX $rootY $b
- if {[info exists data(b:$b)]} {
- unset data(b:$b)
- }
- }
- #----------------------------------------------------------------------
- # "COOKED" event bindings:
- #----------------------------------------------------------------------
- # switch the balloon to a new client
- #
- proc tixBalloon:SwitchToClient {w client} {
- upvar #0 $w data
- if {![winfo exists $w]} {
- return
- }
- if {![winfo exists $client]} {
- return
- }
- if {$client ne $data(client)} {
- return
- }
- if {[info exists data(cancel)]} {
- unset data(cancel)
- return
- }
- if {[tixBalloon:GrabBad $w $w]} {
- return
- }
- tixBalloon:Activate $w
- }
- proc tixBalloon:ClientDestroy {w client} {
- if {![winfo exists $w]} {
- return
- }
- upvar #0 $w data
- if {$data(client) eq $client} {
- tixBalloon:Deactivate $w
- set data(client) ""
- }
- # Maybe thses have already been unset by the Destroy method
- #
- if {[info exists data(m:$client)]} {unset data(m:$client)}
- if {[info exists data(s:$client)]} {unset data(s:$client)}
- }
- #----------------------------------------------------------------------
- # Popping up balloon:
- #----------------------------------------------------------------------
- proc tixBalloon:Activate {w} {
- upvar #0 $w data
- if {[tixBalloon:GrabBad $w $w]} {
- return
- }
- if {[winfo containing -displayof $w \
- [winfo pointerx $w] [winfo pointery $w]] == ""} {
- return
- }
- if {![info exists data(-state)]} {
- # puts "tixBalloon:Activate called without a state\n$w"
- set data(state) none
- return
- }
- if {$data(-state) eq "none"} {
- return
- }
- switch -exact -- $data(-state) {
- "both" {
- tixBalloon:PopUp $w
- tixBalloon:SetStatus $w
- }
- "balloon" {
- tixBalloon:PopUp $w
- }
- "status" {
- tixBalloon:SetStatus $w
- }
- }
- set data(isActive) 1
- after 200 tixBalloon:Verify $w
- }
- # %% Perhaps this is no more needed
- #
- proc tixBalloon:Verify {w} {
- upvar #0 $w data
- if {![winfo exists $w]} {
- return
- }
- if {!$data(isActive)} {
- return
- }
- if {[tixBalloon:GrabBad $w $w]} {
- tixBalloon:Deactivate $w
- return
- }
- if {[winfo containing -displayof $w \
- [winfo pointerx $w] [winfo pointery $w]] == ""} {
- tixBalloon:Deactivate $w
- return
- }
- after 200 tixBalloon:Verify $w
- }
- proc tixBalloon:Deactivate {w} {
- upvar #0 $w data
- tixBalloon:PopDown $w
- tixBalloon:ClearStatus $w
- set data(isActive) 0
- if {[info exists data(cancel)]} {
- unset data(cancel)
- }
- }
- proc tixBalloon:PopUp {w} {
- upvar #0 $w data
- if {[string is true -strict $data(-installcolormap)]} {
- wm colormapwindows [winfo toplevel $data(client)] $w
- }
- # trick: the following lines allow the balloon window to
- # acquire a stable width and height when it is finally
- # put on the visible screen
- #
- set client $data(client)
- if {$data(m:$client) == ""} {return ""}
- $data(w:message) config -text $data(m:$client)
- wm geometry $w +10000+10000
- wm deiconify $w
- raise $w
- update
- # The windows may become destroyed as a result of the "update" command
- #
- if {![winfo exists $w]} {
- return
- }
- if {![winfo exists $client]} {
- return
- }
- # Put it on the visible screen
- #
- set x [expr {[winfo rootx $client]+[winfo width $client]/2}]
- set y [expr {int([winfo rooty $client]+[winfo height $client]/1.3)}]
- set width [winfo reqwidth $w]
- set height [winfo reqheight $w]
- set scrwidth [winfo vrootwidth $w]
- set scrheight [winfo vrootheight $w]
- # If the balloon is too far right, pull it back to the left
- #
- if {($x + $width) > $scrwidth} {
- set x [expr {$scrwidth - $width}]
- }
- # If the balloon is too far left, pull it back to the right
- #
- if {$x < 0} {
- set x 0
- }
- # If the listbox is below bottom of screen, put it upwards
- #
- if {($y + $height) > $scrheight} {
- set y [expr {$scrheight-$height}]
- }
- if {$y < 0} {
- set y 0
- }
- wm geometry $w +$x+$y
- after idle raise $w
- }
- proc tixBalloon:PopDown {w} {
- upvar #0 $w data
- # Close the balloon
- #
- wm withdraw $w
- # We don't set the data(client) to be zero, so that the balloon
- # will re-appear only if you move out then in the client window
- # set data(client) ""
- }
- proc tixBalloon:SetStatus {w} {
- upvar #0 $w data
- if {![winfo exists $data(-statusbar)]
- || ![info exists data(s:$data(client))]} {
- return
- }
- set vv [$data(-statusbar) cget -textvariable]
- if {$vv == ""} {
- $data(-statusbar) config -text $data(s:$data(client))
- } else {
- uplevel #0 set $vv [list $data(s:$data(client))]
- }
- }
- proc tixBalloon:ClearStatus {w} {
- upvar #0 $w data
- if {![winfo exists $data(-statusbar)]} {
- return
- }
- # Clear the StatusBar widget
- #
- set vv [$data(-statusbar) cget -textvariable]
- if {$vv == ""} {
- $data(-statusbar) config -text ""
- } else {
- uplevel #0 set $vv [list ""]
- }
- }
- #----------------------------------------------------------------------
- # PublicMethods:
- #----------------------------------------------------------------------
- # %% if balloon is already popped-up for this client, change mesage
- #
- proc tixBalloon:bind {w client args} {
- upvar #0 $w data
- set alreadyBound [info exists data(m:$client)]
- set opt(-balloonmsg) ""
- set opt(-statusmsg) ""
- set opt(-msg) ""
- tixHandleOptions opt {-balloonmsg -msg -statusmsg} $args
- if {$opt(-balloonmsg) != ""} {
- set data(m:$client) $opt(-balloonmsg)
- } else {
- set data(m:$client) $opt(-msg)
- }
- if {$opt(-statusmsg) != ""} {
- set data(s:$client) $opt(-statusmsg)
- } else {
- set data(s:$client) $opt(-msg)
- }
- tixAppendBindTag $client TixBal$w
- }
- proc tixBalloon:post {w client} {
- upvar #0 $w data
- if {![info exists data(m:$client)] || $data(m:$client) == ""} {
- return
- }
- tixBalloon:Enter $w $client
- incr data(fakeEnter)
- }
- proc tixBalloon:unbind {w client} {
- upvar #0 $w data
- if {[info exists data(m:$client)]} {
- if {[info exists data(m:$client)]} {unset data(m:$client)}
- if {[info exists data(s:$client)]} {unset data(s:$client)}
- if {[winfo exists $client]} {
- catch {tixDeleteBindTag $client TixBal$w}
- }
- }
- }
- #----------------------------------------------------------------------
- #
- # Utility function
- #
- #----------------------------------------------------------------------
- #
- # $w can be a widget name or a classs name
- proc tixBalIgnoreWhenGrabbed {wc} {
- global tixBalloon
- set tixBalloon(g_ignore,$wc) ""
- }
- tixBalIgnoreWhenGrabbed TixComboBox
- tixBalIgnoreWhenGrabbed Menu
- tixBalIgnoreWhenGrabbed Menubutton
|