1 # General purpose code for being a tray applet
3 proc manyset {list args} {
4 foreach val $list var $args {
12 package require tktray
14 #----- general machinery -----
18 # tk::tktray widget is called .i
23 # applet::setup-tooltip ON-VISIBLE ON-INVISIBLE
24 # to make applet have a tooltip.
26 # ON-VISIBLE and ON-INVISIBLE will be globally eval'd
27 # when the tooltip becomes visible and invisible.
30 # applet::tooltip-set TEXT-MAYBE-MULTILINE
36 # applet::setimage IMAGE
39 # Alternatively, instead of icon, it may arrange to run (repeatedly
40 # if necessary) a subprocess.
42 # Caller that needs access to inner window should call
43 # applet::setup-subwindow WIDTH ON-DESTROYING ON-READY
44 # Then the main code will call ON-DESTROYING just before
45 # destroying the inner window and recreating it, and ON-READY
46 # just after. Afterwards, theh inner window is called
49 # proc innerwindow {} { ... }
53 # .i.i.b frame to contain container
54 # .i.i.b.c actual container
58 # Caller may bind .i.i <ButtonPress-$b>
60 # Alternatively caller may call applet::setup-button-menu $b
61 # which will generate a menu .m$b which the user can configure
62 # and which will automatically be posted and unposted etc.
63 # In this case the caller should arrange that all of their
64 # menus, when an item is selected, call
69 tktray::icon .i -class example
70 .i configure -docked 1
73 namespace eval applet {
76 # used by both menus and tooltips
81 proc setup-button-menu {b} {
82 bind .i.i <ButtonPress> { applet::menubuttonpressed %b %X %Y }
86 proc menubuttonpressed {b x y} {
90 puts "unpost $posted toggle"
93 } elseif {[winfo exists .m$b]} {
96 puts "unpost $posted other"
109 #----- tooltips -----
111 variable tooltip_on_vis {}
112 variable tooltip_on_invis {}
114 proc tooltip-starttimer {state x y} {
115 variable tooltip_after
117 variable tooltip_inwindow
118 if {$state || $posted || !$tooltip_inwindow} { tooltip-cancel; return }
119 catch { after cancel $tooltip_after }
120 set tooltip_after [after 500 applet::tooltip-show $x $y]
123 proc tooltip-cancel {} {
124 variable tooltip_after
125 variable tooltip_on_invis
126 catch { after cancel $tooltip_after }
127 catch { unset $tooltip_after }
129 uplevel #0 $tooltip_on_invis
132 set tooltip_inwindow 0
134 proc tooltip-enter {state x y} {
135 variable tooltip_inwindow
136 set tooltip_inwindow 1
137 tooltip-starttimer $state $x $y
140 proc tooltip-leave {} {
141 variable tooltip_inwindow
142 set tooltip_inwindow 0
146 proc setup-tooltip {on_vis on_invis} {
147 foreach v {vis invis} {
148 variable tooltip_on_$v [set on_$v]
150 bind .i <Enter> { applet::tooltip-enter %s %X %Y }
151 bind .i <Leave> { applet::tooltip-leave }
152 bind .i <ButtonRelease> {
153 applet::tooltip-cancel
154 applet::tooltip-starttimer %s %X %Y
156 bind .i <Motion> { applet::tooltip-starttimer %s %X %Y }
157 toplevel .tt -background black
159 wm overrideredirect .tt 1
160 label .tt.t -justify left -background {#EEE1B3}
161 pack .tt.t -padx 1 -pady 1
165 proc tooltip-set {s} {
166 .tt.t configure -text $s
169 proc tooltip-show {x y} {
170 variable tooltip_on_vis
173 wm geometry .tt +$x+$y
175 uplevel #0 $tooltip_on_vis
178 #----- simple images -----
180 proc setimage {image} {
181 .i configure -image $image
184 #----- subwindow -----
186 variable subwindow_on_destroying
187 variable subwindow_on_ready
189 proc innerwindow-resetup-required {why} {
190 variable innerwindow_after
192 if {[info exists innerwindow_after]} return
193 set innerwindow_after [after idle applet::innerwindow-resetup]
196 proc innerwindow-resetup {} {
197 variable innerwindow_after
198 variable subwindow_on_destroying
199 variable subwindow_on_ready
200 unset innerwindow_after
204 uplevel #0 $subwindow_on_destroying
206 catch { destroy .i.i.c }
207 if {![winfo exists .i.i]} return
208 destroy [frame .i.i.make-exist]
209 catch { destroy .i.i.b.c }
210 catch { destroy .i.i.b }
212 pack .i.i.b -fill both -side left -expand 1
213 frame .i.i.b.c -container 1 -background orange
214 pack .i.i.b.c -fill both -side left -expand 1
216 global inner_lastw inner_lasth
217 #set w [winfo width .i.i]
218 # set w [winfo width .i.i]
219 # set h [winfo height .i.i]
221 # if {$w != $inner_lastw || $h != $inner_lasth} {
224 # innerwindow-ph-dummy configure -width $w -height 2
226 uplevel #0 $subwindow_on_ready
230 proc setup-subwindow {w on_destroying on_ready} {
231 foreach v {destroying ready} {
232 variable subwindow_on_$v [set on_$v]
235 global inner_lastw inner_lasth
239 image create photo applet::innerwindow-ph-dummy -width $w -height 2
240 .i configure -image applet::innerwindow-ph-dummy
242 destroy [frame .i.make-exist]
243 destroy [frame .i.i.make-exist]
244 bind .i <<IconConfigure>> {
245 applet::innerwindow-resetup-required IconConfigure