+# General purpose code for being a tray applet
+
+proc manyset {list args} {
+ foreach val $list var $args {
+ upvar 1 $var my
+ set my $val
+ }
+}
+
+
+package require Tclx
+package require tktray
#----- general machinery -----
#
# tk::tktray widget is called .i
#
-# Inner window:
+# Tooltip:
+#
+# Caller may call
+# applet::setup-tooltip ON-VISIBLE ON-INVISIBLE
+# to make applet have a tooltip.
+#
+# ON-VISIBLE and ON-INVISIBLE will be globally eval'd
+# when the tooltip becomes visible and invisible.
+#
+# Caller should call
+# applet::tooltip-set TEXT-MAYBE-MULTILINE
+# whenever they like.
+#
+# Icon:
+#
+# Caller should call:
+# applet::setimage IMAGE
+# as necessary.
+#
+# Inner window subprocess:
+#
# Caller that needs access to inner window should define
# proc innerwindow {} { ... }
# and run
# .i.i.b.c actual container
#
# Button presses
-# Caller should provide
-# proc pressed {b x y} { ... }
-# which should examine b and do something appropriate.
-#
+#
+# Caller may bind .i.i <ButtonPress-$b>
+#
+# Alternatively caller may call applet::setup-button-menu $b
+# which will generate a menu .m$b which the user can configure
+# and which will automatically be posted and unposted etc.
+# In this case the caller should arrange that all of their
+# menus, when an item is selected, call
+# applet::msel
+wm withdraw .
+tktray::icon .i -class example
+.i configure -docked 1
-package require tktray
-#load /home/ian/things/Systray/tktray-1.3.8/libtktray1.3.8.so
+namespace eval applet {
-wm withdraw .
-tktray::icon .i -class example
-.i configure -docked 1
+# used by both menus and tooltips
+variable posted 0
-set posted 0
+#----- menus -----
-foreach b {1 3} {
+proc setup-button-menu {b} {
+ bind .i.i <ButtonPress> { applet::menubuttonpressed %b %X %Y }
menu .m$b -tearoff 0
}
proc menubuttonpressed {b x y} {
- global posted
- tooltip_cancel
+ variable posted
+ tooltip-cancel
if {$posted == $b} {
puts "unpost $posted toggle"
.m$posted unpost
}
proc msel {} {
- global posted
+ variable posted
set posted 0
}
-proc innerwindow-event {why} {
- global innerwindow_after
+#----- tooltips -----
+
+variable tooltip_on_vis {}
+variable tooltip_on_invis {}
+
+proc tooltip-starttimer {state x y} {
+ variable tooltip_after
+ variable posted
+ variable tooltip_inwindow
+ if {$state || $posted || !$tooltip_inwindow} { tooltip-cancel; return }
+ catch { after cancel $tooltip_after }
+ set tooltip_after [after 500 applet::tooltip-show $x $y]
+}
+
+proc tooltip-cancel {} {
+ variable tooltip_after
+ variable tooltip_on_invis
+ catch { after cancel $tooltip_after }
+ catch { unset $tooltip_after }
+ wm withdraw .tt
+ uplevel #0 $tooltip_on_invis
+}
+
+set tooltip_inwindow 0
+
+proc tooltip-enter {state x y} {
+ variable tooltip_inwindow
+ set tooltip_inwindow 1
+ tooltip-starttimer $state $x $y
+}
+
+proc tooltip-leave {} {
+ variable tooltip_inwindow
+ set tooltip_inwindow 0
+ tooltip-cancel
+}
+
+proc setup-tooltip {on_vis on_invis} {
+ foreach v {vis invis} {
+ variable tooltip_on_$v [set on_$v]
+ }
+ bind .i <Enter> { applet::tooltip-enter %s %X %Y }
+ bind .i <Leave> { applet::tooltip-leave }
+ bind .i <ButtonRelease> {
+ applet::tooltip-cancel
+ applet::tooltip-starttimer %s %X %Y
+ }
+ bind .i <Motion> { applet::tooltip-starttimer %s %X %Y }
+ toplevel .tt -background black
+ wm withdraw .tt
+ wm overrideredirect .tt 1
+ label .tt.t -justify left -background {#EEE1B3}
+ pack .tt.t -padx 1 -pady 1
+ tooltip-set {}
+}
+
+proc tooltip-set {s} {
+ .tt.t configure -text $s
+}
+
+proc tooltip-show {x y} {
+ variable tooltip_on_vis
+ incr x 9
+ incr y 9
+ wm geometry .tt +$x+$y
+ wm deiconify .tt
+ uplevel #0 $tooltip_on_vis
+}
+
+#----- simple images -----
+
+proc setimage {image} {
+ .i configure -image $image
+}
+
+}
+
+
+proc innerwindow-resetup-required {why} {
+ variable innerwindow_after
puts "IW-EVENT $why"
if {[info exists innerwindow_after]} return
set innerwindow_after [after idle innerwindow-resetup]
}
proc innerwindow-resetup {} {
- global innerwindow_after
+ variable innerwindow_after
unset innerwindow_after
puts RESETUP
+ innerwindow-destroying
+
catch { destroy .i.i.c }
if {![winfo exists .i.i]} return
destroy [frame .i.i.make-exist]
pack .i.i.b -fill both -side left -expand 1
frame .i.i.b.c -container 1 -background orange
pack .i.i.b.c -fill both -side left -expand 1
- bind .i.i <ButtonPress> { pressed %b %X %Y }
#
global inner_lastw inner_lasth
#set w [winfo width .i.i]
# set inner_lastw $w
# set inner_lasth $h
# innerwindow-ph-dummy configure -width $w -height 2
- innerwindow [winfo id .i.i.b.c]
+ innerwindow-ready
# }
}
destroy [frame .i.make-exist]
destroy [frame .i.i.make-exist]
- bind .i <<IconConfigure>> { innerwindow-event "%w" }
-}
-
-bind .i <ButtonPress> { pressed %b %X %Y }
-
-proc tooltip_starttimer {state x y} {
- global tooltip_after posted tooltip_inwindow
- if {$state || $posted || !$tooltip_inwindow} { tooltip_cancel; return }
- catch { after cancel $tooltip_after }
- set tooltip_after [after 500 tooltip_show $x $y]
-}
-
-proc tooltip_cancel {} {
- global tooltip_after
- catch { after cancel $tooltip_after }
- catch { unset $tooltip_after }
- wm withdraw .tt
-}
-
-set tooltip_inwindow 0
-
-proc tooltip_enter {state x y} {
- global tooltip_inwindow
- set tooltip_inwindow 1
- tooltip_starttimer $state $x $y
-}
-
-proc tooltip_leave {} {
- global tooltip_inwindow
- set tooltip_inwindow 0
- tooltip_cancel
-}
-
-proc setuptooltip {} {
- bind .i <Enter> { tooltip_enter %s %X %Y }
- bind .i <Leave> { tooltip_leave }
- bind .i <ButtonRelease> { tooltip_cancel; tooltip_starttimer %s %X %Y }
- bind .i <Motion> { tooltip_starttimer %s %X %Y }
- toplevel .tt -background black
- wm withdraw .tt
- wm overrideredirect .tt 1
- label .tt.t -justify left -background {#EEE1B3}
- pack .tt.t -padx 1 -pady 1
- settooltip {}
-}
-
-proc settooltip {s} {
- .tt.t configure -text $s
-}
-
-proc tooltip_show {x y} {
- incr x 9
- incr y 9
- wm geometry .tt +$x+$y
- wm deiconify .tt
-}
-
-proc setimage {image} {
- .i configure -image $image
+ bind .i <<IconConfigure>> { innerwindow-resetup-required IconConfigure }
}