1 # tix.tcl --
2 #
3 # Popup tips for Tk
4
5 # ---------------------------------------------------------------------------
6 # This software is in the public domain, furnished "as is", without technical
7 # support, and with no warranty, express or implied, as to its usefulness for
8 # any purpose.
9 #
10 # tips.tcl
11 # Popup tips for Tk
12 # ---------------------------------------------------------------------------
13
14 # -- module -----------------------------------------------------------------
15 #
16 # This package provides popup tips for widgets in Tcl/Tk. Call "add_tip"
17 # to add a tip to a widget, and "remove_tip" to remove it.
18 #
19 # ---------------------------------------------------------------------------
20
21 package provide "tips" 1.0
22
23 #
24 # Programmatic defaults: feel free to adjust the first three.
25 #
26 array set tip_priv {
27 window_delay 500
28 y_offset 5
29 x_offset 20
30 currently_tipping ""
31 tips_enabled 1
32 tips_initialized 0
33 }
34
35 # -- proc -------------------------------------------------------------------
36 # add_tip
37 #
38 # Add a tip message to the given widget. When the pointer enters the
39 # widget, it'll wait a bit, then if it's still there, it'll map the
40 # tip window. As soon as the pointer leaves, then it unmaps it.
41 # ---------------------------------------------------------------------------
42 proc add_tip {window msg} {
43 global tip_priv
44
45 if {! $tip_priv(tips_initialized)} {tip_init_tips}
46
47 # Save the message text for later use.
48 set tip_priv($window) $msg
49
50 # Add the tip bindings to the window ... now, it might already have
51 # them if we got called to change the text, so check first.
52 set tags [bindtags $window]
53 if {[lsearch -exact $tags TipBindings] == -1} {
54 # They're not in there, add 'em.
55 bindtags $window [concat TipBindings [bindtags $window]]
56 }
57 }
58
59 # -- proc -------------------------------------------------------------------
60 # remove_tip
61 #
62 # Remove the popup tip for this window.
63 # ---------------------------------------------------------------------------
64 proc remove_tip {window} {
65 global tip_priv
66
67 # Do we have saved text for this window? If so, then we have to get rid of it
68 # and the window's class binding, too.
69 if [info exists tip_priv($window)] {
70 # Okay, nuke the text.
71 unset tip_priv($window)
72
73 # Now, get the tags and see if the TipBindings is among them.
74 set tags [bindtags $window]
75 if {[set index [lsearch -exact $tags TipBindings]] >= 0} {
76 # Yep, it's there. Set the new bindings without TipBindings present.
77 bindtags $window [lreplace $tags $index $index]
78 }
79
80 # Also, if the tip window is visible for this widget, nuke it.
81 if {$tip_priv(currently_tipping) == $window} {
82 destroy .tip
83 set tip_priv(currently_tipping) ""
84 }
85 } else {
86 # It's not set? Well, I never.
87 error "No popup tip set for $window"
88 }
89 }
90
91 # -- proc -------------------------------------------------------------------
92 # enable_tips
93 #
94 # With boolean true, enable all popup tips. False, disable all of them.
95 # ---------------------------------------------------------------------------
96 proc enable_tips {bool} {
97 global tip_priv
98
99 set tip_priv(tips_enabled) $bool
100 if {! $bool && $tip_priv(currently_tipping) != ""} {
101 destroy $tip_priv(currently_tipping)
102 set tip_priv(currently_tipping) ""
103 }
104 }
105
106 # -- proc -------------------------------------------------------------------
107 # tip_make_window
108 #
109 # Make and map the tip window for the given widget.
110 # ---------------------------------------------------------------------------
111 proc tip_make_window {window} {
112 global tip_priv
113
114 # Note that we're mapping the tip window.
115 set tip_priv(currently_tipping) $window
116
117 # Get rid of it if it already exists
118 catch {destroy .tip}
119
120 # Figure out the X and Y coord of the tip window. It should be below the widget it's tipping,
121 # and slightly to the right of its left edge, too.
122 set y [expr [winfo rooty $window] + [winfo height $window] + $tip_priv(y_offset)]
123 set x [expr [winfo rootx $window] + $tip_priv(x_offset)]
124
125 # Create it at the correct coords, and prevent the window manager from slapping a border around it.
126 toplevel .tip -class Tip
127 wm overrideredirect .tip yes
128 wm geometry .tip +$x+$y
129 # Insert the message and we're done.
130 pack [message .tip.message -text $tip_priv($window) -bg beige]
131 }
132
133 # -- proc -------------------------------------------------------------------
134 # tip_cancel_tip
135 #
136 # Cancel any currently displayed tip by unmapping the window (if it's mapped)
137 # and by canceling the timer to display a window.
138 # ---------------------------------------------------------------------------
139 proc tip_cancel_tip {} {
140 global tip_priv
141
142 if {! $tip_priv(tips_enabled)} return
143
144 if {$tip_priv(currently_tipping) != ""} {
145 catch {destroy .tip}
146 set tip_priv(currently_tipping) ""
147 }
148 catch {after cancel $tip_priv(after_id)}
149 }
150
151 # -- proc -------------------------------------------------------------------
152 # tip_init_tips
153 #
154 # Initialize the tips. Currently, this just means adding X resources
155 # and setting up bindings. Override these in your own X resources, if
156 # you must. (Note that if you use Vue, you likely have things like
157 # "*background", which will override these settings no matter what.
158 # You may want to add these settings in that case.)
159 # ---------------------------------------------------------------------------
160 proc tip_init_tips {} {
161 global tip_priv
162
163 # X defaults for the popup.
164 option add "*tip.message.background" "LemonChiffon" widgetDefault
165 option add "*tip.message.foreground" "Black" widgetDefault
166 option add "*tip.message.relief" "raised" widgetDefault
167 option add "*tip.message.borderWidth" "2" widgetDefault
168 option add "*tip.message.justify" "left" widgetDefault
169 option add "*tip.message.aspect" "350" widgetDefault
170 option add "*tip.message.font" "-*-helvetica-medium-r-normal-*-*-120-*-*-*-*-*-*" widgetDefault
171
172 # Bindings for the TipBindings tag.
173 bind TipBindings <Enter> {
174 global tip_priv
175
176 if {! $tip_priv(tips_enabled)} continue
177
178 set tip_priv(currently_tipping) ""
179 set tip_priv(after_id) [after $tip_priv(window_delay) tip_make_window %W]
180 }
181 bind TipBindings <Leave> {
182 tip_cancel_tip
183 }
184 bind TipBindings <Button-1> {
185 tip_cancel_tip
186 }
187 bind TipBindings <space> {
188 tip_cancel_tip
189 }
190
191 set tip_priv(tips_initialized) 1
192 }
193
194
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.