+# General purpose code for being a tray applet
+
+proc manyset {list args} {
+ foreach val $list var $args {
+ upvar 1 $var my
+ set my $val
+ }
+}
-#----- general machinery -----
+package require Tclx
package require tktray
-#load /home/ian/things/Systray/tktray-1.3.8/libtktray1.3.8.so
+#----- general machinery -----
+
+# Interface:
+#
+# tk::tktray widget is called .i
+#
+# 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.
+#
+# Alternatively, instead of icon, it may arrange to run (repeatedly
+# if necessary) a subprocess.
+#
+# Caller that needs access to inner window should call
+# applet::setup-subwindow WIDTH ON-DESTROYING ON-READY
+# Then the main code will call ON-DESTROYING just before
+# destroying the inner window and recreating it, and ON-READY
+# just after. Afterwards, theh inner window is called
+# .
+#
+# proc innerwindow {} { ... }
+# and run
+# innerwindow
+# This will create
+# .i.i.b frame to contain container
+# .i.i.b.c actual container
+#
+# Button presses
+#
+# 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 pressed {b x y} {
- global posted
- tooltip_cancel
+proc menubuttonpressed {b x y} {
+ variable posted
+ tooltip-cancel
if {$posted == $b} {
puts "unpost $posted toggle"
.m$posted unpost
}
proc msel {} {
- global posted
+ variable posted
set posted 0
}
-proc setupinnerwindow {} {
- global innerwindow_after innerwindow
- catch { after cancel $innerwindow_after }
- catch { unset innerwindow_after }
- if {[info exists innerwindow]} return
- set children {}
- foreach child [winfo children .i] {
- if {![winfo exists $child]} continue
- lappend children $child
- }
- if {[llength $children]==1} {
- set innerwindow [lindex $children 0]
- bind $innerwindow <Destroy> {
- innerwindow-unavailable
- catch { unset innerwindow }
- after idle setupinnerwindow
- }
- innerwindow-available
- } else {
- after 5000 setupinnerwindow
- }
-}
+#----- tooltips -----
-bind .i <ButtonPress> { pressed %b %X %Y }
+variable tooltip_on_vis {}
+variable tooltip_on_invis {}
-proc tooltip_starttimer {state x y} {
- global tooltip_after posted tooltip_inwindow
- if {$state || $posted || !$tooltip_inwindow} { tooltip_cancel; return }
+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 tooltip_show $x $y]
+ set tooltip_after [after 500 applet::tooltip-show $x $y]
}
-proc tooltip_cancel {} {
- global tooltip_after
+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} {
- global tooltip_inwindow
+proc tooltip-enter {state x y} {
+ variable tooltip_inwindow
set tooltip_inwindow 1
- tooltip_starttimer $state $x $y
+ tooltip-starttimer $state $x $y
}
-proc tooltip_leave {} {
- global tooltip_inwindow
+proc tooltip-leave {} {
+ variable tooltip_inwindow
set tooltip_inwindow 0
- tooltip_cancel
+ 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 }
+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
- settooltip {}
+ tooltip-set {}
}
-proc settooltip {s} {
+proc tooltip-set {s} {
.tt.t configure -text $s
}
-proc tooltip_show {x y} {
+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
}
+
+#----- subwindow -----
+
+variable subwindow_on_destroying
+variable subwindow_on_ready
+
+proc innerwindow-resetup-required {why} {
+ variable innerwindow_after
+puts "IW-EVENT $why"
+ if {[info exists innerwindow_after]} return
+ set innerwindow_after [after idle applet::innerwindow-resetup]
+}
+
+proc innerwindow-resetup {} {
+ variable innerwindow_after
+ variable subwindow_on_destroying
+ variable subwindow_on_ready
+ unset innerwindow_after
+
+puts RESETUP
+
+ uplevel #0 $subwindow_on_destroying
+
+ catch { destroy .i.i.c }
+ if {![winfo exists .i.i]} return
+ destroy [frame .i.i.make-exist]
+ catch { destroy .i.i.b.c }
+ catch { destroy .i.i.b }
+ frame .i.i.b
+ 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
+#
+ global inner_lastw inner_lasth
+ #set w [winfo width .i.i]
+# set w [winfo width .i.i]
+# set h [winfo height .i.i]
+
+# if {$w != $inner_lastw || $h != $inner_lasth} {
+# set inner_lastw $w
+# set inner_lasth $h
+# innerwindow-ph-dummy configure -width $w -height 2
+
+ uplevel #0 $subwindow_on_ready
+# }
+}
+
+proc setup-subwindow {w on_destroying on_ready} {
+ foreach v {destroying ready} {
+ variable subwindow_on_$v [set on_$v]
+ }
+
+ global inner_lastw inner_lasth
+ set inner_lastw -2
+ set inner_lasth -2
+
+ image create photo applet::innerwindow-ph-dummy -width $w -height 2
+ .i configure -image applet::innerwindow-ph-dummy
+
+ destroy [frame .i.make-exist]
+ destroy [frame .i.i.make-exist]
+ bind .i <<IconConfigure>> {
+ applet::innerwindow-resetup-required IconConfigure
+ }
+}
+
+}