tkxxs 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZjhkMTczM2I5YzdkZTkwZTQ0NGRlZDI2NGZhNDM1ZGZhYTEwZWQzNA==
4
+ OTNlZTU3NjY4YTQ5ZWMxYmFjOTM5YjlkZDhjYWM3ZmNkODA1MTM5Yw==
5
5
  data.tar.gz: !binary |-
6
- MDVlYWM1NWE4YTE2MTY4YTVkODNkZjBhZmFiMGIxOGNhZWI0YjU3MA==
6
+ ZDBjMDA2MmEyODBjNzA4OWIwODdmMmJhNzNlMDc5ZTNkM2MwOWI0NQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzU2ODQ0OTcwZjQwZTE5YTljNmE2N2JiM2M4NDc5MGQxODljMzMxMmI2Yjdk
10
- MWE1ZDkxYWY5ZjE2NWU4OWMzYjJkYWZhNTI5MTVlNDYzYjkyMjc1NTViNmZk
11
- NjZjNGEwZmZjMjc2ZWFjMWY3OWVlNjczNDk4ZjMxNTc2OWQ5YWY=
9
+ Y2ViN2EwY2ZkMTU1MGE1ZTI1NmI0NGQ1ZmZhZDkyMTcyNTY0OTJlOGEwMGQ3
10
+ NzVlMGE1Zjk1OTBhNzVkYjkxYzkxNjBlOWQ5MjAzYjFjYTBlMjAxMmQ2NzM4
11
+ NzNhZDhhYThiMzc2MzY0MzllNDhjZTAzMWRkMDVlOGNlNGVhOTE=
12
12
  data.tar.gz: !binary |-
13
- MDI1MmQyY2E5ZjJhNGRiYTM1Zjk4ZmM4MzE0ODI3Zjg4YzI0Mjg1OWUxM2Ew
14
- NGEwMzkxN2EzZWI2OWZhNTBkNzZhOTE2YjIyZWZhNzNiYTkyZTA1NzQwZDVi
15
- NThjYjE0OGE1ZDk4NzFiMjRhYmY1NDlmNWM2MTRlZWJlNzA5YWY=
13
+ NTIwNGVjYThkZDdiODljYmZmMjQxMTI2ZmNkMDYxZmVkMzZkYzIzZmE0ZGYz
14
+ Y2U1NjEwMmZmYjYzMDkwMjZlZTFjMGQ3ZGQxNjYzZTdiYWEzYzJmMDU2YjEz
15
+ YWI4NTBhMTRlYzU3ODgzY2RiMDBhYmYyYzU5ZmM0ZWY3MmZhZGE=
@@ -1,2 +1,3 @@
1
1
 
2
- * Axel Friedrich: axel dod friedrich_smail ad gmx dod de
2
+ * Axel Friedrich: axel dod friedrich_smail ad gmx dod de
3
+ * Abinoam P. Marques Jr.
@@ -1,3 +1,13 @@
1
+ === 0.1.2 / 2013-01-05
2
+
3
+ * Made it work on Ubuntu (Many thanks to Abinoam P. Marques Jr.)
4
+ * Fixed a bug in handling configSection. (Can be used now.)
5
+ * Updated documentation and readme.
6
+
7
+ === 0.1.1 / 2014-01-02
8
+
9
+ * Translated remaining German text to English
10
+
1
11
  === 0.1.0 / 2014-01-01
2
12
 
3
13
  * 1 major enhancement
@@ -3,7 +3,7 @@ CONTRIBUTORS
3
3
  History.txt
4
4
  LICENSE
5
5
  Manifest.txt
6
- README.txt
6
+ README.rdoc
7
7
  Rakefile
8
8
  ext/readme.txt
9
9
  ext/tkballoonhelp.rb
@@ -1,6 +1,6 @@
1
1
  = TKXXS
2
2
 
3
- * https://github.com/Axel2
3
+ * https://github.com/Axel2/tkxxs
4
4
 
5
5
  == References
6
6
 
@@ -12,7 +12,7 @@ TKXXS_CLASSES is intended for developers only.
12
12
 
13
13
  == Description
14
14
 
15
- TKXXS provides a very simple and very easy to use GUI (graphical user interface) for Ruby; It gives you a persistent output window and popping up (modal) dialogs for input; For a screenshot, see: images/screenshot.png; Tested on Windows, only.
15
+ TKXXS provides a very simple and very easy to use GUI (graphical user interface) for Ruby; It gives you a persistent output window and popping up (modal) dialogs for input; For a screenshot, see: <tt>https://github.com/Axel2/tkxxs/blob/master/images/screenshot.png</tt>; I tested it on Windows, only; Got user report, that it works on Ubuntu, too.
16
16
 
17
17
  TKXXS shall:
18
18
 
@@ -25,7 +25,7 @@ TKXXS shall:
25
25
 
26
26
 
27
27
  Drawbacks:
28
- * I'v tested it only on Windows. Other operating system probably will need modifications, which I would like to merge in.
28
+ * I'v tested it only on Windows, but got user report, that it works on Ubuntu, too.l
29
29
  * For sure some more drawbacks which I'm not aware of now.
30
30
 
31
31
 
@@ -90,11 +90,43 @@ You close the application simply by clicking the close-icon on top of the output
90
90
  See samples/big_example.rb
91
91
 
92
92
 
93
+ == configSection
94
+
95
+ Normally, you need not care about it.
96
+
97
+ The hash-argument of the dialog methods take as key <tt>:configSection</tt>. The value of this key sets the section name of the configuration file, where configuration setting of this dialog are stored and read from. Configuration settings are, for example: Window size and position, and recent dirs/files and favorite dirs/files.
98
+
99
+ Key may be String, Integer, Float or nil, but not Symbol. nil is the default section.
100
+ * Setting section: Conf#section=
101
+ * Reading the actual section: Conf#section
102
+ * Configuration file path is: Conf#filename (It's YAML)
103
+
104
+ The config section remains unchanged, unless it is set to a new value by either using:
105
+ Conf#section = ...
106
+ or by setting the <tt>:configSection</tt> of the hash-argument of the dialog methods.
107
+
108
+ You can use <tt>:configSection</tt> for example, if you want to have different favorite dirs for two different choose_dir-dialogs. Example code:
109
+
110
+ CONF = Conf.new # This is set inside TKXXS
111
+ ...
112
+ old_section = CONF.section
113
+
114
+ left_dir = choose_dir(
115
+ :configSection=>'left'
116
+ )
117
+
118
+ right_dir = choose_dir(
119
+ :configSection=>'right',
120
+ )
121
+
122
+ CONF.section = old_section
123
+ ...
124
+
93
125
  == Installation
94
126
 
95
127
  === Prerequisites
96
128
 
97
- * Tested only on Windows
129
+ * Tested only on Windows (but user reported that it works on Ubuntu, too.)
98
130
  * Ruby 1.8.7 or 1.9.x with TK (e.g. RubyInstaller)
99
131
  * gem Platform (starting with capital letter "P"!)
100
132
 
@@ -1,332 +1,332 @@
1
- #
2
- # tkballoonhelp.rb : simple balloon help widget
3
- # by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
4
- #
5
- # Add a balloon help to a widget.
6
- # This widget has only poor featureas. If you need more useful features,
7
- # please try to use the Tix extension of Tcl/Tk under Ruby/Tk.
8
- #
9
- # The interval time to display a balloon help is defined 'interval' option
10
- # (default is 750ms).
11
- #
12
- # Modifications by Axel Friedrich:
13
- # * 2010-03-01:
14
- # * 2010-01-31: Shifting position of balloon if it is out of screen
15
- # * TODO: wraplength
16
- require 'tk'
17
-
18
- module Tk
19
- module RbWidget
20
- class BalloonHelp<TkLabel
21
- end
22
- end
23
- end
24
- class Tk::RbWidget::BalloonHelp<TkLabel
25
- DEFAULT_FOREGROUND = 'black'
26
- DEFAULT_BACKGROUND = 'white'
27
- DEFAULT_INTERVAL = 750
28
-
29
- def _balloon_binding(interval)
30
- @timer = TkAfter.new(interval, 1, proc{show})
31
- def @timer.interval(val)
32
- @sleep_time = val
33
- end
34
- @bindtag = TkBindTag.new
35
- @bindtag.bind('Enter', proc{@timer.start})
36
- @bindtag.bind('Motion', proc{@timer.restart; erase})
37
- @bindtag.bind('Any-ButtonPress', proc{@timer.restart; erase})
38
- @bindtag.bind('Leave', proc{@timer.stop; erase})
39
- tags = @parent.bindtags
40
- idx = tags.index(@parent)
41
- unless idx
42
- ppath = TkComm.window(@parent.path)
43
- idx = tags.index(ppath) || 0
44
- end
45
- tags[idx,0] = @bindtag
46
- @parent.bindtags(tags)
47
- end
48
- private :_balloon_binding
49
-
50
- def initialize(parent=nil, keys={})
51
- @parent = parent || Tk.root
52
-
53
- @frame = TkToplevel.new(@parent)
54
- if defined?($tkxxs_) && $tkxxs_[:userscreenx]
55
- $balloonhlp_ = Hash.new
56
- $balloonhlp_[:userscreenx] = $tkxxs_[:userscreenx]
57
- $balloonhlp_[:userscreeny] = $tkxxs_[:userscreeny]
58
- $balloonhlp_[:userscreenwidth] = $tkxxs_[:userscreenwidth]
59
- $balloonhlp_[:userscreenheight] = $tkxxs_[:userscreenheight]
60
- elsif !defined?($balloonhlp_) || !$balloonhlp_[:userscreenx]
61
- userscreen(@frame)
62
- end
63
- @frame.withdraw
64
- @frame.overrideredirect(true)
65
- @frame.transient(TkWinfo.toplevel(@parent))
66
- @epath = @frame.path
67
-
68
- if keys
69
- keys = _symbolkey2str(keys)
70
- else
71
- keys = {}
72
- end
73
-
74
- @command = keys.delete('command')
75
-
76
- @interval = keys.delete('interval'){DEFAULT_INTERVAL}
77
- _balloon_binding(@interval)
78
-
79
- # @label = TkLabel.new(@frame, 'background'=>'bisque').pack
80
- @label = TkLabel.new(@frame,
81
- ## :wraplength => '2i', # Axel
82
- 'foreground'=>DEFAULT_FOREGROUND,
83
- ## 'background'=>DEFAULT_BACKGROUND).pack # -Axel
84
- 'background'=>DEFAULT_BACKGROUND).pack(:expand=>1, :fill=>:both)
85
- @label.configure(_symbolkey2str(keys)) unless keys.empty?
86
- @path = @label
87
- end
88
-
89
- def userscreen( root )
90
- # TODO: Screen "pops"; other way?
91
- root.state('zoomed')
92
- root.update
93
-
94
- if RUBY_PLATFORM[/mingw|mswin|bccwin/ix] # Windows
95
- root.state('zoomed') # OK on Windows, bad on Linux
96
- else
97
- # Linux: works
98
- # Other: not tested
99
- root.height = root.winfo_screenheight
100
- root.width = root.winfo_screenwidth
101
- end
102
-
103
- root.winfo_geometry =~ /(\d+)x(\d+)\+([+-]?\d+)\+([+-]?\d+)/
104
- xwg = $3.to_i
105
- ywg = $4.to_i
106
- root.geometry =~ /(\d+)x(\d+)\+([+-]?\d+)\+([+-]?\d+)/
107
- gw = $1.to_i
108
- gh = $2.to_i
109
-
110
- ## sw = root.winfo_screenwidth
111
- ## sh = root.winfo_screenheight
112
-
113
- rx = root.winfo_rootx
114
- ry = root.winfo_rooty # maybe, taskbar height
115
-
116
- border = -[xwg,ywg].min
117
- userscreenx = xwg + border
118
- userscreeny= ywg + border
119
- userscreenwidth = gw
120
- userscreenheight = gh + ry - ywg - border
121
-
122
- $balloonhlp_ ||= Hash.new
123
- $balloonhlp_[:userscreenx ] = userscreenx
124
- $balloonhlp_[:userscreeny ] = userscreeny
125
- $balloonhlp_[:userscreenwidth ] = userscreenwidth
126
- $balloonhlp_[:userscreenheight] = userscreenheight
127
-
128
- root.state('normal')
129
- nil
130
- end # userscreen
131
-
132
- def epath
133
- @epath
134
- end
135
-
136
- def interval(val)
137
- if val
138
- @timer.interval(val)
139
- else
140
- @interval
141
- end
142
- end
143
-
144
- def command(cmd = Proc.new)
145
- @command = cmd
146
- self
147
- end
148
-
149
- def show
150
- x = TkWinfo.pointerx(@parent)
151
- y = TkWinfo.pointery(@parent)
152
- ## @frame.geometry("+#{x+1}+#{y+1}")
153
-
154
- if @command
155
- case @command.arity
156
- when 0
157
- @command.call
158
- when 2
159
- @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent))
160
- when 3
161
- @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
162
- self)
163
- else
164
- @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
165
- self, @parent)
166
- end
167
- end
168
-
169
- @frame.geometry("+#{x+1}+#{y+1}")
170
- @frame.update
171
-
172
- rw = TkWinfo.reqwidth(@frame)
173
- rh = TkWinfo.reqheight(@frame)
174
- geom1 = geom(x,y,rw,rh)
175
- @frame.geometry(geom1)
176
-
177
- @frame.deiconify
178
- @frame.raise
179
-
180
- ## @org_cursor = @parent['cursor'] # -patch Nagai
181
- ## @parent.cursor('crosshair') # -patch Nagai
182
- begin # +patch Nagai
183
- @org_cursor = @parent.cget('cursor') # +patch Nagai
184
- rescue # +patch Nagai
185
- @org_cursor = @parent['cursor'] # +patch Nagai
186
- end # +patch Nagai
187
- begin # +patch Nagai
188
- @parent.configure('cursor', 'crosshair') # +patch Nagai
189
- rescue # +patch Nagai
190
- @parent.cursor('crosshair') # +patch Nagai
191
- end # +patch Nagai
192
-
193
- @frame.update
194
- end
195
-
196
- def geom( x,y,rw,rh, gapx=1, gapy=10 ) # gap: pixels; may not be 0!
197
- xcorrected = false
198
- ## rw = TkWinfo.reqwidth(@frame)
199
- ## rh = TkWinfo.reqheight(@frame)
200
- xmin = $balloonhlp_[:userscreenx]
201
- ymin = $balloonhlp_[:userscreeny]
202
- xmax= xmin + $balloonhlp_[:userscreenwidth]
203
- ymax= ymin + $balloonhlp_[:userscreenheight]
204
-
205
- origx = x
206
- x += gapx
207
- y += gapy
208
-
209
- if x + rw > xmax
210
- x = [(xmax-rw), xmin].max # Shift left
211
- xcorrected = true
212
- end
213
-
214
- y = y - gapy - rh if y + rh > ymax # Shift up
215
-
216
- if y < ymin # height will overlap pointer
217
- y = ymin
218
- x = origx - rw - gapx if xcorrected # Shift left
219
- end
220
-
221
- if x < xmin # to big
222
- x = xmin
223
- wrap_help
224
- end
225
- geom = "+#{ x }+#{ y }" # balloon may not overlap cursor - why?
226
-
227
- geom
228
- end # geom
229
-
230
-
231
- def wrap_help( )
232
- #TODO: Introduce "wraplength"
233
- puts 'Cannot show balloon help: to big.'
234
- end # wrap_help
235
-
236
-
237
- def erase
238
- ## @parent.cursor(@org_cursor) # -patch Nagai
239
- begin # +patch Nagai
240
- @parent.configure('cursor', @org_cursor) # +patch Nagai
241
- rescue # +patch Nagai
242
- @parent.cursor(@org_cursor) # +patch Nagai
243
- end # +patch Nagai
244
- @frame.withdraw
245
- end
246
-
247
- def destroy
248
- @frame.destroy
249
- end
250
- end
251
-
252
- ################################################
253
- # test
254
- ################################################
255
- if __FILE__ == $0
256
- TkButton.new('text'=>'This button has a balloon help') {|b|
257
- pack('fill'=>'x')
258
- Tk::RbWidget::BalloonHelp.new(b, 'text'=>' Message ')
259
- }
260
- TkButton.new('text'=>'This button has another balloon help') {|b|
261
- pack('fill'=>'x')
262
- Tk::RbWidget::BalloonHelp.new(b,
263
- 'text'=>"CONFIGURED MESSAGE\nchange colors, and so on",
264
- 'interval'=>200, 'font'=>'courier',
265
- 'background'=>'gray', 'foreground'=>'red')
266
- }
267
-
268
- sb = TkScrollbox.new.pack(:fill=>:x)
269
- sb.insert(:end, *%w(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm))
270
- =begin
271
- # CASE1 : command takes no arguemnt
272
- bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
273
- :relief=>:ridge, :background=>'white',
274
- :command=>proc{
275
- y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb)
276
- bh.text "current index == #{sb.nearest(y)}"
277
- })
278
- =end
279
- =begin
280
- # CASE2 : command takes 2 arguemnts
281
- bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
282
- :relief=>:ridge, :background=>'white',
283
- :command=>proc{|x, y|
284
- bh.text "current index == #{sb.nearest(y)}"
285
- })
286
- =end
287
- =begin
288
- # CASE3 : command takes 3 arguemnts
289
- Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
290
- :relief=>:ridge, :background=>'white',
291
- :command=>proc{|x, y, bhelp|
292
- bhelp.text "current index == #{sb.nearest(y)}"
293
- })
294
- =end
295
- =begin
296
- # CASE4a : command is a Proc object and takes 4 arguemnts
297
- cmd = proc{|x, y, bhelp, parent|
298
- bhelp.text "current index == #{parent.nearest(y)}"
299
- }
300
-
301
- Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
302
- :relief=>:ridge, :background=>'white',
303
- :command=>cmd)
304
-
305
- sb2 = TkScrollbox.new.pack(:fill=>:x)
306
- sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
307
- Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500,
308
- :padx=>5, :relief=>:raised,
309
- :background=>'gray25', :foreground=>'white',
310
- :command=>cmd)
311
- =end
312
- #=begin
313
- # CASE4b : command is a Method object and takes 4 arguemnts
314
- def set_msg(x, y, bhelp, parent)
315
- bhelp.text "current index == #{parent.nearest(y)}"
316
- end
317
- cmd = self.method(:set_msg)
318
-
319
- Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
320
- :relief=>:ridge, :background=>'white',
321
- :command=>cmd)
322
-
323
- sb2 = TkScrollbox.new.pack(:fill=>:x)
324
- sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
325
- Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500,
326
- :padx=>5, :relief=>:raised,
327
- :background=>'gray25', :foreground=>'white',
328
- :command=>cmd)
329
- #=end
330
-
331
- Tk.mainloop
332
- end
1
+ #
2
+ # tkballoonhelp.rb : simple balloon help widget
3
+ # by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
4
+ #
5
+ # Add a balloon help to a widget.
6
+ # This widget has only poor featureas. If you need more useful features,
7
+ # please try to use the Tix extension of Tcl/Tk under Ruby/Tk.
8
+ #
9
+ # The interval time to display a balloon help is defined 'interval' option
10
+ # (default is 750ms).
11
+ #
12
+ # Modifications by Axel Friedrich:
13
+ # * 2010-03-01:
14
+ # * 2010-01-31: Shifting position of balloon if it is out of screen
15
+ # * TODO: wraplength
16
+ require 'tk'
17
+
18
+ module Tk
19
+ module RbWidget
20
+ class BalloonHelp<TkLabel
21
+ end
22
+ end
23
+ end
24
+ class Tk::RbWidget::BalloonHelp<TkLabel
25
+ DEFAULT_FOREGROUND = 'black'
26
+ DEFAULT_BACKGROUND = 'white'
27
+ DEFAULT_INTERVAL = 750
28
+
29
+ def _balloon_binding(interval)
30
+ @timer = TkAfter.new(interval, 1, proc{show})
31
+ def @timer.interval(val)
32
+ @sleep_time = val
33
+ end
34
+ @bindtag = TkBindTag.new
35
+ @bindtag.bind('Enter', proc{@timer.start})
36
+ @bindtag.bind('Motion', proc{@timer.restart; erase})
37
+ @bindtag.bind('Any-ButtonPress', proc{@timer.restart; erase})
38
+ @bindtag.bind('Leave', proc{@timer.stop; erase})
39
+ tags = @parent.bindtags
40
+ idx = tags.index(@parent)
41
+ unless idx
42
+ ppath = TkComm.window(@parent.path)
43
+ idx = tags.index(ppath) || 0
44
+ end
45
+ tags[idx,0] = @bindtag
46
+ @parent.bindtags(tags)
47
+ end
48
+ private :_balloon_binding
49
+
50
+ def initialize(parent=nil, keys={})
51
+ @parent = parent || Tk.root
52
+
53
+ @frame = TkToplevel.new(@parent)
54
+ if defined?($tkxxs_) && $tkxxs_[:userscreenx]
55
+ $balloonhlp_ = Hash.new
56
+ $balloonhlp_[:userscreenx] = $tkxxs_[:userscreenx]
57
+ $balloonhlp_[:userscreeny] = $tkxxs_[:userscreeny]
58
+ $balloonhlp_[:userscreenwidth] = $tkxxs_[:userscreenwidth]
59
+ $balloonhlp_[:userscreenheight] = $tkxxs_[:userscreenheight]
60
+ elsif !defined?($balloonhlp_) || !$balloonhlp_[:userscreenx]
61
+ userscreen(@frame)
62
+ end
63
+ @frame.withdraw
64
+ @frame.overrideredirect(true)
65
+ @frame.transient(TkWinfo.toplevel(@parent))
66
+ @epath = @frame.path
67
+
68
+ if keys
69
+ keys = _symbolkey2str(keys)
70
+ else
71
+ keys = {}
72
+ end
73
+
74
+ @command = keys.delete('command')
75
+
76
+ @interval = keys.delete('interval'){DEFAULT_INTERVAL}
77
+ _balloon_binding(@interval)
78
+
79
+ # @label = TkLabel.new(@frame, 'background'=>'bisque').pack
80
+ @label = TkLabel.new(@frame,
81
+ ## :wraplength => '2i', # Axel
82
+ 'foreground'=>DEFAULT_FOREGROUND,
83
+ ## 'background'=>DEFAULT_BACKGROUND).pack # -Axel
84
+ 'background'=>DEFAULT_BACKGROUND).pack(:expand=>1, :fill=>:both)
85
+ @label.configure(_symbolkey2str(keys)) unless keys.empty?
86
+ @path = @label
87
+ end
88
+
89
+ def userscreen( root )
90
+ # TODO: Screen "pops"; other way?
91
+ root.state('zoomed')
92
+ root.update
93
+
94
+ if RUBY_PLATFORM[/mingw|mswin|bccwin/ix] # Windows
95
+ root.state('zoomed') # OK on Windows, bad on Linux
96
+ else
97
+ # Linux: works
98
+ # Other: not tested
99
+ root.height = root.winfo_screenheight
100
+ root.width = root.winfo_screenwidth
101
+ end
102
+
103
+ root.winfo_geometry =~ /(\d+)x(\d+)\+([+-]?\d+)\+([+-]?\d+)/
104
+ xwg = $3.to_i
105
+ ywg = $4.to_i
106
+ root.geometry =~ /(\d+)x(\d+)\+([+-]?\d+)\+([+-]?\d+)/
107
+ gw = $1.to_i
108
+ gh = $2.to_i
109
+
110
+ ## sw = root.winfo_screenwidth
111
+ ## sh = root.winfo_screenheight
112
+
113
+ rx = root.winfo_rootx
114
+ ry = root.winfo_rooty # maybe, taskbar height
115
+
116
+ border = -[xwg,ywg].min
117
+ userscreenx = xwg + border
118
+ userscreeny= ywg + border
119
+ userscreenwidth = gw
120
+ userscreenheight = gh + ry - ywg - border
121
+
122
+ $balloonhlp_ ||= Hash.new
123
+ $balloonhlp_[:userscreenx ] = userscreenx
124
+ $balloonhlp_[:userscreeny ] = userscreeny
125
+ $balloonhlp_[:userscreenwidth ] = userscreenwidth
126
+ $balloonhlp_[:userscreenheight] = userscreenheight
127
+
128
+ root.state('normal')
129
+ nil
130
+ end # userscreen
131
+
132
+ def epath
133
+ @epath
134
+ end
135
+
136
+ def interval(val)
137
+ if val
138
+ @timer.interval(val)
139
+ else
140
+ @interval
141
+ end
142
+ end
143
+
144
+ def command(cmd = Proc.new)
145
+ @command = cmd
146
+ self
147
+ end
148
+
149
+ def show
150
+ x = TkWinfo.pointerx(@parent)
151
+ y = TkWinfo.pointery(@parent)
152
+ ## @frame.geometry("+#{x+1}+#{y+1}")
153
+
154
+ if @command
155
+ case @command.arity
156
+ when 0
157
+ @command.call
158
+ when 2
159
+ @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent))
160
+ when 3
161
+ @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
162
+ self)
163
+ else
164
+ @command.call(x - TkWinfo.rootx(@parent), y - TkWinfo.rooty(@parent),
165
+ self, @parent)
166
+ end
167
+ end
168
+
169
+ @frame.geometry("+#{x+1}+#{y+1}")
170
+ @frame.update
171
+
172
+ rw = TkWinfo.reqwidth(@frame)
173
+ rh = TkWinfo.reqheight(@frame)
174
+ geom1 = geom(x,y,rw,rh)
175
+ @frame.geometry(geom1)
176
+
177
+ @frame.deiconify
178
+ @frame.raise
179
+
180
+ ## @org_cursor = @parent['cursor'] # -patch Nagai
181
+ ## @parent.cursor('crosshair') # -patch Nagai
182
+ begin # +patch Nagai
183
+ @org_cursor = @parent.cget('cursor') # +patch Nagai
184
+ rescue # +patch Nagai
185
+ @org_cursor = @parent['cursor'] # +patch Nagai
186
+ end # +patch Nagai
187
+ begin # +patch Nagai
188
+ @parent.configure('cursor', 'crosshair') # +patch Nagai
189
+ rescue # +patch Nagai
190
+ @parent.cursor('crosshair') # +patch Nagai
191
+ end # +patch Nagai
192
+
193
+ @frame.update
194
+ end
195
+
196
+ def geom( x,y,rw,rh, gapx=1, gapy=10 ) # gap: pixels; may not be 0!
197
+ xcorrected = false
198
+ ## rw = TkWinfo.reqwidth(@frame)
199
+ ## rh = TkWinfo.reqheight(@frame)
200
+ xmin = $balloonhlp_[:userscreenx]
201
+ ymin = $balloonhlp_[:userscreeny]
202
+ xmax= xmin + $balloonhlp_[:userscreenwidth]
203
+ ymax= ymin + $balloonhlp_[:userscreenheight]
204
+
205
+ origx = x
206
+ x += gapx
207
+ y += gapy
208
+
209
+ if x + rw > xmax
210
+ x = [(xmax-rw), xmin].max # Shift left
211
+ xcorrected = true
212
+ end
213
+
214
+ y = y - gapy - rh if y + rh > ymax # Shift up
215
+
216
+ if y < ymin # height will overlap pointer
217
+ y = ymin
218
+ x = origx - rw - gapx if xcorrected # Shift left
219
+ end
220
+
221
+ if x < xmin # to big
222
+ x = xmin
223
+ wrap_help
224
+ end
225
+ geom = "+#{ x }+#{ y }" # balloon may not overlap cursor - why?
226
+
227
+ geom
228
+ end # geom
229
+
230
+
231
+ def wrap_help( )
232
+ #TODO: Introduce "wraplength"
233
+ puts 'Cannot show balloon help: to big.'
234
+ end # wrap_help
235
+
236
+
237
+ def erase
238
+ ## @parent.cursor(@org_cursor) # -patch Nagai
239
+ begin # +patch Nagai
240
+ @parent.configure('cursor', @org_cursor) # +patch Nagai
241
+ rescue # +patch Nagai
242
+ @parent.cursor(@org_cursor) # +patch Nagai
243
+ end # +patch Nagai
244
+ @frame.withdraw
245
+ end
246
+
247
+ def destroy
248
+ @frame.destroy
249
+ end
250
+ end
251
+
252
+ ################################################
253
+ # test
254
+ ################################################
255
+ if __FILE__ == $0
256
+ TkButton.new('text'=>'This button has a balloon help') {|b|
257
+ pack('fill'=>'x')
258
+ Tk::RbWidget::BalloonHelp.new(b, 'text'=>' Message ')
259
+ }
260
+ TkButton.new('text'=>'This button has another balloon help') {|b|
261
+ pack('fill'=>'x')
262
+ Tk::RbWidget::BalloonHelp.new(b,
263
+ 'text'=>"CONFIGURED MESSAGE\nchange colors, and so on",
264
+ 'interval'=>200, 'font'=>'courier',
265
+ 'background'=>'gray', 'foreground'=>'red')
266
+ }
267
+
268
+ sb = TkScrollbox.new.pack(:fill=>:x)
269
+ sb.insert(:end, *%w(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm))
270
+ =begin
271
+ # CASE1 : command takes no arguemnt
272
+ bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
273
+ :relief=>:ridge, :background=>'white',
274
+ :command=>proc{
275
+ y = TkWinfo.pointery(sb) - TkWinfo.rooty(sb)
276
+ bh.text "current index == #{sb.nearest(y)}"
277
+ })
278
+ =end
279
+ =begin
280
+ # CASE2 : command takes 2 arguemnts
281
+ bh = Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
282
+ :relief=>:ridge, :background=>'white',
283
+ :command=>proc{|x, y|
284
+ bh.text "current index == #{sb.nearest(y)}"
285
+ })
286
+ =end
287
+ =begin
288
+ # CASE3 : command takes 3 arguemnts
289
+ Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
290
+ :relief=>:ridge, :background=>'white',
291
+ :command=>proc{|x, y, bhelp|
292
+ bhelp.text "current index == #{sb.nearest(y)}"
293
+ })
294
+ =end
295
+ =begin
296
+ # CASE4a : command is a Proc object and takes 4 arguemnts
297
+ cmd = proc{|x, y, bhelp, parent|
298
+ bhelp.text "current index == #{parent.nearest(y)}"
299
+ }
300
+
301
+ Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
302
+ :relief=>:ridge, :background=>'white',
303
+ :command=>cmd)
304
+
305
+ sb2 = TkScrollbox.new.pack(:fill=>:x)
306
+ sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
307
+ Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500,
308
+ :padx=>5, :relief=>:raised,
309
+ :background=>'gray25', :foreground=>'white',
310
+ :command=>cmd)
311
+ =end
312
+ #=begin
313
+ # CASE4b : command is a Method object and takes 4 arguemnts
314
+ def set_msg(x, y, bhelp, parent)
315
+ bhelp.text "current index == #{parent.nearest(y)}"
316
+ end
317
+ cmd = self.method(:set_msg)
318
+
319
+ Tk::RbWidget::BalloonHelp.new(sb, :interval=>500,
320
+ :relief=>:ridge, :background=>'white',
321
+ :command=>cmd)
322
+
323
+ sb2 = TkScrollbox.new.pack(:fill=>:x)
324
+ sb2.insert(:end, *%w(AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK LLL MMM))
325
+ Tk::RbWidget::BalloonHelp.new(sb2, :interval=>500,
326
+ :padx=>5, :relief=>:raised,
327
+ :background=>'gray25', :foreground=>'white',
328
+ :command=>cmd)
329
+ #=end
330
+
331
+ Tk.mainloop
332
+ end