+# 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.
-#
-
-proc manyset {list args} {
- foreach val $list var $args {
- upvar 1 $var my
- set my $val
- }
-}
-
-
-package require Tclx
-package require tktray
+#
+# 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
-set posted 0
-foreach b {1 3} {
+namespace eval applet {
+
+
+# used by both menus and tooltips
+variable posted 0
+
+#----- menus -----
+
+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
}
+#----- 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} {
- global innerwindow_after
+ 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
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]
destroy [frame .i.i.make-exist]
bind .i <<IconConfigure>> { innerwindow-resetup-required IconConfigure }
}
-
-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
-}
-
-proc fork-then {ondeath inchild} {
- global children errorCode errorInfo
- foreach f {stdout stderr} {
- if {[catch { flush $f } emsg]} {
- catch { bgerror $emsg }
- }
- }
- set pid [fork]
- if {!$pid} {
- if {[catch {
- uplevel 1 $inchild
- } emsg]} {
- puts stderr "CHILD ERROR $emsg\n$errorCode\n$errorInfo\n"
- }
- kill KILL [id process]
- }
- set children($pid) $ondeath
- return $pid
-}
-
-proc chld-handler {} {
- global children
- while 1 {
- if {[catch { set got [wait -nohang] }]} break
- if {![llength $got]} break
- manyset $got pid how how2
- if {[info exists children($pid)]} {
- set l $children($pid)
- unset children($pid)
- if {[catch {
- uplevel #0 [concat [list $l] $how $how2]
- } emsg]} {
- catch { bgerror $emsg }
- }
- }
- }
-}
-
-signal -restart trap CHLD { after idle chld-handler }