1 # -*- coding: euc-jp -*-
4 # This demonstration script creates several entry widgets whose
5 # permitted input is constrained in some way. It also shows off a
8 # based on Tcl/Tk8.4.4 widget demos
10 if defined?($entry3_demo) && $entry3_demo
15 $entry3_demo = TkToplevel.new {|w|
16 title("Constrained Entry Demonstration")
21 base_frame = TkFrame.new($entry3_demo).pack(:fill=>:both, :expand=>true)
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 ÆþÎϤµ¤ì¤¿Ê¸»ú¤Ï¥¢¥¹¥¿¥ê¥¹¥¯µ¹æ¤ËÃÖ¤´¹¤¨¤Æɽ¼¨¤µ¤ì¤Þ¤¹¡¥
44 TkFrame.new(base_frame){|f|
45 pack(:side=>:bottom, :fill=>:x, :pady=>'2m')
47 TkButton.new(f, :text=>'ÊĤ¸¤ë', :width=>15, :command=>proc{
50 }).pack(:side=>:left, :expand=>true)
52 TkButton.new(f, :text=>'¥³¡¼¥É»²¾È', :width=>15, :command=>proc{
54 }).pack(:side=>:left, :expand=>true)
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
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)
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)}
76 # TkTimer.new(150, 3){Tk.bell}.start
78 TkTimer.new(200, count,
79 proc{widget.configure(:foreground=>'white',
80 :background=>'black')},
81 proc{widget.configure(:foreground=>'black',
82 :background=>'white')}
84 widget.configure(:foreground=>fg,
93 l1 = TkLabelFrame.new(base_frame, :text=>"À°¿ô¥¨¥ó¥È¥ê")
94 TkEntry.new(l1, :validate=>:focus,
96 proc{|s| s == '' || /^[+-]?\d+$/ =~ s }, '%P'
100 invalidcommand [proc{|w| focusAndFlash(w, fg, bg)}, '%W']
101 pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
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')
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.
113 # Initial content for the third entry widget
114 entry3content = TkVariable.new("1-(000)-000-0000")
116 # Mapping from alphabetic characters to numbers.
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
126 # Skip over fixed characters in a phone-number string when moving left.
129 # widget - The entry widget containing the phone-number.
130 def phoneSkipLeft(widget)
131 idx = widget.index('insert')
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
139 # Can't move any further
146 # Skip over fixed characters in a phone-number string when moving right.
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')
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
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.
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.
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]/
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).
193 l3 = TkLabelFrame.new(base_frame, :text=>"ÊƹñÅÅÏÃÈֹ楨¥ó¥È¥ê")
194 TkEntry.new(l3, :validate=>:key, :invcmd=>proc{Tk.bell},
195 :textvariable=>entry3content,
197 proc{|w,v,i,s| validatePhoneChange(w,v,i,s)},
200 # Click to focus goes to the first editable character...
201 bind('FocusIn', proc{|d,w|
202 if d != "NotifyAncestor"
204 Tk.after_idle(proc{w.selection_clear})
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')
212 l4 = TkLabelFrame.new(base_frame, :text=>"¥Ñ¥¹¥ï¡¼¥É¥¨¥ó¥È¥ê")
213 TkEntry.new(l4, :validate=>:key, :show=>'*',
215 proc{|s| s.length <= 8},
217 ]).pack(:fill=>:x, :expand=>true, :padx=>'1m', :pady=>'1m')
219 TkFrame.new(base_frame){|f|
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)