1# -*- coding: utf-8 -*-
2#
3# Text Search widget demo (called by 'widget')
4#
5
6# textLoadFile --
7# This method below loads a file into a text widget, discarding
8# the previous contents of the widget. Tags for the old widget are
9# not affected, however.
10#
11# Arguments:
12# w -           The window into which to load the file.  Must be a
13#               text widget.
14# file -        The name of the file to load.  Must be readable.
15
16def textLoadFile(w,file)
17  w.delete('1.0', 'end')
18  f = open(file, 'r')
19  while(!f.eof?)
20    w.insert('end', f.read(1000))
21  end
22  f.close
23end
24
25# textSearch --
26# Search for all instances of a given string in a text widget and
27# apply a given tag to each instance found.
28#
29# Arguments:
30# w -           The window in which to search.  Must be a text widget.
31# string -      The string to search for.  The search is done using
32#               exact matching only;  no special characters.
33# tag -         Tag to apply to each instance of a matching string.
34
35def textSearch(w, string, tag)
36  tag.remove('0.0', 'end')
37  return if string == ""
38  cur = '1.0'
39  loop {
40    cur, len = w.search_with_length(string, cur, 'end')
41    break if cur == ""
42    tag.add(cur, "#{cur} + #{len} char")
43    cur = w.index("#{cur} + #{len} char")
44  }
45end
46
47# textToggle --
48# This method is invoked repeatedly to invoke two commands at
49# periodic intervals.  It normally reschedules itself after each
50# execution but if an error occurs (e.g. because the window was
51# deleted) then it doesn't reschedule itself.
52#
53# Arguments:
54# cmd1 -        Command to execute when method is called.
55# sleep1 -      Ms to sleep after executing cmd1 before executing cmd2.
56# cmd2 -        Command to execute in the *next* invocation of this method.
57# sleep2 -      Ms to sleep after executing cmd2 before executing cmd1 again.
58
59def textToggle(cmd1,sleep1,cmd2,sleep2)
60  sleep_list = [sleep2, sleep1]
61  TkAfter.new(proc{sleep = sleep_list.shift; sleep_list.push(sleep); sleep},
62              -1, cmd1, cmd2).start(sleep1)
63end
64
65# toplevel widget が存在すれば削除する
66if defined?($search_demo) && $search_demo
67  $search_demo.destroy
68  $search_demo = nil
69end
70
71# demo 用の toplevel widget を生成
72$search_demo = TkToplevel.new {|w|
73  title("Text Demonstration - Search and Highlight")
74  iconname("search")
75  positionWindow(w)
76}
77
78base_frame = TkFrame.new($search_demo).pack(:fill=>:both, :expand=>true)
79
80# frame 生成
81$search_buttons = TkFrame.new(base_frame) {|frame|
82  TkButton.new(frame) {
83    #text '了解'
84    text '閉じる'
85    command proc{
86      tmppath = $search_demo
87      $search_demo = nil
88      tmppath.destroy
89    }
90  }.pack('side'=>'left', 'expand'=>'yes')
91
92  TkButton.new(frame) {
93    text 'コード参照'
94    command proc{showCode 'search'}
95  }.pack('side'=>'left', 'expand'=>'yes')
96}
97$search_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
98
99# frame 生成
100TkFrame.new(base_frame) {|f|
101  TkLabel.new(f, 'text'=>'ファイル名:',
102              'width'=>13, 'anchor'=>'w').pack('side'=>'left')
103  $search_fileName = TkVariable.new
104  TkEntry.new(f, 'width'=>40,
105              'textvariable'=>$search_fileName) {
106    pack('side'=>'left')
107    bind('Return', proc{textLoadFile($search_text, $search_fileName.value)
108                        $search_string_entry.focus})
109    focus
110  }
111  TkButton.new(f, 'text'=>'読み込み',
112               'command'=>proc{textLoadFile($search_text,
113                                            $search_fileName.value)})\
114  .pack('side'=>'left', 'pady'=>5, 'padx'=>10)
115}.pack('side'=>'top', 'fill'=>'x')
116
117TkFrame.new(base_frame) {|f|
118  TkLabel.new(f, 'text'=>'検索文字列:',
119              'width'=>13, 'anchor'=>'w').pack('side'=>'left')
120  $search_searchString = TkVariable.new
121  $search_string_entry = TkEntry.new(f, 'width'=>40,
122                                     'textvariable'=>$search_searchString) {
123    pack('side'=>'left')
124    bind('Return', proc{textSearch($search_text, $search_searchString.value,
125                                   $search_Tag)})
126  }
127  TkButton.new(f, 'text'=>'反転',
128               'command'=>proc{textSearch($search_text,
129                                          $search_searchString.value,
130                                          $search_Tag)}) {
131    pack('side'=>'left', 'pady'=>5, 'padx'=>10)
132  }
133}.pack('side'=>'top', 'fill'=>'x')
134
135$search_text = TkText.new(base_frame, 'setgrid'=>true) {|t|
136  $search_Tag = TkTextTag.new(t)
137  TkScrollbar.new(base_frame, 'command'=>proc{|*args| t.yview(*args)}) {|sc|
138    t.yscrollcommand(proc{|first,last| sc.set first,last})
139    pack('side'=>'right', 'fill'=>'y')
140  }
141  pack('expand'=>'yes', 'fill'=>'both')
142}
143
144# Set up display styles for text highlighting.
145
146if TkWinfo.depth($search_demo) > 1
147  textToggle(proc{
148               $search_Tag.configure('background'=>'#ce5555',
149                                     'foreground'=>'white')
150             },
151             800,
152             proc{
153               $search_Tag.configure('background'=>'', 'foreground'=>'')
154             },
155             200 )
156else
157  textToggle(proc{
158               $search_Tag.configure('background'=>'black',
159                                     'foreground'=>'white')
160             },
161             800,
162             proc{
163               $search_Tag.configure('background'=>'', 'foreground'=>'')
164             },
165             200 )
166end
167$search_text.insert('1.0', "\
168このウィンドウは検索機構を実現するのにテキスト widget のタグ機能がどの \
169ように使われるのかをデモするものです。まず上のエントリにファイル名を入 \
170れ、<リターン> を押すか「ロード」ボタンを押してください。次にその下の \
171エントリに文字列を入力し、<リターン> を押すか「反転」ボタンを押してく \
172ださい。するとファイル中の、検索文字列と一致する部分に全て \"search_Tag\" \
173というタグがつけられ、タグの表示属性としてその文字列が点滅するように \
174設定されます。\n")
175$search_text.insert('end', "\
176ファイル読み込みのカレントディレクトリは \"#{Dir.pwd}\" です。\
177")
178$search_text.set_insert '0.0'
179
180$search_fileName.value = ''
181$search_searchString.value = ''
182
183$search_text.width = 60
184$search_text.height = 20
185