1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
#
# tkballoonhelp.rb : simple balloon help widget
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
#
# Add a balloon help to a widget.
# This widget has only poor featureas. If you need more useful features,
# please try to use the Tix extension of Tcl/Tk under Ruby/Tk.
#
# The interval time to display a balloon help is defined 'interval' option
# (default is 750ms).
#
require 'tk'
module Tk
module RbWidget
class BalloonHelp<TkLabel
end
end
end
class Tk::RbWidget::BalloonHelp<TkLabel
DEFAULT_FOREGROUND = 'black'
DEFAULT_BACKGROUND = 'white'
DEFAULT_INTERVAL = 750
def _balloon_binding(interval)
@timer = TkAfter.new(interval, 1, proc{show})
def @timer.interval(val)
@sleep_time = val
end
@bindtag = TkBindTag.new
@bindtag.bind('Enter', proc{@timer.start})
@bindtag.bind('Motion', proc{@timer.restart; erase})
@bindtag.bind('Any-ButtonPress', proc{@timer.restart; erase})
@bindtag.bind('Leave', proc{@timer.stop; erase})
tags = @parent.bindtags
idx = tags.index(@parent)
unless idx
ppath = TkComm.window(@parent.path)
idx = tags.index(ppath) || 0
end
tags[idx,0] = @bindtag
@parent.bindtags(tags)
end
private :_balloon_binding
def initialize(parent=nil, keys={})
@parent = parent || Tk.root
@frame = TkToplevel.new(@parent)
@frame.withdraw
@frame.overrideredirect(true)
@frame.transient(TkWinfo.toplevel(@parent))
@epath = @frame.path
if keys
keys = _symbolkey2str(keys)
else
keys = {}
end
@command = keys.delete('command')
@interval = keys.delete('interval'){DEFAULT_INTERVAL}
_balloon_binding(@interval)
# @label = TkLabel.new(@frame, 'background'=>'bisque').pack
@label = TkLabel.new(@frame,
'foreground'=>DEFAULT_FOREGROUND,
'background'=>DEFAULT_BACKGROUND).pack
@label.configure(_symbolkey2str(keys)) unless keys.empty?
@path = @label
end
def epath
@epath
end
def interval(val)
if val
@timer.interval(val)
else
@interval
end
end
def command(cmd = Proc.new)
@command = cmd
self
end
def show
x = TkWinfo.pointerx(@parent)
y = TkWinfo.pointery(@parent)
@frame.geometry("+#{x+1}+#{y+1}")
if @command
case @command.arity
when 0
@command.call
when 2
@command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent))
when 3
@command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
self)
else
@command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
self, @parent)
end
end
@frame.deiconify
@frame.raise
begin
@org_cursor = @parent.cget('cursor')
rescue
@org_cursor = @parent['cursor']
end
begin
@parent.configure('cursor', 'crosshair')
rescue
@parent.cursor('crosshair')
end
end
def erase
begin
@parent.configure('cursor', @org_cursor)
rescue
@parent.cursor(@org_cursor)
end
@frame.withdraw
end
def destroy
@frame.destroy
end
end
################################################
# test
################################################
if __FILE__ == $0
TkButton.new('text'=>'This button has a balloon help') {|b|
pack('fill'=>'x')
Tk::RbWidget::BalloonHelp.new(b, 'text'=>' Message ')
}
TkButton.new('text'=>'This button has another balloon help') {|b|
pack('fill'=>'x')
Tk::RbWidget::BalloonHelp.new(b,
'text'=>"CONFIGURED MESSAGE\nchange colors, and so on",
'interval'=>200, 'font'=>'courier',
'background'=>'gray', 'foreground'=>'red')
}
sb = TkScrollbox.new.pack(:fill=>:x)
sb.insert(:end, *%w(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm))
=begin
# CASE1 : command takes no arguemnt
bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
:relief=>:ridge, :background=>'white',
:command=>proc{
y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb)
bh.text "current index == #{sb.nearest(y)}"
})
=end
=begin
# CASE2 : command takes 2 arguemnts
bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
:relief=>:ridge, :background=>'white',
:command=>proc{|x, y|
bh.text "current index == #{sb.nearest(y)}"
})
=end
=begin
# CASE3 : command takes 3 arguemnts
Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
:relief=>:ridge, :background=>'white',
:command=>proc{|x, y, bhelp|
bhelp.text "current index == #{sb.nearest(y)}"
})
=end
=begin
# CASE4a : command is a Proc object and takes 4 arguemnts
cmd = proc{|x, y, bhelp, parent|
bhelp.text "current index == #{parent.nearest(y)}"
}
Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
:relief=>:ridge, :background=>'white',
:command=>cmd)
sb2 = TkScrollbox.new.pack(:fill=>:x)
sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500,
:padx=>5, :relief=>:raised,
:background=>'gray25', :foreground=>'white',
:command=>cmd)
=end
#=begin
# CASE4b : command is a Method object and takes 4 arguemnts
def set_msg(x, y, bhelp, parent)
bhelp.text "current index == #{parent.nearest(y)}"
end
cmd = self.method(:set_msg)
Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
:relief=>:ridge, :background=>'white',
:command=>cmd)
sb2 = TkScrollbox.new.pack(:fill=>:x)
sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500,
:padx=>5, :relief=>:raised,
:background=>'gray25', :foreground=>'white',
:command=>cmd)
#=end
Tk.mainloop
end
|