OSDN Git Service

ruby-1.9.1-rc1
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / tk / sample / demos-jp / entry3.rb
1 # -*- coding: euc-jp -*-
2 # entry3.rb --
3 #
4 # This demonstration script creates several entry widgets whose
5 # permitted input is constrained in some way.  It also shows off a
6 # password entry.
7 #
8 # based on Tcl/Tk8.4.4 widget demos
9
10 if defined?($entry3_demo) && $entry3_demo
11   $entry3_demo.destroy 
12   $entry3_demo = nil
13 end
14
15 $entry3_demo = TkToplevel.new {|w|
16   title("Constrained Entry Demonstration")
17   iconname("entry3")
18   positionWindow(w)
19 }
20
21 base_frame = TkFrame.new($entry3_demo).pack(:fill=>:both, :expand=>true)
22
23 TkLabel.new(base_frame, 
24             :font=>$font, :wraplength=>'5i', :justify=>:left, 
25             :text=><<EOL).pack(:side=>:top)
26 °Ê²¼¤Ë¤Ï£´¼ïÎà¤Î¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥³Æ¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤Ï¡¤\
27 ¥Þ¥¦¥¹¥¯¥ê¥Ã¥¯¤ÇÁªÂò¤·Ê¸»ú¤òÂǤÁ¹þ¤à¤³¤È¤¬²Äǽ¤Ç¤¹¤¬¡¤¤½¤ì¤¾¤ì¤¬¤É¤Î¤è¤¦¤Ê\
28 ÆþÎϤò¼õ¤±ÉÕ¤±¤ë¤³¤È¤¬¤Ç¤­¤ë¤«¤Ë¤ÏÀ©Ìó¤¬Àߤ±¤é¤ì¤Æ¤¤¤Þ¤¹¡¥\
29 °ì¤Ä¤á¤Î¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤ÏÀ°¿ô¤È¸«¤Ê¤µ¤ì¤ëʸ»úÎó¤«ÆþÎÏʸ»ú¤¬¤Ê¤¤¶õ¤Î¾õÂÖ¤«\
30 ¤Î¾ì¹ç¤À¤±¤ò¼õ¤±ÉÕ¤±¡¤ÌäÂ꤬¤¢¤ë¾ì¹ç¤Ï¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤¬ÅÀÌǤ·¤Þ¤¹\
31 ¡Ê¥Õ¥©¡¼¥«¥¹¤¬µî¤ë»þ¤Ë¥Á¥§¥Ã¥¯¤µ¤ì¤Þ¤¹¡Ë¡¥\
32 Æó¤Ä¤á¤Î¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤Ï¡¤ÆþÎϤµ¤ì¤¿Ê¸»úÎó¤ÎŤµ¤¬\
33 £±£°Ê¸»ṳ́Ëþ¤Î¾ì¹ç¤À¤±¤ò¼õ¤±ÉÕ¤±¡¤À©¸Â¤ò±Û¤¨¤Æ½ñ¤­¹þ¤â¤¦¤È¤·¤¿¤È¤­¤Ë¤Ï\
34 ¥Ù¥ë¤òÌĤ餷¤ÆÃΤ餻¤Þ¤¹¡¥\
35 »°¤Ä¤á¤ÏÊƹñ¤ÎÅÅÏÃÈÖ¹æ¤ò¼õ¤±ÉÕ¤±¤ë¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤Ç¤¹¡¥\
36 ¥¢¥ë¥Õ¥¡¥Ù¥Ã¥È¤Ï¡¤ÅÅÏõ¡¤Î¥À¥¤¥ä¥ë¾å¤ÇÂбþ¤Å¤±¤é¤ì¤Æ¤¤¤ë¿ô»ú¤ËÊÑ´¹¤µ¤ì¤Þ¤¹¡¥\
37 ÉÔŬÀÚ¤Êʸ»ú¤¬ÆþÎϤµ¤ì¤¿¤ê¿ô»ú°Ê³°¤Îʸ»ú¤Î°ÌÃ֤˿ô»ú¤òÆþÎϤ·¤è¤¦¤È¤·¤¿¤ê\
38 ¤·¤¿¾ì¹ç¤Ë¤Ï·Ù¹ð¤Î¥Ù¥ë¤¬ÌĤê¤Þ¤¹¡¥\
39 »Í¤Ä¤á¤Î¥¨¥ó¥È¥ê¥Ü¥Ã¥¯¥¹¤Ï¡¤£¸Ê¸»ú¤Þ¤Ç¤ÎÆþÎϤò¼õ¤±ÉÕ¤±¤ë\
40 ¥Ñ¥¹¥ï¡¼¥É¥Õ¥£¡¼¥ë¥É¤Ç¤¹¡Ê£¸Ê¸»ú°Ê¾å¤ÏÆä˷ٹð¤ò½Ð¤¹¤³¤È¤Ê¤¯Ìµ»ë¤µ¤ì¤Þ¤¹¡Ë¡¥\
41 ÆþÎϤµ¤ì¤¿Ê¸»ú¤Ï¥¢¥¹¥¿¥ê¥¹¥¯µ­¹æ¤ËÃÖ¤­´¹¤¨¤Æɽ¼¨¤µ¤ì¤Þ¤¹¡¥
42 EOL
43
44 TkFrame.new(base_frame){|f|
45   pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
46
47   TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
48                  $entry3_demo.destroy
49                  $entry3_demo = nil
50                }).pack(:side=>:left, :expand=>true)
51
52   TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
53                  showCode 'entry3'
54                }).pack(:side=>:left, :expand=>true)
55 }
56
57 # focusAndFlash --
58 # Error handler for entry widgets that forces the focus onto the
59 # widget and makes the widget flash by exchanging the foreground and
60 # background colours at intervals of 200ms (i.e. at approximately
61 # 2.5Hz).
62 #
63 # Arguments:
64 # widget -      entry widget to flash
65 # fg -          Initial foreground colour
66 # bg -          Initial background colour
67 # count -       Counter to control the number of times flashed
68 def focusAndFlash(widget, fg, bg, count=5)
69   return if count <= 0
70   if fg && !fg.empty? && bg && !bg.empty?
71     TkTimer.new(200, count, 
72                 proc{widget.configure(:foreground=>bg, :background=>fg)}, 
73                 proc{widget.configure(:foreground=>fg, :background=>bg)}
74                 ).start
75   else
76     # TkTimer.new(150, 3){Tk.bell}.start
77     Tk.bell
78     TkTimer.new(200, count, 
79                 proc{widget.configure(:foreground=>'white', 
80                                       :background=>'black')}, 
81                 proc{widget.configure(:foreground=>'black', 
82                                       :background=>'white')}
83                 ).at_end{begin
84                            widget.configure(:foreground=>fg, 
85                                             :background=>bg)
86                          rescue
87                            # ignore
88                          end}.start
89   end
90   widget.focus(true)
91 end
92
93 l1 = TkLabelFrame.new(base_frame, :text=>"À°¿ô¥¨¥ó¥È¥ê")
94 TkEntry.new(l1, :validate=>:focus, 
95             :vcmd=>[
96               proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
97             ]) {|e|
98   fg = e.foreground
99   bg = e.background
100   invalidcommand [proc{|w| focusAndFlash(w, fg, bg)}, '%W']
101   pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
102 }
103
104 l2 = TkLabelFrame.new(base_frame, :text=>"ŤµÀ©ÌóÉÕ¤­¥¨¥ó¥È¥ê")
105 TkEntry.new(l2, :validate=>:key, :invcmd=>proc{Tk.bell}, 
106             :vcmd=>[proc{|s| s.length < 10}, '%P']
107             ).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
108
109 ### PHONE NUMBER ENTRY ###
110 # Note that the source to this is quite a bit longer as the behaviour
111 # demonstrated is a lot more ambitious than with the others.
112
113 # Initial content for the third entry widget
114 entry3content = TkVariable.new("1-(000)-000-0000")
115
116 # Mapping from alphabetic characters to numbers.
117 $phoneNumberMap = {}
118 Hash[*(%w(abc 2 def 3 ghi 4 jkl 5 mno 6 pqrs 7 tuv 8 wxyz 9))].each{|chars, n|
119   chars.split('').each{|c|
120     $phoneNumberMap[c] = n
121     $phoneNumberMap[c.upcase] = n
122   }
123 }
124
125 # phoneSkipLeft --
126 # Skip over fixed characters in a phone-number string when moving left.
127 #
128 # Arguments:
129 # widget -      The entry widget containing the phone-number.
130 def phoneSkipLeft(widget)
131   idx = widget.index('insert')
132   if idx == 8
133     # Skip back two extra characters
134     widget.cursor = idx - 2
135   elsif idx == 7 || idx == 12
136     # Skip back one extra character
137     widget.cursor = idx - 1
138   elsif idx <= 3
139     # Can't move any further
140     Tk.bell
141     Tk.callback_break
142   end
143 end
144
145 # phoneSkipRight --
146 # Skip over fixed characters in a phone-number string when moving right.
147 #
148 # Arguments:
149 # widget -      The entry widget containing the phone-number.
150 # add - Offset to add to index before calculation (used by validation.)
151 def phoneSkipRight(widget, add = 0)
152   idx = widget.index('insert')
153   if (idx + add == 5)
154     # Skip forward two extra characters
155     widget.cursor = idx + 2
156   elsif (idx + add == 6 || idx + add == 10)
157     # Skip forward one extra character
158     widget.cursor = idx + 1
159   elsif (idx + add == 15 && add == 0)
160     # Can't move any further
161     Tk.bell
162     Tk.callback_break
163   end
164 end
165
166 # validatePhoneChange --
167 # Checks that the replacement (mapped to a digit) of the given
168 # character in an entry widget at the given position will leave a
169 # valid phone number in the widget.
170 #
171 # widget - entry widget to validate
172 # vmode -  The widget's validation mode
173 # idx -    The index where replacement is to occur
174 # char -   The character (or string, though that will always be
175 #          refused) to be overwritten at that point.
176
177 def validatePhoneChange(widget, vmode, idx, char)
178   return true if idx == nil
179   Tk.after_idle(proc{widget.configure(:validate=>vmode, 
180                                       :invcmd=>proc{Tk.bell})})
181   if !(idx<3 || idx==6 || idx==7 || idx==11 || idx>15) && char =~ /[0-9A-Za-z]/
182     widget.delete(idx)
183     widget.insert(idx, $phoneNumberMap[char] || char)
184     Tk.after_idle(proc{phoneSkipRight(widget, -1)})
185     # Tk.update(true)  # <- Don't work 'update' inter validation callback.
186                        #    It depends on Tcl/Tk side (tested on Tcl/Tk8.5a1).
187     return true
188   end
189   return false
190 end
191
192
193 l3 = TkLabelFrame.new(base_frame, :text=>"ÊƹñÅÅÏÃÈֹ楨¥ó¥È¥ê")
194 TkEntry.new(l3, :validate=>:key, :invcmd=>proc{Tk.bell}, 
195             :textvariable=>entry3content, 
196             :vcmd=>[
197               proc{|w,v,i,s| validatePhoneChange(w,v,i,s)}, 
198               "%W %v %i %S"
199             ]){|e|
200   # Click to focus goes to the first editable character...
201   bind('FocusIn', proc{|d,w|
202          if d != "NotifyAncestor"
203            w.cursor = 3
204            Tk.after_idle(proc{w.selection_clear})
205          end
206        }, '%d %W')
207   bind('Left',  proc{|w| phoneSkipLeft(w)},  '%W')
208   bind('Right', proc{|w| phoneSkipRight(w)}, '%W')
209   pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
210 }
211
212 l4 = TkLabelFrame.new(base_frame, :text=>"¥Ñ¥¹¥ï¡¼¥É¥¨¥ó¥È¥ê")
213 TkEntry.new(l4, :validate=>:key, :show=>'*', 
214             :vcmd=>[
215               proc{|s| s.length <= 8}, 
216               '%P'
217             ]).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
218
219 TkFrame.new(base_frame){|f|
220   lower
221   TkGrid.configure(l1, l2, :in=>f, :padx=>'3m', :pady=>'1m', :sticky=>:ew)
222   TkGrid.configure(l3, l4, :in=>f, :padx=>'3m', :pady=>'1m', :sticky=>:ew)
223   TkGrid.columnconfigure(f, [0,1], :uniform=>1)
224   pack(:fill=>:both, :expand=>true)
225 }