arcadia 0.1.2.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,101 +1,105 @@
1
- name=editor
2
- label=Editor
3
- frame=0.1
4
- active=yes
5
- require=ext/ae-editor/ae-editor
6
- class=AgMultiEditor
7
-
8
- tabs=0.5c left
9
- # to use tab key set tab-replace-width-space=0
10
- tab-replace-width-space=2
11
-
12
- #tabs
13
- tabs.font=courier 12
14
- freebsd::tabs.font=courier 12
15
- win::tabs.font={Courier New} 9
16
- #tabs.side=bottom
17
- tabs.side=top
18
- # editor
19
- font=courier 12
20
- font.bold=courier 12 bold
21
- freebsd::font=courier 12
22
- freebsd::font.bold=courier 12 bold
23
- win::font={Courier New} 9
24
- win::font.bold={Courier New} 9 bold
25
- #+--------------------------------------------------
26
- #color.background=#000040
27
- #color.foreground=white
28
- #color.insertbackground=#ff8000
29
- #hightlight.keyword.color.foreground=#800000
30
- #hightlight.variable.color.foreground=#f9c6f8
31
- #hightlight.comment.color.foreground=#4aff4a
32
- #hightlight.string.color.foreground=#8080ff
33
- #hightlight.number.color.foreground=red
34
- #hightlight.capitalize.color.foreground=#ffff00
35
- #hightlight.select.color.foreground=yellow
36
- #hightlight.select.color.background=blue
37
- #hightlight.goto.color.foreground=blue
38
- #hightlight.goto.color.background=yellow
39
- #+--------------------------------------------------
40
- #+--------------------------------------------------
41
- color.background=#FFFFFF
42
- color.foreground=#7F7F7F
43
- color.insertbackground=#ff8000
44
- hightlight.keyword.color.foreground=#00007F
45
- hightlight.keyword.style=bold
46
- hightlight.method_name.color.foreground=#007F7F
47
- hightlight.method_name.style=bold
48
- hightlight.class_name.color.foreground=#0000FF
49
- hightlight.class_name.style=bold
50
- hightlight.module_name.color.foreground=#0000FF
51
- hightlight.module_name.style=bold
52
- hightlight.instance_variable.color.foreground=#7F7F7F
53
- hightlight.instance_variable.style=bold
54
- hightlight.comment.color.foreground=#007F00
55
- hightlight.string.color.foreground=#7F007F
56
- hightlight.number.color.foreground=#007F7F
57
- #hightlight.capitalize.color.foreground=#0000FF
58
- hightlight.operator.color.foreground=#000000
59
- hightlight.operator.style=bold
60
- hightlight.sel.color.foreground=black
61
- hightlight.sel.color.background=#68f914
62
- hightlight.sel.borderwidth=1
63
- hightlight.sel.relief=raised
64
- #hightlight.goto.color.foreground=blue
65
- hightlight.selected.color.background=yellow
66
- hightlight.tabs.color.foreground=black
67
- hightlight.tabs.color.background=#b1cfba
68
- hightlight.tabs.borderwidth=1
69
- hightlight.tabs.relief=raised
70
- hightlight.spaces.color.foreground=black
71
- hightlight.spaces.color.background=#d9f42b
72
- hightlight.spaces.borderwidth=1
73
- hightlight.spaces.relief=raised
74
- #+--------------------------------------------------
75
-
76
-
77
- # line number
78
- #line_number_panel.color.background=#6e6e6e
79
- #line_number_panel.color.foreground=white
80
-
81
- line_number_panel.color.background=#e1e1e1
82
- line_number_panel.color.foreground=#333333
83
-
84
-
85
- # tree explorer
86
- explorer_panel.tree.color.background=#ffffff
87
- explorer_panel.tree.color.foreground=white
88
- explorer_panel.tree.font=courier 12
89
- freebsd::explorer_panel.tree.font=courier 12
90
- win::explorer_panel.tree.font={Courier New} 9
91
- explorer_panel.tree.class.color.foreground=#a42019
92
- explorer_panel.tree.class.font=times 10 bold
93
- win::explorer_panel.tree.class.font=times 10 bold
94
- explorer_panel.tree.def.color.foreground=blue
95
- explorer_panel.tree.def.font=times 10
96
- win::explorer_panel.tree.def.font=times 10
97
- explorer_panel.tree.module.color.foreground=#1b691e
98
- explorer_panel.tree.module.font=times 8 bold
99
- win::explorer_panel.tree.module.font={Courier New} 9 bold
100
-
101
- #:::::::::::::::: Editor group ::::::::::::::::::::::<end>
1
+ name=editor
2
+ label=Editor
3
+ frame=0.1
4
+ active=yes
5
+ require=ext/ae-editor/ae-editor
6
+ class=AgMultiEditor
7
+
8
+ tabs=0.5c left
9
+ # to use tab key set tab-replace-width-space=0
10
+ tab-replace-width-space=2
11
+
12
+ #tabs
13
+ tabs.font=courier 12
14
+ freebsd::tabs.font=courier 12
15
+ win::tabs.font={Courier New} 9
16
+ #tabs.side=bottom
17
+ tabs.side=top
18
+
19
+ # editor
20
+ font=courier 12
21
+ font.bold=courier 12 bold
22
+ freebsd::font=courier 12
23
+ freebsd::font.bold=courier 12 bold
24
+ win::font={Courier New} 9
25
+ win::font.bold={Courier New} 9 bold
26
+ #+--------------------------------------------------
27
+ #color.background=#000040
28
+ #color.foreground=white
29
+ #color.insertbackground=#ff8000
30
+ #hightlight.keyword.color.foreground=#800000
31
+ #hightlight.variable.color.foreground=#f9c6f8
32
+ #hightlight.comment.color.foreground=#4aff4a
33
+ #hightlight.string.color.foreground=#8080ff
34
+ #hightlight.number.color.foreground=red
35
+ #hightlight.capitalize.color.foreground=#ffff00
36
+ #hightlight.select.color.foreground=yellow
37
+ #hightlight.select.color.background=blue
38
+ #hightlight.goto.color.foreground=blue
39
+ #hightlight.goto.color.background=yellow
40
+ #+--------------------------------------------------
41
+ #+--------------------------------------------------
42
+ color.background=#FFFFFF
43
+ color.foreground=#7F7F7F
44
+ color.insertbackground=#ff8000
45
+ hightlight.keyword.color.foreground=#00007F
46
+ hightlight.keyword.style=bold
47
+ hightlight.method_name.color.foreground=#007F7F
48
+ hightlight.method_name.style=bold
49
+ hightlight.class_name.color.foreground=#0000FF
50
+ hightlight.class_name.style=bold
51
+ hightlight.module_name.color.foreground=#0000FF
52
+ hightlight.module_name.style=bold
53
+ hightlight.instance_variable.color.foreground=#7F7F7F
54
+ hightlight.instance_variable.style=bold
55
+ hightlight.comment.color.foreground=#007F00
56
+ hightlight.string.color.foreground=#7F007F
57
+ hightlight.number.color.foreground=#007F7F
58
+ #hightlight.capitalize.color.foreground=#0000FF
59
+ hightlight.operator.color.foreground=#000000
60
+ hightlight.operator.style=bold
61
+ hightlight.sel.color.foreground=black
62
+ hightlight.sel.color.background=#68f914
63
+ hightlight.sel.borderwidth=1
64
+ hightlight.sel.relief=raised
65
+ #hightlight.goto.color.foreground=blue
66
+ hightlight.selected.color.background=yellow
67
+ hightlight.tabs.color.foreground=black
68
+ hightlight.tabs.color.background=#b1cfba
69
+ hightlight.tabs.borderwidth=1
70
+ hightlight.tabs.relief=raised
71
+ hightlight.spaces.color.foreground=black
72
+ hightlight.spaces.color.background=#d9f42b
73
+ hightlight.spaces.borderwidth=1
74
+ hightlight.spaces.relief=raised
75
+ #+--------------------------------------------------
76
+
77
+
78
+ # line number
79
+ #line_number_panel.color.background=#6e6e6e
80
+ #line_number_panel.color.foreground=white
81
+
82
+ line_number_panel.color.background=#e1e1e1
83
+ line_number_panel.color.foreground=#333333
84
+
85
+
86
+ # tree explorer
87
+ explorer_panel.tree.color.background=#ffffff
88
+ explorer_panel.tree.color.foreground=white
89
+ #explorer_panel.tabs.side=bottom
90
+ explorer_panel.tabs.side=top
91
+
92
+ explorer_panel.tree.font=courier 12
93
+ freebsd::explorer_panel.tree.font=courier 12
94
+ win::explorer_panel.tree.font={Courier New} 9
95
+ explorer_panel.tree.class.color.foreground=#a42019
96
+ explorer_panel.tree.class.font=times 10 bold
97
+ win::explorer_panel.tree.class.font=times 10 bold
98
+ explorer_panel.tree.def.color.foreground=blue
99
+ explorer_panel.tree.def.font=times 10
100
+ win::explorer_panel.tree.def.font=times 10
101
+ explorer_panel.tree.module.color.foreground=#1b691e
102
+ explorer_panel.tree.module.font=times 8 bold
103
+ win::explorer_panel.tree.module.font={Courier New} 9 bold
104
+
105
+ #:::::::::::::::: Editor group ::::::::::::::::::::::<end>
@@ -1,2229 +1,2287 @@
1
- #
2
- # ae-editor.rb - Arcadia Ruby ide
3
- # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
- #
5
-
6
- require 'tk'
7
- require 'tktext'
8
- require 'base/a-utils'
9
-
10
-
11
- class TreeNode
12
- attr_reader :sons
13
- attr_reader :parent
14
- attr_reader :kind
15
- attr_reader :rif, :label, :helptext
16
- attr_writer :rif, :label, :helptext
17
- def initialize(parent=nil, kind='KClass')
18
- @sons = Array.new
19
- @parent = parent
20
- @kind = kind
21
- if @parent !=nil
22
- @parent.sons << self
23
- end
24
- yield(self) if block_given?
25
- end
26
-
27
- def <=> (other)
28
- self.label.strip <=> other.label.strip
29
- end
30
- end
31
-
32
- class AgEditor
33
- attr_reader :file
34
- attr_reader :page_frame
35
- attr_reader :text, :root
36
- def initialize(_controller, _page_frame)
37
- @controller = _controller
38
- @page_frame = _page_frame
39
- @set_mod = false
40
- @font = @controller.conf('font')
41
- @font_bold = @controller.conf('font.bold')
42
- @font_metrics = TkFont.new(@font).metrics
43
- @font_metrics_bold = TkFont.new(@font_bold).metrics
44
- @highlighting = false
45
- @classbrowsing = false
46
- @find = @controller.get_find
47
- end
48
-
49
- def initialize_tree(_frame)
50
- @classbrowsing = true
51
- @nb = Tk::BWidget::NoteBook.new(_frame){
52
- tabbevelsize 0
53
- internalborderwidth 0
54
- activeforeground 'red'
55
- activebackground 'yellow'
56
- borderwidth 1
57
- side $arcadia['conf']['editor.tabs.side']
58
- font $arcadia['conf']['editor.tabs.font']
59
- pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
60
- }
61
- @nb_tab_exp = @nb.insert('end','exp' ,'text'=>'Source Tree' )
62
- @nb.raise('exp')
63
- _tree_goto = proc{|_self|
64
- _line = _self.selection_get[0]
65
- _index =_line.to_s+'.0'
66
- _hinner_text = @tree_exp.itemcget(_line,'text').strip
67
- _editor_line = @text.get(_index, _index+ ' lineend')
68
- if !_editor_line.include?(_hinner_text)
69
- MsgContract.instance.out_simple(self, "... rebuild tree \n")
70
- if @tree_thread && @tree_thread.alive?
71
- @tree_thread.exit
72
- end
73
- @tree_thread = Thread.new{
74
- build_tree(_line)
75
- Tk.update
76
- }
77
- _line = _self.selection_get[0]
78
- _index =_line.to_s+'.0'
79
- end
80
- @text.see(_index)
81
- @text.tag_remove('selected','1.0','end')
82
- @text.tag_add('selected',_line.to_s+'.0',(_line+1).to_s+'.0')
83
- }
84
- @tree_exp = Tk::BWidget::Tree.new(@nb_tab_exp){
85
- background '#FFFFFF'
86
- relief 'flat'
87
- showlines false
88
- deltay 18
89
- dragenabled true
90
- selectcommand proc{ _tree_goto.call(self) }
91
- place('relwidth' => 1,'relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => 1,'bordermode' => 'inside','width' => '50')
92
- }
93
-
94
- _c_explo = proc{|*args| @tree_exp.yview(*args)}
95
- _s_explo = TkScrollbar.new(@nb_tab_exp){|s|
96
- width 8
97
- command _c_explo
98
- }.pack('side'=>'right', 'fill'=>'y')
99
- @tree_exp.yscrollcommand proc{|first,last| _s_explo.set first,last}
100
- pop_up_menu_tree
101
- end
102
-
103
- def pop_up_menu_tree
104
- @pop_up_tree = TkMenu.new(
105
- :parent=>@tree_exp,
106
- :title => 'Menu tree'
107
- )
108
- @pop_up_tree.insert('end',
109
- :command,
110
- :label=>'Rebuild',
111
- :hidemargin => false,
112
- :command=> proc{build_tree}
113
- )
114
- @tree_exp.bind_append("Button-3",
115
- proc{|x,y|
116
- _x = TkWinfo.pointerx(@tree_exp)
117
- _y = TkWinfo.pointery(@tree_exp)
118
- @pop_up_tree.popup(_x,_y)
119
- },
120
- "%x %y")
121
- end
122
-
123
-
124
- def initialize_text(_frame)
125
- @v_scroll = TkScrollbar.new(_frame,
126
- 'orient'=>'vertical',
127
- 'relief'=>'flat'
128
- ).pack('side' => 'right', 'fill' => 'y')
129
- @text = TkText.new(@fm1.right_frame){|j|
130
- wrap 'none'
131
- relief 'flat'
132
- undo true
133
- insertofftime 200
134
- insertontime 200
135
- insertbackground $arcadia['conf']['editor.color.insertbackground']
136
- background $arcadia['conf']['editor.color.background']
137
- foreground $arcadia['conf']['editor.color.foreground']
138
- insertwidth 3
139
- exportselection true
140
- autoseparators true
141
- padx 0
142
- tabs $arcadia['conf']['editor.tabs']
143
- place(
144
- 'x'=>0,
145
- 'y'=>0,
146
- 'width' => -15,
147
- 'relheight'=>1,
148
- 'relwidth'=>1,
149
- 'bordermode'=>'outside'
150
- )
151
- }
152
- @text.configure('font', @font);
153
-
154
- @text.tag_configure('eval','foreground' => 'yellow', 'background' =>'red','borderwidth'=>1, 'relief'=>'raised')
155
- @text.tag_configure('errline','borderwidth'=>1, 'relief'=>'groove')
156
- @text.tag_configure('debug', 'background' =>'#b9c6d9', 'borderwidth'=>1 ,'relief'=>'raise')
157
- @buffer = text_value
158
- pop_up_menu
159
- end
160
-
161
- def create_temp_file
162
- _file = @file+'~~'
163
- f = File.new(@file+'~~', "w")
164
- begin
165
- if f
166
- f.syswrite(text_value)
167
- end
168
- ensure
169
- f.close unless f.nil?
170
- end
171
- _file
172
- end
173
-
174
- def initialize_text_binding
175
- @v_scroll.command(proc{|*args|
176
- @text.yview *args
177
- })
178
- @text.yscrollcommand(proc{|first,last| @v_scroll.set(first,last)
179
- self.do_line_update()
180
- })
181
- @text.tag_bind('selected', 'Enter', proc{@text.tag_remove('selected','1.0','end')})
182
-
183
- @text.bind("Enter", proc{check_file_last_access_time})
184
- @text.bind("ButtonPress-1", proc{
185
- _code = $arcadia['palette'].give_me_code
186
- @text.insert('insert', _code) if _code
187
- })
188
-
189
- @text.bind("Control-KeyPress"){|e|
190
- case e.keysym
191
- when 'space'
192
- line, col = @text.index('insert').split('.')
193
- _file = create_temp_file
194
- EditorContract.instance.complete_code(self, 'file'=>_file, 'line'=>line.to_s, 'col'=>col.to_s)
195
- when 'z'
196
- _b = @text.index('insert').split('.')[0].to_i
197
- @text.edit_undo
198
- _e = @text.index('insert').split('.')[0].to_i
199
- if @highlighting
200
- for j in _b..._e
201
- rehighlightline(j)
202
- end
203
- end
204
- break
205
- when 'c'
206
- @text.text_copy
207
- break
208
- when 'x'
209
- @text.text_cut
210
- break
211
- when 'v'
212
- _b = @text.index('insert').split('.')[0].to_i
213
- @text.text_paste
214
- _e = @text.index('insert').split('.')[0].to_i
215
- if @highlighting
216
- for j in _b..._e
217
- rehighlightline(j)
218
- end
219
- end
220
- break
221
- end
222
- case e.keysym
223
- when 's'
224
- save
225
- when 'f'
226
- _r = @text.tag_ranges('sel')
227
- if _r.length>0
228
- _text=@text.get(_r[0][0],_r[0][1])
229
- if _text.length > 0
230
- @find.e_what.text(_text)
231
- end
232
- else
233
- end
234
- @find.use(self)
235
- @find.e_what.focus
236
- @find.show
237
- when 'egrave'
238
- @text.insert('insert',"{")
239
- when 'plus'
240
- @text.insert('insert',"}")
241
- end
242
- }
243
-
244
- @text.bind("Control-Shift-KeyPress"){|e|
245
- case e.keysym
246
- when 'I'
247
- _r = @text.tag_ranges('sel')
248
- _row_begin = _r[0][0].split('.')[0].to_i
249
- _row_end = _r[_r.length - 1][1].split('.')[0].to_i
250
- n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
251
- if n_space > 0
252
- suf = "\s"*n_space
253
- else
254
- suf = "\t"
255
- end
256
-
257
- for _row in _row_begin..._row_end
258
- @text.insert(_row.to_s+'.0',suf)
259
- end
260
- when 'U'
261
- _r = @text.tag_ranges('sel')
262
- _row_begin = _r[0][0].split('.')[0].to_i
263
- _row_end = _r[_r.length - 1][1].split('.')[0].to_i
264
- n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
265
- if n_space > 0
266
- suf = "\s"*n_space
267
- else
268
- suf = "\t"
269
- end
270
- _l_suf = suf.length.to_s
271
- for _row in _row_begin..._row_end
272
- if @text.get(_row.to_s+'.0',_row.to_s+'.'+_l_suf) == suf
273
- @text.delete(_row.to_s+'.0',_row.to_s+'.'+_l_suf)
274
- end
275
- end
276
- when 'C'
277
- _r = @text.tag_ranges('sel')
278
- _row_begin = _r[0][0].split('.')[0].to_i
279
- _row_end = _r[_r.length - 1][1].split('.')[0].to_i
280
-
281
- for _row in _row_begin..._row_end
282
- if @text.get(_row.to_s+'.0',_row.to_s+'.1') == "#"
283
- @text.delete(_row.to_s+'.0',_row.to_s+'.1')
284
- else
285
- @text.insert(_row.to_s+'.0',"#")
286
- end
287
- rehighlightline(_row) if @highlighting
288
- end
289
-
290
- end
291
- }
292
-
293
- @text.bind("KeyPress"){|e|
294
- case e.keysym
295
- when 'Return'
296
- when 'BackSpace'
297
- _index = @text.index('insert')
298
- _row, _col = _index.split('.')
299
- rehighlightline(_row.to_i) if @highlighting
300
- when 'Delete'
301
- _index = @text.index('insert')
302
- _row, _col = _index.split('.')
303
- rehighlightline(_row.to_i) if @highlighting
304
- when 'F5'
305
- save
306
- $arcadia['shell'].run(@file.to_s)
307
- when 'F3'
308
- @find.do_find_next
309
- when 'F1'
310
- line, col = @text.index('insert').split('.')
311
- _file = create_temp_file
312
- _x, _y = @controller.xy_insert
313
- EditorContract.instance.doc_code(@controller, 'file'=>_file, 'line'=>line.to_s, 'col'=>col.to_s, 'xdoc'=>_x, 'ydoc'=>_y)
314
- when 'Tab'
315
- n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
316
- _r = @text.tag_ranges('sel')
317
- if _r && _r[0]
318
- _row_begin = _r[0][0].split('.')[0].to_i
319
- _row_end = _r[_r.length - 1][1].split('.')[0].to_i
320
- if n_space > 0
321
- suf = "\s"*n_space
322
- else
323
- suf = "\t"
324
- end
325
- for _row in _row_begin..._row_end
326
- @text.insert(_row.to_s+'.0', suf)
327
- end
328
- break
329
- elsif n_space > 0
330
- @text.insert('insert', "\s"*n_space)
331
- break
332
- end
333
- end
334
- }
335
-
336
- @text.bind("Shift-KeyPress"){|e|
337
- case e.keysym
338
- when 'Tab'
339
- _r = @text.tag_ranges('sel')
340
- if _r && _r[0]
341
- _row_begin = _r[0][0].split('.')[0].to_i
342
- _row_end = _r[_r.length - 1][1].split('.')[0].to_i
343
-
344
- n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
345
- if n_space > 0
346
- suf = "\s"*n_space
347
- else
348
- suf = "\t"
349
- n_space = 1
350
- end
351
- for _row in _row_begin..._row_end
352
- if @text.get(_row.to_s+'.0',_row.to_s+'.'+n_space.to_s) == suf
353
- @text.delete(_row.to_s+'.0',_row.to_s+'.'+n_space.to_s)
354
- end
355
- end
356
- break
357
- end
358
- end
359
- }
360
-
361
- @text.bind("KeyRelease"){|e|
362
- case e.keysym
363
- when 'Control_L','Return', 'Control_V', 'BackSpace', 'Delete'
364
- if modified?
365
- set_modify
366
- else
367
- reset_modify
368
- end
369
- do_line_update
370
- when 'Right','Left','Down', 'Up'
371
- # do nil
372
- else
373
- check_modify
374
- end
375
- case e.keysym
376
- when 'Return'
377
- _index = @text.index('insert')
378
- _row, _col = _index.split('.')
379
- _txt = @text.get((_row.to_i-1).to_s+'.0',_index)
380
- if _txt.length > 0
381
- m = /\s*/.match(_txt)
382
- if m
383
- if (m[0] != "\n")
384
- _sm = m[0]
385
- _sm = _sm.sub(/\n/,"")
386
- @text.insert('insert',_sm)
387
- end
388
- end
389
- end
390
- if _row.to_i + 1 == @text.index('end').split('.')[0].to_i
391
- do_line_update
392
- end
393
- else
394
- if @highlighting && /\w/.match(e.keysym)
395
- rehighlightline(@text.index('insert').split('.')[0].to_i)
396
- end
397
- end
398
- }
399
- end
400
-
401
- def initialize_line_number(_frame)
402
- @text_line_num = TkText.new(_frame){
403
- wrap 'none'
404
- relief 'flat'
405
- undo false
406
- takefocus 0
407
- insertofftime 0
408
- exportselection true
409
- autoseparators true
410
- background $arcadia['conf']['editor.line_number_panel.color.background']
411
- foreground $arcadia['conf']['editor.line_number_panel.color.foreground']
412
- place(
413
- 'x'=>0,
414
- 'y'=>0,
415
- 'relheight'=>1,
416
- 'relwidth'=>1,
417
- 'bordermode'=>'outside'
418
- )
419
- }
420
- delta = @font_metrics_bold[2][1]-@font_metrics[2][1]
421
- @text_line_num.tag_configure('bold_case', 'spacing1'=>delta)
422
- @text_line_num.tag_configure('breakpoint', 'background'=>'red','borderwidth'=>1, 'relief'=>'raised')
423
- @text_line_num.bind("Double-ButtonPress-1", proc{
424
- _index = @text_line_num.index('insert')
425
- _line = @text_line_num.get(_index+' linestart',_index+' lineend').strip
426
- if @controller.breakpoint_lines_on_file(@file).include?(_line)
427
- @text_line_num.tag_remove('breakpoint',_index+' linestart',_index+' lineend')
428
- @controller.breakpoint_del(@file, _line)
429
- else
430
- @text_line_num.tag_add('breakpoint',_index+' linestart',_index+' linestart + 1 chars')
431
- @controller.breakpoint_add(@file, _line)
432
- end
433
- })
434
- @text_line_num.configure('font', @font);
435
- @text_line_num.tag_configure('line_num',
436
- 'foreground' => '#FFFFFF',
437
- 'background' =>'#0000a0',
438
- 'borderwidth'=>2,
439
- 'relief'=>'raised'
440
- )
441
- end
442
-
443
- def initialize_highlight
444
- @highlighting = true
445
- @highlight_zone = Hash.new;
446
- # @highlight_zone_length = 45;
447
- @highlight_zone_length = 8;
448
- @last_line_begin = 0
449
- @last_line_end = 0
450
- @last_zone_begin=0;
451
- @last_zone_end=0;
452
- @is_line_bold = Hash.new
453
- @is_tag_bold = Hash.new
454
-
455
- @keyword = ['__FILE__', 'and', 'def', 'end', 'in', 'or', 'self', 'unless',
456
- '__LINE__', 'begin', 'defined?', 'ensure', 'module', 'redo', 'super', 'until',
457
- 'BEGIN', 'break', 'do', 'false', 'next', 'rescue', 'then', 'when',
458
- 'END', 'case', 'else', 'for', 'nil', 'retry', 'true', 'while',
459
- 'alias', 'class', 'elsif', 'if', 'not', 'return', 'undef', 'yield','require','include']
460
- _re_string = ''
461
- @keyword.each{|word|
462
- if _re_string.length > 0
463
- _re_string << '|'
464
- end
465
- if ['class','module','def'].include?(word)
466
- _re_string << '([\s]*'+word+'[\s])'
467
- else
468
- _re_string << '\b('+word+')([.,+\(\s])'
469
- end
470
- }
471
- @re_keyword = Regexp::new(_re_string)
472
- @re_instance_variable = /([\s]*@)[A-Za-z0-9_]*/
473
- @re_string = /'([\/A-Za-z0-9_@+\-!?=<>\[\]\{\}\(\).\s]*)'|"([\/A-Za-z0-9_@+\-!?=<>\[\]\{\}\(\).\s]*)"/
474
- @re_number = /\d/
475
- @re_operator = /[\(\)\[\]\(\)\{\}.:;,=><|]/
476
- @re_method_name = /(def[\s][\s]*)[A-Za-z0-9_]*/
477
- @re_class_name = /(class[\s][\s]*)[A-Za-z0-9_]*/
478
- @re_module_name = /(module[\s][\s]*)[A-Za-z0-9_]*/
479
- do_tag_configure('keyword')
480
- do_tag_configure('method_name')
481
- do_tag_configure('instance_variable')
482
- do_tag_configure('class_name')
483
- do_tag_configure('module_name')
484
- do_tag_configure('comment')
485
- do_tag_configure('string')
486
- do_tag_configure('number')
487
- do_tag_configure('sel')
488
- do_tag_configure('selected')
489
- do_tag_configure('operator')
490
- do_tag_configure('tabs')
491
- do_tag_configure('spaces')
492
- end
493
-
494
- def do_tag_configure(_name)
495
- h = Hash.new
496
- if $arcadia['conf']['editor.hightlight.'+_name+'.color.foreground']
497
- h['foreground']=$arcadia['conf']['editor.hightlight.'+_name+'.color.foreground']
498
- end
499
- if $arcadia['conf']['editor.hightlight.'+_name+'.color.background']
500
- h['background']=$arcadia['conf']['editor.hightlight.'+_name+'.color.background']
501
- end
502
- if $arcadia['conf']['editor.hightlight.'+_name+'.style']== 'bold'
503
- h['font']=@font_bold
504
- @is_tag_bold[_name]= true
505
- end
506
- if $arcadia['conf']['editor.hightlight.'+_name+'.relief']
507
- h['relief']=$arcadia['conf']['editor.hightlight.'+_name+'.relief']
508
- end
509
- if $arcadia['conf']['editor.hightlight.'+_name+'.borderwidth']
510
- h['borderwidth']=$arcadia['conf']['editor.hightlight.'+_name+'.borderwidth']
511
- end
512
- @text.tag_configure(_name, h)
513
- end
514
-
515
- def pop_up_menu
516
- @pop_up = TkMenu.new(
517
- :parent=>@text,
518
- :tearoff=>1,
519
- :title => 'Menu'
520
- )
521
- @pop_up.insert('end',
522
- :command,
523
- :label=>'Save as',
524
- :hidemargin => false,
525
- :command=> proc{save_as}
526
- )
527
- @pop_up.insert('end',
528
- :command,
529
- :label=>'Save',
530
- :hidemargin => false,
531
- :command=> proc{save}
532
- )
533
-
534
- @pop_up.insert('end',
535
- :command,
536
- :label=>'Close',
537
- :hidemargin => false,
538
- :command=> proc{@controller.close_editor(self)}
539
- )
540
-
541
- @pop_up.insert('end',
542
- :command,
543
- :label=>'Close others',
544
- :hidemargin => false,
545
- :command=> proc{@controller.close_others_editor(self)}
546
- )
547
-
548
- @pop_up.insert('end',
549
- :command,
550
- :label=>'Close all',
551
- :hidemargin => false,
552
- :command=> proc{@controller.close_all_editor(self)}
553
- )
554
-
555
-
556
- @pop_up.insert('end', :separator)
557
-
558
- @pop_up.insert('end',
559
- :command,
560
- :label=>'Color',
561
- :hidemargin => false,
562
- :command=> proc{
563
- @text.insert('insert',Tk.chooseColor)
564
- }
565
- )
566
- @pop_up.insert('end',
567
- :command,
568
- :label=>'Font',
569
- :hidemargin => false,
570
- :command=> proc{
571
- @text.insert('insert', $arcadia['action.get.font'].call)
572
- }
573
- )
574
-
575
- @pop_up.insert('end', :separator)
576
-
577
- @pop_up.insert('end',
578
- :command,
579
- :label=>'Show tabs',
580
- :hidemargin => false,
581
- :command=> proc{show_tabs}
582
- )
583
-
584
-
585
- @pop_up.insert('end',
586
- :command,
587
- :label=>'Hide tabs',
588
- :hidemargin => false,
589
- :command=> proc{hide_tabs}
590
- )
591
-
592
- @pop_up.insert('end',
593
- :command,
594
- :label=>'Show spaces',
595
- :hidemargin => false,
596
- :command=> proc{show_spaces}
597
- )
598
-
599
-
600
- @pop_up.insert('end',
601
- :command,
602
- :label=>'Hide spaces',
603
- :hidemargin => false,
604
- :command=> proc{hide_spaces}
605
- )
606
-
607
-
608
- @pop_up.insert('end',
609
- :command,
610
- :label=>'Space to tabs indentation',
611
- :hidemargin => false,
612
- :command=> proc{indentation_space_2_tabs}
613
- )
614
-
615
- @pop_up.insert('end',
616
- :command,
617
- :label=>'Tabs to space indentation',
618
- :hidemargin => false,
619
- :command=> proc{indentation_tabs_2_space}
620
- )
621
-
622
-
623
- @text.bind("Button-3",
624
- proc{|x,y|
625
- _x = TkWinfo.pointerx(@text)
626
- _y = TkWinfo.pointery(@text)
627
- @pop_up.popup(_x,_y)
628
- },
629
- "%x %y")
630
- end
631
-
632
- def unmark_debug(_index)
633
- @text.tag_remove('debug',_index+' linestart', _index+' lineend')
634
- end
635
-
636
- def mark_debug(_index)
637
- #@text.tag_add('debug',_index +' linestart', _index +' +1 lines linestart')
638
- @text.tag_add('debug',_index +' linestart', _index +' lineend')
639
- end
640
-
641
- def mark_selected(_index)
642
- @text.tag_remove('selected','1.0', 'end')
643
- @text.tag_add('selected',_index +' linestart', _index +' +1 lines linestart')
644
- end
645
-
646
-
647
- def build_tree_from_source(_source)
648
- _row = 1
649
- _liv = 0
650
- _livs = Array.new
651
- root = TreeNode.new(nil, 'KRoot'){|_node|
652
- _node.rif= 'root'
653
- _node.label=''
654
- }
655
- _livs[_liv]=root
656
- _source.each_line{|line|
657
- line = "\s"+line.split("#")[0]+"\s"
658
- m = /[\s\n\t\;]+(module|class|def|if|unless|begin|case|for|while|do)[\s\n\t\;]+/.match(line)
659
- if m
660
- index = m.post_match.strip.length - 1
661
- if m.post_match.strip[index,index]=='{'
662
- _row = _row +1
663
- next
664
- end
665
- _liv>=0? _liv = _liv + 1:_liv=1
666
- _pliv = _liv
667
- _parent = nil
668
- while (_parent == nil && _pliv>=0)
669
- _pliv = _pliv -1
670
- _parent = _livs[_pliv]
671
- end
672
- if _parent
673
- _helptext = m.post_match.strip
674
- _label = _helptext.split('<')[0]
675
- if _label == nil || _label.strip.length==0
676
- _label = _helptext
677
- end
678
- if (m[0].strip[0..4] == "class" && m.pre_match.strip.length==0)
679
- _kind = 'KClass'
680
- elsif (m[0].strip[0..4] == "class" && m.pre_match.strip.length>0)
681
- _row = _row +1
682
- _liv = _liv - 1
683
- next
684
- elsif (m[0].strip[0..5] == "module" && m.pre_match.strip.length==0)
685
- _kind = 'KModule'
686
- elsif (m[0].strip[0..5] == "module" && m.pre_match.strip.length>0)
687
- _row = _row +1
688
- _liv = _liv - 1
689
- next
690
- elsif ((m[0].strip[0..4] == "begin")||(m[0].strip[0..3] == "case") ||(m[0].strip[0..4] == "while") || (m[0].strip[0..2] == "for") || (m[0].strip[0..1] == "do") || ((m[0].strip[0..1] == "if" || m[0].strip[0..5] == "unless") && m.pre_match.strip.length==0))
691
- _row = _row +1
692
- next
693
- elsif ((m[0].strip[0..1] == "if" || m[0].strip[0..5] == "unless") && m.pre_match.strip.length>0)
694
- _row = _row +1
695
- _liv = _liv - 1
696
- next
697
- elsif (m[0].strip[0..2] == "def" && m.pre_match.strip.length==0)
698
- _kind = 'KDef'
699
- if _label.include?(_parent.label + '.')
700
- _kind = 'KDefClass'
701
- end
702
- # elsif (m[0].strip[0..10] == "attr_reader" && m.pre_match.strip.length==0)
703
- # _kind = 'KAttr_reader'
704
- # _liv = _liv - 1
705
- # _row = _row +1
706
- end
707
-
708
- TreeNode.new(_parent, _kind){|_node|
709
- _node.label = _label
710
- _node.helptext = _helptext
711
- _node.rif = _row.to_s
712
- _livs[_pliv + 1]=_node
713
- }
714
- else
715
- _row = _row +1
716
- _liv = _liv - 1
717
- next
718
- end
719
- end
720
- m_end = /[\s\n\t\;]+end[\s\n\t\;]+/.match(line)
721
- if m_end
722
- _liv = _liv - 1
723
- end
724
- _row = _row +1
725
- }
726
- return root
727
- end
728
-
729
- def build_tree_from_node(_node, _label_match=nil)
730
-
731
- @image_kclass = TkPhotoImage.new('dat' => TREE_NODE_CLASS_GIF)
732
- @image_kmodule = TkPhotoImage.new('dat' => TREE_NODE_MODULE_GIF)
733
- @image_kdef = TkPhotoImage.new('dat' => TREE_NODE_DEF_GIF)
734
- @image_kdefclass = TkPhotoImage.new('dat' => TREE_NODE_DEFCLASS_GIF)
735
-
736
- _sorted_sons = _node.sons.sort
737
- for inode in 0.._sorted_sons.length - 1
738
- _son = _sorted_sons[inode]
739
- if _son.kind == 'KClass'
740
- _image = @image_kclass
741
- elsif _son.kind == 'KModule'
742
- _image = @image_kmodule
743
- elsif _son.kind == 'KDef'
744
- _image = @image_kdef
745
- elsif _son.kind == 'KDefClass'
746
- _image = @image_kdefclass
747
- end
748
- @tree_exp.insert('end', _son.parent.rif ,_son.rif, {
749
- 'text' => _son.label ,
750
- 'helptext' => _son.helptext,
751
- 'font'=>$arcadia['conf']['editor.explorer_panel.tree.font'],
752
- 'image'=> _image
753
- }
754
- )
755
- if (_label_match) && (_label_match.strip == _son.label.strip)
756
- @selected = _son
757
- end
758
- build_tree_from_node(_son, _label_match)
759
- end
760
- end
761
-
762
- def build_tree(_sel=nil)
763
- if _sel
764
- _label_sel = @tree_exp.itemcget(_sel,'text')
765
- end
766
-
767
- #clear tree
768
- begin
769
- @tree_exp.delete(@tree_exp.nodes('root'))
770
- rescue Exception
771
- # workaround on windows
772
- @tree_exp.delete(@tree_exp.nodes('root'))
773
- end
774
-
775
-
776
- #(re)build tree
777
- _txt = @text.get('1.0','end')
778
- @root = build_tree_from_source(_txt)
779
- @selected = nil
780
- build_tree_from_node(@root, _label_sel)
781
- if @selected
782
- @tree_exp.selection_add(@selected.rif)
783
- @tree_exp.open_tree(@selected.parent.rif)
784
- @tree_exp.see(@selected.rif)
785
- end
786
- end
787
-
788
- def insert_popup_menu_item(_where, *args)
789
- @pop_up.insert(_where,*args)
790
- end
791
-
792
- def text_value
793
- return @text.value
794
- end
795
-
796
- # vertical scrollbar : ON/OFF
797
- def vscroll(mode)
798
- st = TkGrid.info(@v_scroll)
799
- if mode && st == [] then
800
- @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns')
801
- elsif !mode && st != [] then
802
- @v_scroll.ungrid
803
- end
804
- self
805
- end
806
-
807
- # horizontal scrollbar : ON/OFF
808
- def hscroll(mode, wrap_mode="char")
809
- st = TkGrid.info(@h_scroll)
810
- if mode && st == [] then
811
- @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew')
812
- @text.configure('wrap'=> 'none')
813
- elsif !mode && st != [] then
814
- @h_scroll.ungrid
815
- @text.configure('wrap'=> wrap_mode)
816
- end
817
- self
818
- end
819
-
820
- def rowcol(_index, _gap_row = nil, _gap_col = nil)
821
- _riga, _colonna = _index.split('.')
822
- if _gap_row == nil
823
- _riga = '1'
824
- _gap_row = 0
825
- end
826
- if _gap_col == nil
827
- _colonna = '0'
828
- _gap_col = 0
829
- end
830
- return (_riga.to_i + _gap_row).to_s + '.'+ (_colonna.to_i + _gap_col).to_s
831
- end
832
-
833
- def find_and_set_tag(_re, _row, _txt, _tag, _tag_rem = nil)
834
- m = _re.match(_txt)
835
- _end = 0
836
- if m && @is_tag_bold[_tag]
837
- @is_line_bold[_row]=true
838
- end
839
- while m
840
- _txt = m.post_match
841
- _ibegin = _row.to_s+'.'+(m.begin(0)+_end).to_s
842
- _end = m.end(0) + _end
843
- _iend = _row.to_s+'.'+(_end.to_s)
844
- if _tag_rem
845
- _tag_rem.each {|value|
846
- @text.tag_remove(value,_ibegin, _iend)
847
- }
848
- end
849
- @text.tag_add(_tag,_ibegin, _iend)
850
- m = _re.match(_txt)
851
- end
852
- end
853
-
854
- def show_spaces
855
- @spaces_show = true
856
- _row = 1
857
- @text.value.each{|_line|
858
- show_chars_line(_row, _line, /[ ^\t]\s*/, 'spaces')
859
- _row = _row+1
860
- }
861
- end
862
-
863
-
864
- def show_tabs
865
- @tabs_show = true
866
- _row = 1
867
- @text.value.each{|_line|
868
- show_chars_line(_row, _line, /\t/, 'tabs')
869
- _row = _row+1
870
- }
871
- end
872
-
873
-
874
- def show_chars_line(_row, _line, _re, _tag)
875
- m = _re.match(_line)
876
- _end = 0
877
- while m
878
- _txt = m.post_match
879
- _ibegin = _row.to_s+'.'+(m.begin(0)+_end).to_s
880
- _end = m.end(0) + _end
881
- _iend = _row.to_s+'.'+(_end.to_s)
882
- @text.tag_add(_tag,_ibegin, _iend)
883
- m = _re.match(_txt)
884
- end
885
- end
886
-
887
- def indentation_space_2_tabs(_n_space=2)
888
- _row = 1
889
- @text.value.each{|_line|
890
- m = /\s*/.match(_line)
891
- _end = 0
892
- if m && m.begin(0)==0
893
- _s = m[0]
894
- if !_s.include?("\n") && !_s.include?("\t")
895
- _ibegin = _row.to_s+'.0'
896
- _iend = _row.to_s+'.'+m.end(0).to_s
897
- _n_tab = (_s.length / _n_space).round
898
- @text.delete(_ibegin, _iend)
899
- @text.insert(_ibegin,"\t"*_n_tab )
900
- end
901
- end
902
- _row = _row+1
903
- }
904
- check_modify
905
- end
906
-
907
- def indentation_tabs_2_space(_n_space=2)
908
- _row = 1
909
- @text.value.each{|_line|
910
- m = /\t*/.match(_line)
911
- _end = 0
912
- if m && m.begin(0)==0
913
- _s = m[0]
914
- if !_s.include?("\n")
915
- _ibegin = _row.to_s+'.0'
916
- _iend = _row.to_s+'.'+m.end(0).to_s
917
- @text.delete(_ibegin, _iend)
918
- @text.insert(_ibegin,"\s"*_s.length*_n_space )
919
- end
920
- end
921
- _row = _row+1
922
- }
923
- check_modify
924
- end
925
-
926
-
927
- def hide_tabs
928
- @text.tag_remove('tabs','1.0', 'end')
929
- @tabs_show = false
930
- end
931
-
932
- def hide_spaces
933
- @text.tag_remove('spaces','1.0', 'end')
934
- @spaces_show = false
935
- end
936
-
937
-
938
- def modified?
939
- return !(@buffer === text_value)
940
- end
941
-
942
- def set_modify
943
- if !@set_mod
944
- @set_mod = true
945
- @controller.change_tab_set_modify(@page_frame)
946
- end
947
- end
948
-
949
- def reset_modify
950
- @controller.change_tab_reset_modify(@page_frame)
951
- @set_mod = false
952
- @file_last_access_time = File.mtime(@file) if @file
953
- end
954
-
955
- def highlightline(_row, _line, _check_mod = false)
956
- if _check_mod
957
- check_modify
958
- end
959
- _txt = _line
960
- _end = 0
961
-
962
- #if line is a comment
963
- m_c = /#/.match(_txt)
964
- if m_c then
965
- _ibegin = _row.to_s+'.'+(m_c.begin(0)).to_s
966
- _iend = _row.to_s+'.'+(_line.length - 1).to_s
967
- @text.tag_add('comment',_ibegin, _iend)
968
- _txt = m_c.pre_match
969
- end
970
- arem = Array.new
971
- if _txt.strip.length > 0
972
- find_and_set_tag(@re_number, _row, _txt, 'number')
973
- arem << 'number'
974
- find_and_set_tag(@re_method_name, _row, _txt, 'method_name',arem)
975
- arem << 'method_name'
976
- find_and_set_tag(@re_class_name, _row, _txt, 'class_name',arem)
977
- arem << 'class_name'
978
- find_and_set_tag(@re_module_name, _row, _txt, 'module_name',arem)
979
- arem << 'module_name'
980
- find_and_set_tag(@re_keyword, _row, _txt, 'keyword',arem)
981
- arem << 'keyword'
982
- find_and_set_tag(@re_instance_variable, _row, _txt, 'instance_variable',arem)
983
- arem << 'instance_variable'
984
- find_and_set_tag(@re_operator, _row, _txt, 'operator')
985
- arem << 'operator'
986
- find_and_set_tag(@re_string, _row, _txt, 'string', arem)
987
- end
988
- find_and_set_tag(/\t/, _row, _txt, 'tabs', arem) if @tabs_show
989
- find_and_set_tag(/[ ^\t]\s*/, _row, _txt, 'spaces', arem) if @spaces_show
990
- end
991
-
992
- def rehighlightline(_row)
993
- _ibegin = _row.to_s+'.0'
994
- _iend = (_row+1).to_s+'.0'
995
- @text.tag_remove('keyword',_ibegin, _iend)
996
- @text.tag_remove('comment',_ibegin, _iend)
997
- @text.tag_remove('string',_ibegin, _iend)
998
- @text.tag_remove('number',_ibegin, _iend)
999
- @text.tag_remove('operator',_ibegin, _iend)
1000
- @text.tag_remove('capitalize',_ibegin, _iend)
1001
- _line = @text.get(_ibegin, _iend)
1002
- highlightline(_row, _line)
1003
- end
1004
-
1005
- def row(_index='insert')
1006
- _row = @text.index(_index).split('.')[0].to_i
1007
- print "def row(_index='insert')",_row.to_s,"\n"
1008
- return _row
1009
- end
1010
-
1011
- def do_line_update
1012
- #renum in @text_line_num the portion of visibled screen of @text
1013
- if @text_line_num
1014
- incr = 1 + (@font_metrics[2][1]+@font_metrics_bold[2][1]) / 4
1015
- line_begin = @text.index('@0,0').split('.')[0].to_i
1016
- line_end = @text.index('@0,'+TkWinfo.height(@text).to_s).split('.')[0].to_i + 1
1017
- # breakpoint
1018
- b = @controller.breakpoint_lines_on_file(@file)
1019
- @text_line_num.delete('1.0','end')
1020
- for j in line_begin...line_end
1021
- nline = j.to_s.rjust(6)
1022
- _index = @text_line_num.index('end')
1023
- if @hightliting && @is_line_bold[j]
1024
- @text_line_num.insert('end', nline+"\n",'bold_case')
1025
- else
1026
- @text_line_num.insert('end', nline+"\n")
1027
- end
1028
- if b.include?(j.to_s)
1029
- @text_line_num.tag_add('breakpoint',_index+' -1 lines',_index+' -1 lines + 1 chars')
1030
- end
1031
- end
1032
-
1033
- if @highlighting
1034
- _zone_begin = ((line_begin) / @highlight_zone_length).to_i + 1
1035
- _zone_end = ((line_end) / @highlight_zone_length).to_i + 1
1036
-
1037
- (_zone_begin >=@last_zone_begin)?_zone_begin.upto(_zone_end+1){|_zone|
1038
- highlight_zone(_zone)
1039
- }:_zone_end.downto(_zone_begin-1){|_zone|
1040
- highlight_zone(_zone)
1041
- }
1042
- @last_line_begin = line_begin
1043
- @last_line_end = line_end
1044
- @last_zone_begin = _zone_begin
1045
- @last_zone_end = _zone_end
1046
- end
1047
- end
1048
- end
1049
-
1050
- def highlight_zone(_zone)
1051
- if !@highlight_zone[_zone]
1052
- _b = @highlight_zone_length*(_zone - 1)
1053
- _e = @highlight_zone_length*(_zone) + 1
1054
- for j in _b..._e
1055
- rehighlightline(j)
1056
- end
1057
- @highlight_zone[_zone] = true
1058
- end
1059
- end
1060
-
1061
- def text_see(_index=nil)
1062
- if _index
1063
- @text.see(_index)
1064
- end
1065
- end
1066
-
1067
- def text_insert_index
1068
- @text.index('insert')
1069
- end
1070
-
1071
- def text_insert(index, chars, *tags, &b)
1072
- if block_given?
1073
- instance_eval(&b)
1074
- end
1075
- _index = @text.index(index)
1076
- _row, _col = _index.split('.')
1077
- _row = (_row.to_i - 1).to_s
1078
- chars.each_line {|line|
1079
- @text.insert(_row+'.0', line, *tags)
1080
- if !defined?(m_begin)||(m_begin == nil)
1081
- m_begin = /=begin/.match(line)
1082
- end
1083
- if @highlighting
1084
- if m_begin &&(m_begin.begin(0)==0)
1085
- _ibegin = _row+'.0'
1086
- _iend = _row+'.'+(line.length - 1).to_s
1087
- @text.tag_add('comment',_ibegin, _iend)
1088
- else
1089
- highlightline(_row.to_i, line, false)
1090
- end
1091
- end
1092
- _row = (_row.to_i + 1).to_s
1093
- }
1094
- if defined?(_edit_reset)
1095
- if _edit_reset
1096
- @text.edit_reset
1097
- end
1098
- else
1099
- @text.edit_reset
1100
- end
1101
- end
1102
-
1103
- def save
1104
- if !@file
1105
- save_as
1106
- else
1107
- f = File.new(@file, "w")
1108
- begin
1109
- if f
1110
- f.syswrite(text_value)
1111
- @buffer = text_value
1112
- reset_modify
1113
- end
1114
- ensure
1115
- f.close unless f.nil?
1116
- end
1117
- EditorContract.instance.file_saved(self,'file' =>@file)
1118
- end
1119
- end
1120
-
1121
- def save_as
1122
- @file = Tk.getSaveFile("filetypes"=>[["Ruby Files", [".rb", ".rbw"]]])
1123
- @file = nil if @file == "" # cancelled
1124
- if @file
1125
- save
1126
- @controller.change_file_name(@page_frame, @file)
1127
- EditorContract.instance.file_created(self, 'file'=>@file)
1128
- end
1129
- end
1130
-
1131
- def check_modify
1132
- if modified? && !@set_mod
1133
- set_modify
1134
- else
1135
- reset_modify
1136
- end
1137
- end
1138
-
1139
- def check_file_last_access_time
1140
- if @file && @file_last_access_time
1141
-
1142
- ftime = File.mtime(@file)
1143
- if @file_last_access_time != ftime
1144
- msg = 'File "'+@file+'" is changed! Reload?'
1145
- if Tk.messageBox('icon' => 'error', 'type' => 'yesno',
1146
- 'title' => '(Arcadia) Libs', 'parent' => @text,
1147
- 'message' => msg) == 'yes'
1148
- @text.delete('1.0','end')
1149
- load_file(@file)
1150
- else
1151
- @file_last_access_time = ftime
1152
- end
1153
- end
1154
- end
1155
- end
1156
-
1157
- def init_editing(_ext='rb')
1158
- case _ext
1159
- when 'rb'
1160
- @fm = AGTkVSplittedFrames.new(@page_frame,150)
1161
- @fm1 = AGTkVSplittedFrames.new(@fm.right_frame,60)
1162
- initialize_text(@fm1.right_frame)
1163
- initialize_text_binding
1164
- initialize_highlight
1165
- initialize_line_number(@fm1.left_frame)
1166
- initialize_tree(@fm.left_frame)
1167
- when nil
1168
- @fm1 = AGTkVSplittedFrames.new(@page_frame,60)
1169
- initialize_text(@fm1.right_frame)
1170
- initialize_text_binding
1171
- initialize_highlight
1172
- initialize_line_number(@fm1.left_frame)
1173
- else
1174
- @fm1 = AGTkVSplittedFrames.new(@page_frame,60)
1175
- initialize_text(@fm1.right_frame)
1176
- initialize_text_binding
1177
- initialize_line_number(@fm1.left_frame)
1178
- end
1179
- end
1180
-
1181
- def file_extension(_filename=nil)
1182
- if _filename
1183
- _m = /(.*\.)(.*$)/.match(File.basename(_filename))
1184
- end
1185
- _ret = (_m && _m.length > 1)?_m[2]: nil
1186
- end
1187
-
1188
- def load_file(_filename = nil)
1189
- #if filename is nil then open a new tab
1190
- @file = _filename
1191
- if _filename
1192
- #init_editing(file_extension(_filename))
1193
- File::open(_filename,'r'){ |file|
1194
- @text.insert('end',file.readlines.collect!{| line | line.chomp+"\n" }.to_s)
1195
- }
1196
- end
1197
- reset
1198
- refresh
1199
- end
1200
-
1201
- def reset
1202
- @buffer = text_value
1203
- reset_modify
1204
- @text.edit_reset
1205
- end
1206
-
1207
- def refresh
1208
- build_tree if @classbrowsing
1209
- end
1210
- end
1211
-
1212
- class AgMultiEditorView
1213
- attr_reader :enb
1214
- def initialize(parent=nil)
1215
- @enb = Tk::BWidget::NoteBook.new(parent){
1216
- tabbevelsize 0
1217
- internalborderwidth 2
1218
- activeforeground 'red'
1219
- activebackground 'yellow'
1220
- #background 'black'
1221
- borderwidth 1
1222
- side $arcadia['conf']['editor.tabs.side']
1223
- font $arcadia['conf']['editor.tabs.font']
1224
- pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
1225
- }
1226
- end
1227
-
1228
- end
1229
-
1230
- class AgMultiEditor < ArcadiaExt
1231
- attr_reader :breakpoints
1232
- attr_reader :splitted_frame
1233
- def before_build
1234
- ArcadiaContractListener.new(self, DebugContract, :do_debug_event)
1235
- ArcadiaContractListener.new(self, EditorContract, :do_editor_event)
1236
- ArcadiaContractListener.new(self, MainContract, :do_main_event)
1237
- end
1238
-
1239
- def build
1240
- if @arcadia.layout.headed?
1241
- title_frame = @arcadia.layout.domain(conf('frame'))['root']
1242
- #@close_button = title_frame.add_button(nil,nil,TAB_CLOSE_GIF,'left')
1243
- end
1244
-
1245
- #@splitted_frame = AGTkOSplittedFrames.new(self.frame,20)
1246
- #@main_frame = AgMultiEditorView.new(@splitted_frame.bottom_frame)
1247
- @main_frame = AgMultiEditorView.new(self.frame)
1248
- #@close_button.bind('1',proc{close_raised})
1249
- @tabs_file =Hash.new
1250
- @tabs_editor =Hash.new
1251
- @breakpoints =Array.new
1252
- create_find
1253
- pop_up_menu
1254
- end
1255
-
1256
- def after_build
1257
- self.open_last_files
1258
- end
1259
-
1260
- def pop_up_menu
1261
- @pop_up = TkMenu.new(
1262
- :parent=>@main_frame.enb,
1263
- :tearoff=>0,
1264
- :title => 'Menu'
1265
- )
1266
- @pop_up.insert('end',
1267
- :command,
1268
- :label=>'...',
1269
- :state=>'disabled',
1270
- :background=>'blue',
1271
- :font => conf('font.bold'),
1272
- :hidemargin => true
1273
- )
1274
- @c = @pop_up.insert('end',
1275
- :command,
1276
- :label=>'Close',
1277
- :font => conf('font'),
1278
- :hidemargin => false,
1279
- :command=> proc{
1280
- if @selected_tab_name_from_popup != nil
1281
- _e = @tabs_editor[@selected_tab_name_from_popup]
1282
- self.close_editor(_e)
1283
- end
1284
- }
1285
- )
1286
- @c = @pop_up.insert('end',
1287
- :command,
1288
- :label=>'Close others',
1289
- :font => conf('font'),
1290
- :hidemargin => false,
1291
- :command=> proc{
1292
- if @selected_tab_name_from_popup != nil
1293
- _e = @tabs_editor[@selected_tab_name_from_popup]
1294
- self.close_others_editor(_e)
1295
- end
1296
- }
1297
- )
1298
- @c = @pop_up.insert('end',
1299
- :command,
1300
- :label=>'Close all',
1301
- :font => conf('font'),
1302
- :hidemargin => false,
1303
- :command=> proc{
1304
- if @selected_tab_name_from_popup != nil
1305
- _e = @tabs_editor[@selected_tab_name_from_popup]
1306
- self.close_all_editor(_e)
1307
- end
1308
- }
1309
- )
1310
-
1311
- @main_frame.enb.tabbind("Button-3",
1312
- proc{|*x|
1313
- _x = TkWinfo.pointerx(@main_frame.enb)
1314
- _y = TkWinfo.pointery(@main_frame.enb)
1315
- @selected_tab_name_from_popup = x[0].split(':')[0]
1316
- _index = @main_frame.enb.index(@selected_tab_name_from_popup)
1317
- if _index == -1
1318
- @selected_tab_name_from_popup = 'ff'+@selected_tab_name_from_popup
1319
- _index = @main_frame.enb.index(@selected_tab_name_from_popup)
1320
- end
1321
- if _index != -1
1322
- _file = @main_frame.enb.itemcget(@selected_tab_name_from_popup, 'text')
1323
- @pop_up.entryconfigure(0, 'label'=>_file)
1324
- @pop_up.popup(_x,_y)
1325
- end
1326
- })
1327
- end
1328
-
1329
-
1330
- def do_debug_event(_event)
1331
- #@arcadia.outln('_sender ----> '+_sender.to_s)
1332
- #@arcadia.outln('_event.signature ----> '+_event.signature)
1333
- case _event.signature
1334
- when DebugContract::DEBUG_BEGIN
1335
- self.debug_begin
1336
- when DebugContract::DEBUG_END
1337
- self.debug_end
1338
- when DebugContract::DEBUG_STEP
1339
- if _event.context.file
1340
- self.open_file_in_debug(_event.context.file, _event.context.line)
1341
- end
1342
- end
1343
- end
1344
-
1345
- def do_editor_event(_event)
1346
- case _event.signature
1347
- when EditorContract::OPEN_FILE
1348
- if _event.context.file
1349
- if _event.context.line
1350
- _index = _event.context.line.to_s+'.0'
1351
- end
1352
- self.open_file(_event.context.file, _index)
1353
- _event.handled(self)
1354
- end
1355
- when EditorContract::CLOSE_FILE
1356
- if _event.context.file
1357
- self.close_file(_event.context.file)
1358
- _event.handled(self)
1359
- end
1360
- when EditorContract::SAVE_FILE_RAISED
1361
- self.raised.save
1362
- _event.handled(self)
1363
- when EditorContract::SAVE_FILE
1364
- if _event.context.file
1365
- self.save_file(_event.context.file)
1366
- _event.handled(self)
1367
- end
1368
- when EditorContract::SAVE_AS_FILE_RAISED
1369
- self.raised.save_as
1370
- _event.handled(self)
1371
- when EditorContract::SAVE_AS_FILE
1372
- if _event.context.file
1373
- self.save_as_file(_event.context.file)
1374
- _event.handled(self)
1375
- end
1376
- when EditorContract::OPEN_TEXT
1377
- if _event.context.title
1378
- _tab_name = self.tab_name(_event.context.title)
1379
- self.open_buffer(_tab_name, _event.context.title)
1380
- _e = @tabs_editor[_tab_name]
1381
- _e.text_insert('end',_event.context.text) if _event.context.text
1382
- _e.reset
1383
- _e.refresh
1384
- add_reverse_item(_e)
1385
- _event.handled(self)
1386
- end
1387
- when EditorContract::SHOW_SEARCH_DIALOG
1388
- @find.show
1389
- when EditorContract::SHOW_GOTO_LINE_DIALOG
1390
- @find.show_go_to_line_dialog
1391
- end
1392
- end
1393
-
1394
- def xy_insert
1395
- _text = self.raised.text
1396
- _index_now = _text.index('insert')
1397
- _rx, _ry, _widht, _heigth = _text.bbox(_index_now);
1398
- _x = _rx + TkWinfo.rootx(_text)
1399
- _y = _ry + TkWinfo.rooty(_text) + TkFont.new(conf('font')).metrics[2][1]
1400
- _xroot = _x - TkWinfo.rootx(@arcadia.layout.root)
1401
- _yroot = _y - TkWinfo.rooty(@arcadia.layout.root)
1402
- return _xroot, _yroot
1403
- end
1404
-
1405
-
1406
-
1407
- def raise_complete_code(_context)
1408
- # delete the file used for completion
1409
- if File.exist?(_context.file) && _context.file.include?('~~')
1410
- File.delete(_context.file)
1411
- end
1412
- @raised_listbox.destroy if @raised_listbox != nil
1413
-
1414
- _text = self.raised.text
1415
- _index_call = _context.line+'.'+_context.col
1416
- _index_now = _text.index('insert')
1417
- if _index_call == _index_now
1418
- _target = _text.get('insert - 1 chars wordstart','insert')
1419
- if _target.length > 0 && _target != '.'
1420
- extra_len = _target.length.+@
1421
- _begin_index = _index_now<<' - '<<extra_len.to_s<<' chars'
1422
- _text.tag_add('sel', _begin_index, _index_now)
1423
- else
1424
- _begin_index = _index_now
1425
- extra_len = 0
1426
- end
1427
- if _context.candidates.length > 1
1428
- _rx, _ry, _widht, heigth = _text.bbox(_begin_index);
1429
- _x = _rx + TkWinfo.rootx(_text)
1430
- _y = _ry + TkWinfo.rooty(_text) + TkFont.new(conf('font')).metrics[2][1]
1431
-
1432
- _xroot = _x - TkWinfo.rootx(@arcadia.layout.root)
1433
- _yroot = _y - TkWinfo.rooty(@arcadia.layout.root)
1434
-
1435
- _max_height = TkWinfo.screenheight(@arcadia.layout.root) - _y - 5
1436
-
1437
- @raised_listbox = TkListbox.new(@arcadia.layout.root,
1438
- 'takefocus'=>true,
1439
- :background=>conf('color.background'),
1440
- :foreground=>conf('color.foreground'),
1441
- :selectbackground=>'yellow',
1442
- :selectforeground=>'red',
1443
- :activestyle=>'none',
1444
- :font => conf('font'),
1445
- :borderwidth=>1
1446
- )
1447
- _font = TkFont.new(conf('font'))
1448
- _char_height = _font.metrics[2][1]
1449
- _width = 0
1450
- _docs_entries = Hash.new
1451
- _context.candidates.each{|value|
1452
- _key, _doc = value.split
1453
- _docs_entries[_key]= _doc
1454
- @raised_listbox.insert('end', _key)
1455
- _temp_width = _font.measure(_key) + _font.measure('X')
1456
- _width = _temp_width if _temp_width > _width
1457
- }
1458
- _height = (_context.candidates.length+1)*_char_height
1459
- _height = _max_height if _height > _max_height
1460
- @raised_listbox.place('x'=>_xroot,'y'=>_yroot, 'width'=>_width, 'height'=>_height)
1461
-
1462
- @raised_listbox.focus
1463
- @raised_listbox.bind_append('KeyPress'){|e|
1464
- case e.keysym
1465
- when 'Escape'
1466
- @raised_listbox.destroy
1467
- #_menu.destroy
1468
- Tk.callback_break
1469
- when 'Return'
1470
- _value = @raised_listbox.get('active')
1471
- _text.delete(_begin_index,'insert')
1472
- _text.insert('insert',_value)
1473
- @raised_listbox.destroy
1474
- #_menu.destroy
1475
- Tk.callback_break
1476
- when 'F1'
1477
- _key = @raised_listbox.get('active')
1478
- _x, _y = xy_insert
1479
- EditorContract.instance.doc_code(self, 'doc_entry'=>_docs_entries[_key], 'xdoc'=>_x, 'ydoc'=>_y)
1480
- end
1481
- }
1482
- elsif _context.candidates.length == 1 && _context.candidates[0].length>0
1483
- _text.delete(_begin_index,'insert');
1484
- _text.insert('insert',_context.candidates[0].split[0])
1485
- end
1486
- end
1487
- end
1488
-
1489
- def do_main_event(_event)
1490
- case _event.signature
1491
- when MainContract::EVENT_HANDLED
1492
- _cause = _event.context.caused_by
1493
- if _cause.signature == EditorContract::COMPLETE_CODE &&
1494
- _cause.context.sender == self.raised
1495
- raise_complete_code(_cause.context)
1496
- elsif _cause.signature == EditorContract::DOC_CODE && _cause.context.file != nil
1497
- # delete the file used for completion
1498
- if File.exist?(_cause.context.file) && _cause.context.file.include?('~~')
1499
- File.delete(_cause.context.file)
1500
- end
1501
- end
1502
- end
1503
- end
1504
-
1505
- def add_reverse_item(_editor)
1506
- code2form = proc{
1507
- Revparsel.new(_editor.text_value)
1508
- self.close_editor(_editor, false)
1509
- InspectorContract.instance.raise_last_widget(self)
1510
- }
1511
- _editor.insert_popup_menu_item('end',
1512
- :command,
1513
- :label=>'View as form',
1514
- :hidemargin => false,
1515
- :command=> code2form
1516
- )
1517
-
1518
- end
1519
-
1520
- # def editor_state
1521
- # r = EditorContract::SObj.new
1522
- # r.raised_file = self.raised.file
1523
- # r.breakpoints = @breakpoints
1524
- # return r
1525
- # end
1526
-
1527
- def get_find
1528
- @find
1529
- end
1530
-
1531
- def create_find
1532
- #find_frame = @arcadia.layout.register_panel(conf('find.frame'),'Find', 'Find')
1533
- # @find = Find.new(@splitted_frame.top_frame, self)
1534
- @find = Find.new(@arcadia.layout.root, self)
1535
- @find.on_close=proc{@find.hide}
1536
- @find.hide
1537
- end
1538
-
1539
- def finalize
1540
- _files =''
1541
- @tabs_editor.each_value{|editor|
1542
- _files=_files+'|'+ editor.file if editor.file != nil
1543
- close_editor(editor)
1544
- }
1545
- @arcadia['pers']['editor.files.open']=_files
1546
- end
1547
-
1548
- def raised
1549
- _page = @main_frame.enb.raise
1550
- return @tabs_editor[_page]
1551
- end
1552
-
1553
- def close_raised
1554
- close_editor(@tabs_editor[@main_frame.enb.raise])
1555
-
1556
- #_page = @main_frame.enb.raise
1557
- #_editor = @tabs_editor[_page]
1558
- #_row = _editor.text_insert_index.split('.')[0].strip.to_i
1559
- #close_editor(_editor)
1560
- end
1561
-
1562
- def breakpoint_add(_file,_line)
1563
- EditorContract.instance.breakpoint_created(self, 'file'=>_file, 'line'=>_line)
1564
- @breakpoints << {:file=>_file,:line=>_line}
1565
- end
1566
-
1567
- def breakpoint_del(_file,_line)
1568
- EditorContract.instance.breakpoint_deleted(self, 'file'=>_file, 'line'=>_line)
1569
- @breakpoints.delete_if{|b| (b[:file]==_file && b[:line]==_line)}
1570
- end
1571
-
1572
- def breakpoint_lines_on_file(_file)
1573
- result = Array.new
1574
- @breakpoints.each{|value|
1575
- if value[:file]==_file
1576
- result << value[:line]
1577
- end
1578
- }
1579
- return result
1580
- end
1581
-
1582
- def open_last_files
1583
- if $arcadia['pers']['editor.files.open']
1584
- _files_index =$arcadia['pers']['editor.files.open'].split("|")
1585
- _files_index.each{|value|
1586
- _file,_index = value.split(';')
1587
- if _file
1588
- open_file(_file,_index)
1589
- end
1590
- }
1591
- end
1592
- self
1593
- end
1594
-
1595
- def bookmark_add(_file, _index)
1596
- if @bookmarks == nil
1597
- @bookmarks = Array.new
1598
- @bookmarks_index = - 1
1599
- else
1600
- _cur_file, _cur_index = @bookmarks[@bookmarks_index]
1601
- if _cur_file == _file && _cur_index == _index
1602
- #@arcadia.outln('uguale ----> '+_file+':'+_index)
1603
- return
1604
- end
1605
- @bookmarks = @bookmarks[0..@bookmarks_index]
1606
- end
1607
- @bookmarks << [_file, _index]
1608
- @bookmarks_index = @bookmarks.length - 1
1609
- #@arcadia.outln('add ----> '+_file+':'+_index)
1610
- end
1611
-
1612
- def bookmark_clear
1613
- @bookmarks.clear
1614
- @bookmarks_index = - 1
1615
- end
1616
-
1617
- def bookmark_next
1618
- return if @bookmarks == nil || @bookmarks_index >= @bookmarks.length - 1
1619
- bookmark_move(+1)
1620
- end
1621
-
1622
- def bookmark_move(_n=0)
1623
- @bookmarks_index = @bookmarks_index + _n
1624
- #Tk.messageBox('message'=>@bookmarks_index.to_s)
1625
- _file, _index = @bookmarks[@bookmarks_index]
1626
- _line, _col = _index.split('.') if _index
1627
- open_file(_file, _index)
1628
- #openfile(@bookmarks[@bookmarks_index])
1629
- end
1630
-
1631
-
1632
- def bookmark_prev
1633
- return if @bookmarks == nil || @bookmarks_index <= 0
1634
- bookmark_move(-1)
1635
- end
1636
-
1637
-
1638
- def get_tab_from_name(_name=nil)
1639
- return @main_frame.enb.get_frame(_name)
1640
- # if _name
1641
- # @tabs_name.each{
1642
- # |key,value|
1643
- # if value.to_s==_name.to_s
1644
- # return key
1645
- # end
1646
- # }
1647
- # return nil
1648
- # end
1649
- end
1650
-
1651
- def change_tab_set_modify(_tab)
1652
- _new_name = '(...)'+@main_frame.enb.itemcget(page_name(_tab), 'text')
1653
- change_tab_title(_tab, _new_name)
1654
- end
1655
-
1656
- def page_name(_page_frame)
1657
- TkWinfo.appname(_page_frame).sub('f','')
1658
- end
1659
-
1660
- def change_tab_reset_modify(_tab)
1661
- #_new_name = @main_frame.enb.itemcget(@tabs_name[_tab], 'text').gsub!("(...)",'')
1662
- _new_name = @main_frame.enb.itemcget(page_name(_tab), 'text').gsub!("(...)",'')
1663
- if _new_name
1664
- change_tab_title(_tab, _new_name)
1665
- end
1666
- end
1667
-
1668
- def change_tab_title(_tab, _new_text)
1669
- @main_frame.enb.itemconfigure(page_name(_tab), 'text'=> _new_text)
1670
- end
1671
-
1672
- def change_file_name(_tab, _new_file)
1673
- _new_label = File.basename(_new_file)
1674
- change_tab_title(_tab, _new_label)
1675
- @tabs_file[page_name(_tab)] = _new_file
1676
- end
1677
-
1678
- def debug_begin
1679
- if @editors_in_debug != nil
1680
- @editors_in_debug.clear
1681
- else
1682
- @editors_in_debug = Array.new
1683
- end
1684
- end
1685
-
1686
- def debug_end
1687
- debug_reset
1688
- @editors_in_debug.each{|e|
1689
- close_editor(e)
1690
- }
1691
- end
1692
-
1693
- def debug_reset
1694
- if @last_index && @last_e
1695
- @last_e.unmark_debug(@last_index)
1696
- end
1697
- end
1698
-
1699
- def open_file_in_debug(_filename=nil, _line=nil)
1700
- debug_reset
1701
- if _filename && _line
1702
-
1703
- @last_index = _line.to_s+'.0'
1704
- _editor_exist = editor_exist?(_filename)
1705
- @last_e = open_file(_filename, @last_index)
1706
- if !_editor_exist
1707
- @editors_in_debug << @last_e
1708
- end
1709
- @last_e.mark_debug(@last_index) if @last_e
1710
-
1711
- end
1712
- end
1713
-
1714
- def do_buffer_raise(_name, _title='...')
1715
- _index = @main_frame.enb.index(_name)
1716
- _new_caption = '...'
1717
- if _index != -1
1718
- #_name = @main_frame.enb.pages(_index)
1719
- #_tab = get_tab_from_name(_name)
1720
- #@main_frame.enb.raise(_name)
1721
- _e = @tabs_editor[_name]
1722
- if _e && _e.file != nil
1723
- _new_caption = _e.file
1724
- @find.use(_e)
1725
- _e.check_file_last_access_time
1726
- else
1727
- _new_caption = _title
1728
- end
1729
- end
1730
- if @arcadia.layout.headed?
1731
- @arcadia.layout.domain(@arcadia['conf'][@name+'.frame'])['root'].top_text(_new_caption)
1732
- end
1733
- _title = @tabs_file[_name] != nil ? File.basename(@tabs_file[_name]) :_name
1734
- EditorContract.instance.buffer_raised(self, 'title'=>_title, 'file'=>@tabs_file[_name])
1735
- end
1736
-
1737
- def editor_exist?(_filename)
1738
- _basefilename = File.basename(_filename)
1739
- #_basename = _basefilename.split('.')[0]+'_'+_basefilename.split('.')[1]
1740
-
1741
-
1742
- _index = @main_frame.enb.index(self.tab_name(_filename))
1743
- return _index != -1
1744
- end
1745
-
1746
- def tab_name(_str="")
1747
- 'ff'+_str.gsub("/","_").gsub(".","_").gsub(":","_").gsub("\\","_")
1748
- end
1749
-
1750
- def tab_file_name(_filename="")
1751
- _fstr = File.expand_path(_filename)
1752
- _fstr = _filename if _fstr == nil
1753
- tab_name(_fstr)
1754
- end
1755
-
1756
- def open_file(_filename = nil, _text_index='1.0')
1757
- return if _filename == nil || !File.exist?(_filename)
1758
- _basefilename = File.basename(_filename)
1759
- _tab_name = self.tab_file_name(_filename)
1760
- _index = @main_frame.enb.index(_tab_name)
1761
- _exist_buffer = _index != -1
1762
-
1763
- if _exist_buffer
1764
- open_buffer(_tab_name)
1765
- else
1766
- open_buffer(_tab_name, _basefilename)
1767
- # _basefilename.include?('.rb')?_image = RUBY_DOCUMENT_GIF: _image = DOCUMENT_OPEN_GIF
1768
- # @main_frame.enb.itemconfigure(_tab_name,
1769
- # 'image'=> TkPhotoImage.new('data' =>_image )
1770
- # )
1771
- @tabs_file[_tab_name]= _filename
1772
- @tabs_editor[_tab_name].load_file(_filename)
1773
- #do_buffer_raise(_tab_name)
1774
- EditorContract.instance.file_opened(self, 'file'=>_filename)
1775
- end
1776
-
1777
- if _text_index != nil && _text_index != '1.0'
1778
- @tabs_editor[_tab_name].text_see(_text_index)
1779
- @tabs_editor[_tab_name].mark_selected(_text_index)
1780
- end
1781
-
1782
- return @tabs_editor[_tab_name]
1783
- end
1784
-
1785
-
1786
- def open_buffer(_buffer_name = nil, _title = nil)
1787
- _index = @main_frame.enb.index(_buffer_name)
1788
- if _buffer_name == nil
1789
- _buffer_name = tab_name('new')
1790
- _title_new = '*new'
1791
- end
1792
-
1793
- if _index != -1
1794
- _tab = @main_frame.enb.get_frame(_buffer_name)
1795
- @main_frame.enb.raise(_buffer_name)
1796
- else
1797
- _n = 1
1798
- while @main_frame.enb.index(_buffer_name) != -1
1799
- _title_new = '*new'+_n.to_s
1800
- _buffer_name = tab_name('new')+_n.to_s
1801
- _n =_n+1
1802
- end
1803
- if _title == nil
1804
- _title = _title_new
1805
- end
1806
- _tab = @main_frame.enb.insert('end', _buffer_name ,
1807
- 'text'=> _title,
1808
- 'raisecmd'=>proc{do_buffer_raise(_buffer_name, _title)}
1809
- )
1810
- _e = AgEditor.new(self, _tab)
1811
- _e.init_editing(_e.file_extension(_title))
1812
- @tabs_file[_buffer_name]= nil
1813
- @tabs_editor[_buffer_name]=_e
1814
- end
1815
- @main_frame.enb.move(_buffer_name, 1)
1816
- @main_frame.enb.raise(_buffer_name)
1817
- @main_frame.enb.see(_buffer_name)
1818
- return _tab
1819
- end
1820
-
1821
- def close_others_editor(_editor, _mod=true)
1822
- @tabs_editor.values.each do |_e|
1823
- close_editor(_e) if _e != _editor
1824
- end
1825
- end
1826
-
1827
- def close_all_editor(_editor, _mod=true)
1828
- @tabs_editor.values.each do |_e|
1829
- close_editor(_e)
1830
- end
1831
- end
1832
-
1833
- def close_editor(_editor, _mod=true)
1834
- if ((_mod)&&(_editor.modified?))
1835
- _message = @main_frame.enb.itemcget(page_name(_editor.page_frame), 'text')+"\n modified. Save?"
1836
- _r = TkDialog2.new('message'=>_message, 'buttons'=>['Ok','No','Cancel']).show()
1837
- if _r == 0
1838
- _editor.save
1839
- elsif _r == 1
1840
- close_tab(_editor.page_frame)
1841
- elsif _r == 2
1842
- return
1843
- end
1844
- else
1845
- close_tab(_editor.page_frame)
1846
- end
1847
- EditorContract.instance.file_closed(self, 'file'=>_editor.file)
1848
- end
1849
-
1850
- def close_tab(_page_frame)
1851
- _name = page_name(_page_frame)
1852
- @tabs_editor.delete(_name)
1853
- _index = @main_frame.enb.index(_name)
1854
- @main_frame.enb.delete(_name)
1855
- if !@main_frame.enb.pages.empty?
1856
- @main_frame.enb.raise(@main_frame.enb.pages[_index-1])
1857
- end
1858
- end
1859
-
1860
- def close_file(_filename)
1861
- close_editor(@tabs_editor[tab_name(_filename)])
1862
- end
1863
-
1864
- def save_file(_filename)
1865
- @tabs_editor[tab_name(_filename)].save
1866
- end
1867
-
1868
- def save_as_file(_filename)
1869
- @tabs_editor[tab_name(_filename)].save_as
1870
- end
1871
-
1872
- end
1873
-
1874
- class Findview < TkFloatTitledFrame
1875
- def initialize(_parent)
1876
- super(_parent)
1877
- #stop_resizing
1878
- y0 = 10
1879
- d = 23
1880
- TkLabel.new(self.frame){
1881
- text 'Find what:'
1882
- place('x' => 8,'y' => y0,'height' => 19)
1883
- }
1884
- y0 = y0 + d
1885
- @e_what = Tk::BWidget::ComboBox.new(self.frame){
1886
- editable true
1887
- justify 'left'
1888
- relief 'ridge'
1889
- autocomplete 'true'
1890
- #insertbackground '#FFFFFF'
1891
- entrybg '#FFFFFF'
1892
- expand 'tab'
1893
- takefocus 'true'
1894
- #pack('padx'=>10, 'fill'=>'x')
1895
- place('relwidth' => 1, 'width'=>-16,'x' => 8,'y' => y0,'height' => 19)
1896
- }
1897
- y0 = y0 + d
1898
- TkLabel.new(self.frame){
1899
- text 'Replace with:'
1900
- place('x' => 8,'y' => y0,'height' => 19)
1901
- }
1902
- y0 = y0 + d
1903
-
1904
- @e_with = Tk::BWidget::ComboBox.new(self.frame){
1905
- editable true
1906
- justify 'left'
1907
- relief 'ridge'
1908
- autocomplete 'true'
1909
- #insertbackground '#FFFFFF'
1910
- entrybg '#FFFFFF'
1911
- expand 'tab'
1912
- takefocus 'true'
1913
- #pack('padx'=>10, 'fill'=>'x')
1914
- place('relwidth' => 1, 'width'=>-16,'x' => 8,'y' => y0,'height' => 19)
1915
- }
1916
-
1917
- y0 = y0 + d
1918
- @cb_reg = TkCheckButton.new(self.frame){|_cb_reg|
1919
- text 'Use Regular Expression'
1920
- justify 'left'
1921
- relief 'flat'
1922
- #pack('side'=>'left', 'anchor'=>'e')
1923
- place('x' => 8,'y' => y0,'height' => 22)
1924
- }
1925
- y0 = y0 + d
1926
- @cb_back = TkCheckButton.new(self.frame){|_cb_reg|
1927
- text 'Search backwards'
1928
- justify 'left'
1929
- relief 'flat'
1930
- #pack('side'=>'left', 'anchor'=>'e')
1931
- place('x' => 8,'y' => y0,'height' => 22)
1932
- }
1933
-
1934
- y0 = y0 + d
1935
- y0 = y0 + d
1936
- @buttons_frame = TkFrame.new(self.frame).pack('fill'=>'x', 'side'=>'bottom')
1937
-
1938
- @b_replace_all = TkButton.new(@buttons_frame){|_b_go|
1939
- state 'disabled'
1940
- default 'disabled'
1941
- text 'Replace All'
1942
- overrelief 'raised'
1943
- justify 'center'
1944
- #width 15
1945
- pack('side'=>'right','ipadx'=>5, 'padx'=>5)
1946
- #place('width' => 50,'x' => 0,'y' => y0,'height' => 23,'bordermode' => 'inside')
1947
- }
1948
-
1949
-
1950
- @b_replace = TkButton.new(@buttons_frame){|_b_go|
1951
- state 'disabled'
1952
- default 'disabled'
1953
- text 'Replace'
1954
- overrelief 'raised'
1955
- justify 'center'
1956
- #width 15
1957
- pack('side'=>'right','ipadx'=>5, 'padx'=>5)
1958
- #place('width' => 50,'x' => 0,'y' => y0,'height' => 23,'bordermode' => 'inside')
1959
- }
1960
-
1961
-
1962
- @b_go = TkButton.new(@buttons_frame){|_b_go|
1963
- compound 'none'
1964
- default 'disabled'
1965
- text 'Find Next'
1966
- #background '#ffffff'
1967
- #image TkPhotoImage.new('dat' => FIND_GIF)
1968
- overrelief 'raised'
1969
- justify 'center'
1970
- #relief 'ridge'
1971
- #width 15
1972
- pack('side'=>'right','ipadx'=>5, 'padx'=>5)
1973
- #place('width' => 50,'x' => 0,'y' => y0,'height' => 23,'bordermode' => 'inside')
1974
- }
1975
- #place('x'=>0,'y'=>0,'relheight'=> 1,'relwidth'=> 1)
1976
- place('x'=>100,'y'=>100,'height'=> 220,'width'=> 300)
1977
-
1978
- end
1979
- end
1980
-
1981
- class Find < Findview
1982
- attr_reader :e_what
1983
- def initialize(_frame, _controller)
1984
- super(_frame)
1985
- #@l_file.configure('text'=>_title)
1986
- #Tk.tk_call('wm', 'title', self, _title )
1987
- @controller = _controller
1988
- @forwards = true
1989
- @find_action = proc{
1990
- #_radio = @rb.get_value
1991
-
1992
- #if _radio == 'line'
1993
- # go_line
1994
- #else
1995
- do_find_next
1996
- #end
1997
- }
1998
- @b_go.bind('1', @find_action)
1999
-
2000
- @b_replace.bind('1', proc{do_replace})
2001
-
2002
- @b_replace_all.bind('1', proc{do_replace_all})
2003
-
2004
- e = TkWinfo.children(@e_what)[0]
2005
- e.bind_append('KeyPress'){|e|
2006
- case e.keysym
2007
- when 'Return'
2008
- @find_action.call
2009
- hide
2010
- @editor_caller.text.focus
2011
- Tk.callback_break
2012
- else
2013
- widget_state
2014
- end
2015
- }
2016
- e2 = TkWinfo.children(@e_with)[0]
2017
- e2.bind_append('KeyPress'){|e|
2018
- widget_state
2019
- }
2020
- @last_index='insert'
2021
-
2022
- @goto_line_dialog = GoToLine.new(_frame).hide
2023
- @goto_line_dialog.on_close=proc{@goto_line_dialog.hide}
2024
-
2025
- @goto_line_dialog.b_go.bind('1',proc{go_line})
2026
- end
2027
-
2028
- def do_replace
2029
- if do_find_next
2030
- _message = 'Replace "'+@e_what.value+'" with "'+@e_with.value+'" ?'
2031
- if TkDialog2.new('message'=>_message, 'buttons'=>['Yes','No']).show() == 0
2032
- self.editor.text.delete(@idx1,@idx2)
2033
- self.editor.text.insert(@idx1,@e_with.value)
2034
- self.editor.check_modify
2035
- end
2036
- end
2037
- end
2038
-
2039
- def do_replace_all
2040
- while do_find_next
2041
- _message = 'Replace "'+@e_what.value+'" with "'+@e_with.value+'" ?'
2042
- _rc = TkDialog2.new('message'=>_message, 'buttons'=>['Yes','No','Annulla']).show()
2043
- if _rc == 0
2044
- self.editor.text.delete(@idx1,@idx2)
2045
- self.editor.text.insert(@idx1,@e_with.value)
2046
- self.editor.check_modify
2047
- elsif _rc == 2
2048
- break
2049
- end
2050
- end
2051
- end
2052
-
2053
- def widget_state
2054
- if (@e_what.value.length > 0) && (@e_with.value.length > 0)
2055
- @b_replace.configure('state'=>'active')
2056
- @b_replace_all.configure('state'=>'active')
2057
- else
2058
- @b_replace.configure('state'=>'disabled')
2059
- @b_replace_all.configure('state'=>'disabled')
2060
- end
2061
- end
2062
-
2063
-
2064
- def editor
2065
- if @editor_caller == nil
2066
- @editor_caller = @controller.raised
2067
- end
2068
- return @editor_caller
2069
- end
2070
-
2071
- def show_go_to_line_dialog
2072
- @goto_line_dialog.show
2073
- end
2074
-
2075
- def go_line
2076
- if @goto_line_dialog.e_line.value.length > 0
2077
- _row = @goto_line_dialog.e_line.value
2078
- _index = _row+'.1'
2079
- self.editor.text.see(_index)
2080
- self.editor.text.tag_add('sel', _index,_index+' lineend')
2081
- self.editor.text.set_insert(_index)
2082
- @controller.bookmark_add(self.editor.file, _index)
2083
- @goto_line_dialog.hide
2084
- end
2085
- #self.hide()
2086
- end
2087
-
2088
- def use(_editor)
2089
- if (_editor != @editor_caller)
2090
- @last_index='insert'
2091
- @editor_caller = _editor
2092
- title(_editor.file)
2093
- end
2094
- end
2095
-
2096
- def update_combo(_txt)
2097
- values = @e_what.cget('values')
2098
- if (values != nil && !values.include?(_txt))
2099
- @e_what.insert('end', @e_what.value)
2100
- end
2101
- end
2102
-
2103
- def do_find(_istart=nil)
2104
- @forwards = @cb_back.cget('onvalue') != @cb_back.cget('variable').value.to_i
2105
- _found = false
2106
- @idx1 = nil
2107
- @idx2 = nil
2108
- if @e_what.text.length > 0
2109
- update_combo(@e_what.text)
2110
- if !_istart && self.editor.text.index('insert')!=nil
2111
- _istart ='insert'
2112
- elsif defined?(@last_index)
2113
- _istart = @last_index
2114
- else
2115
- _istart = '1.0'
2116
- end
2117
- if @forwards
2118
- if @cb_reg.cget('onvalue')==@cb_reg.cget('variable').value.to_i
2119
- _index = self.editor.text.tksearch(['regexp'],@e_what.text,_istart)
2120
- else
2121
- _index = self.editor.text.search(@e_what.text,_istart)
2122
- end
2123
- else
2124
-
2125
- if @cb_reg.cget('onvalue')==@cb_reg.cget('variable').value.to_i
2126
- _index = self.editor.text.tksearch(['regexp','backwards'],@e_what.text,_istart)
2127
- else
2128
- _index = self.editor.text.tksearch(['backwards'],@e_what.text,_istart)
2129
- end
2130
- end
2131
- if _index && _index.length>0
2132
- self.editor.text.see(_index)
2133
- _row, _col = _index.split('.')
2134
- _index_sel_end = _row.to_i.to_s+'.'+(_col.to_i+@e_what.text.length).to_i.to_s
2135
- if @forwards
2136
- @last_index= _index_sel_end
2137
- else
2138
- @last_index= _row.to_i.to_s+'.'+(_col.to_i-1).to_i.to_s
2139
- end
2140
- self.editor.text.tag_add('sel', _index,_index_sel_end)
2141
- self.editor.text.set_insert(_index)
2142
- @idx1 =_index
2143
- @idx2 =_index_sel_end
2144
- _found = true
2145
- @controller.bookmark_add(self.editor.file, _index)
2146
- else
2147
- _message = '"'+@e_what.value+'" not found'
2148
- TkDialog2.new('message'=>_message, 'buttons'=>['Ok']).show()
2149
- end
2150
-
2151
- else
2152
- self.show()
2153
- end
2154
- return _found
2155
- end
2156
-
2157
- def do_find_next
2158
- if @idx1 != nil
2159
- self.editor.text.tag_remove('sel',@idx1,@idx2)
2160
- end
2161
- do_find(@last_index)
2162
- end
2163
- end
2164
-
2165
-
2166
- class KeyTestView < TkToplevel
2167
- attr_reader :ttest
2168
- def initialize
2169
- super
2170
-
2171
- Tk.tk_call('wm', 'title', self, '...hello' )
2172
- Tk.tk_call('wm', 'geometry', self, '638x117+200+257' )
2173
-
2174
- @ttest = TkText.new(self){
2175
- background '#FFF454'
2176
- place('relwidth' => '1','relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => '0','bordermode' => 'inside','width' => '0')
2177
- }
2178
-
2179
- end
2180
- end
2181
-
2182
- class KetTest
2183
- def initialize
2184
- kt = KeyTestView.new
2185
- kt.ttest.bind("KeyPress"){|e|
2186
- kt.ttest.insert('end'," [ "+e.keysym+" ] ")
2187
- break
2188
- }
2189
- end
2190
- end
2191
-
2192
- class CodeInsight
2193
- end
2194
-
2195
- class GoToLine < TkFloatTitledFrame
2196
- attr_reader :e_line
2197
- attr_reader :b_go
2198
- def initialize(_parent)
2199
- super(_parent)
2200
- #stop_resizing
2201
- y0 = 10
2202
- d = 23
2203
- TkLabel.new(self.frame){
2204
- text 'Go to line:'
2205
- place('x' => 8,'y' => y0,'height' => 19)
2206
- }
2207
- y0 = y0 + d
2208
- @e_line = TkEntry.new(self.frame){
2209
- justify 'left'
2210
- relief 'ridge'
2211
- place('relwidth' => 1, 'width'=>-16,'x' => 8,'y' => y0,'height' => 19)
2212
- }
2213
-
2214
- y0 = y0 + d
2215
- y0 = y0 + d
2216
- @buttons_frame = TkFrame.new(self.frame).pack('fill'=>'x', 'side'=>'bottom')
2217
-
2218
- @b_go = TkButton.new(@buttons_frame){|_b_go|
2219
- compound 'none'
2220
- default 'disabled'
2221
- text 'Go'
2222
- overrelief 'raised'
2223
- justify 'center'
2224
- pack('side'=>'right','ipadx'=>5, 'padx'=>5)
2225
- }
2226
- place('x'=>150,'y'=>150,'height'=> 120,'width'=> 100)
2227
-
2228
- end
2229
- end
1
+ #
2
+ # ae-editor.rb - Arcadia Ruby ide
3
+ # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
+ #
5
+
6
+ require 'tk'
7
+ require 'tktext'
8
+ require 'base/a-utils'
9
+
10
+
11
+ class TreeNode
12
+ attr_reader :sons
13
+ attr_reader :parent
14
+ attr_reader :kind
15
+ attr_reader :rif, :label, :helptext
16
+ attr_writer :rif, :label, :helptext
17
+ def initialize(parent=nil, kind='KClass')
18
+ @sons = Array.new
19
+ @parent = parent
20
+ @kind = kind
21
+ if @parent !=nil
22
+ @parent.sons << self
23
+ end
24
+ yield(self) if block_given?
25
+ end
26
+
27
+ def <=> (other)
28
+ self.label.strip <=> other.label.strip
29
+ end
30
+ end
31
+
32
+ class AgEditor
33
+ attr_reader :file
34
+ attr_reader :page_frame
35
+ attr_reader :text, :root
36
+ def initialize(_controller, _page_frame)
37
+ @controller = _controller
38
+ @page_frame = _page_frame
39
+ @set_mod = false
40
+ @font = @controller.conf('font')
41
+ @font_bold = @controller.conf('font.bold')
42
+ @font_metrics = TkFont.new(@font).metrics
43
+ @font_metrics_bold = TkFont.new(@font_bold).metrics
44
+ @highlighting = false
45
+ @classbrowsing = false
46
+ @find = @controller.get_find
47
+ end
48
+
49
+ def initialize_tree(_frame)
50
+ @classbrowsing = true
51
+ @nb = Tk::BWidget::NoteBook.new(_frame){
52
+ tabbevelsize 0
53
+ internalborderwidth 0
54
+ activeforeground 'red'
55
+ activebackground 'yellow'
56
+ borderwidth 1
57
+ side $arcadia['conf']['editor.explorer_panel.tabs.side']
58
+ font $arcadia['conf']['editor.tabs.font']
59
+ pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
60
+ }
61
+ @nb_tab_exp = @nb.insert('end','exp' ,'text'=>'Source Tree' )
62
+ @nb.raise('exp')
63
+ _tree_goto = proc{|_self|
64
+ _line = _self.selection_get[0]
65
+ _index =_line.to_s+'.0'
66
+ _hinner_text = @tree_exp.itemcget(_line,'text').strip
67
+ _editor_line = @text.get(_index, _index+ ' lineend')
68
+ if !_editor_line.include?(_hinner_text)
69
+ MsgContract.instance.out_simple(self, "... rebuild tree \n")
70
+ if @tree_thread && @tree_thread.alive?
71
+ @tree_thread.exit
72
+ end
73
+ @tree_thread = Thread.new{
74
+ build_tree(_line)
75
+ Tk.update
76
+ }
77
+ _line = _self.selection_get[0]
78
+ _index =_line.to_s+'.0'
79
+ end
80
+ @text.see(_index)
81
+ @text.tag_remove('selected','1.0','end')
82
+ @text.tag_add('selected',_line.to_s+'.0',(_line+1).to_s+'.0')
83
+ }
84
+ @tree_exp = Tk::BWidget::Tree.new(@nb_tab_exp){
85
+ background '#FFFFFF'
86
+ relief 'flat'
87
+ showlines false
88
+ deltay 18
89
+ dragenabled true
90
+ selectcommand proc{ _tree_goto.call(self) }
91
+ place('relwidth' => 1,'relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => 1,'bordermode' => 'inside','width' => '50')
92
+ }
93
+
94
+ _c_explo = proc{|*args| @tree_exp.yview(*args)}
95
+ _s_explo = TkScrollbar.new(@nb_tab_exp){|s|
96
+ width 8
97
+ command _c_explo
98
+ }.pack('side'=>'right', 'fill'=>'y')
99
+ @tree_exp.yscrollcommand proc{|first,last| _s_explo.set first,last}
100
+ pop_up_menu_tree
101
+ end
102
+
103
+ def pop_up_menu_tree
104
+ @pop_up_tree = TkMenu.new(
105
+ :parent=>@tree_exp,
106
+ :title => 'Menu tree'
107
+ )
108
+ @pop_up_tree.insert('end',
109
+ :command,
110
+ :label=>'Rebuild',
111
+ :hidemargin => false,
112
+ :command=> proc{build_tree}
113
+ )
114
+ @tree_exp.bind_append("Button-3",
115
+ proc{|x,y|
116
+ _x = TkWinfo.pointerx(@tree_exp)
117
+ _y = TkWinfo.pointery(@tree_exp)
118
+ @pop_up_tree.popup(_x,_y)
119
+ },
120
+ "%x %y")
121
+ end
122
+
123
+
124
+ def initialize_text(_frame)
125
+ @v_scroll = TkScrollbar.new(_frame,
126
+ 'orient'=>'vertical',
127
+ 'relief'=>'flat'
128
+ ).pack('side' => 'right', 'fill' => 'y')
129
+ @text = TkText.new(@fm1.right_frame){|j|
130
+ wrap 'none'
131
+ relief 'flat'
132
+ undo true
133
+ insertofftime 200
134
+ insertontime 200
135
+ insertbackground $arcadia['conf']['editor.color.insertbackground']
136
+ background $arcadia['conf']['editor.color.background']
137
+ foreground $arcadia['conf']['editor.color.foreground']
138
+ insertwidth 3
139
+ exportselection true
140
+ autoseparators true
141
+ padx 0
142
+ tabs $arcadia['conf']['editor.tabs']
143
+ place(
144
+ 'x'=>0,
145
+ 'y'=>0,
146
+ 'width' => -15,
147
+ 'relheight'=>1,
148
+ 'relwidth'=>1,
149
+ 'bordermode'=>'outside'
150
+ )
151
+ }
152
+ @text.configure('font', @font);
153
+
154
+ @text.tag_configure('eval','foreground' => 'yellow', 'background' =>'red','borderwidth'=>1, 'relief'=>'raised')
155
+ @text.tag_configure('errline','borderwidth'=>1, 'relief'=>'groove')
156
+ @text.tag_configure('debug', 'background' =>'#b9c6d9', 'borderwidth'=>1 ,'relief'=>'raise')
157
+ #@text.tag_configure('debug', 'background' =>'#ffd2ff', 'borderwidth'=>1 ,'relief'=>'raise')
158
+ @buffer = text_value
159
+ pop_up_menu
160
+ end
161
+
162
+ def create_temp_file
163
+ _file = @file+'~~'
164
+ f = File.new(@file+'~~', "w")
165
+ begin
166
+ if f
167
+ f.syswrite(text_value)
168
+ end
169
+ ensure
170
+ f.close unless f.nil?
171
+ end
172
+ _file
173
+ end
174
+
175
+ def initialize_text_binding
176
+ @v_scroll.command(proc{|*args|
177
+ @text.yview *args
178
+ })
179
+ @text.yscrollcommand(proc{|first,last| @v_scroll.set(first,last)
180
+ self.do_line_update()
181
+ })
182
+ @text.tag_bind('selected', 'Enter', proc{@text.tag_remove('selected','1.0','end')})
183
+
184
+ @text.bind("Enter", proc{check_file_last_access_time})
185
+ @text.bind("ButtonPress-1", proc{
186
+ _code = $arcadia['palette'].give_me_code
187
+ @text.insert('insert', _code) if _code
188
+ })
189
+
190
+ @text.bind("Control-KeyPress"){|e|
191
+ case e.keysym
192
+ when 'space'
193
+ line, col = @text.index('insert').split('.')
194
+ _file = create_temp_file
195
+ EditorContract.instance.complete_code(self, 'file'=>_file, 'line'=>line.to_s, 'col'=>col.to_s)
196
+ when 'z'
197
+ _b = @text.index('insert').split('.')[0].to_i
198
+ @text.edit_undo
199
+ _e = @text.index('insert').split('.')[0].to_i
200
+ if @highlighting
201
+ for j in _b..._e
202
+ rehighlightline(j)
203
+ end
204
+ end
205
+ break
206
+ when 'c'
207
+ @text.text_copy
208
+ break
209
+ when 'x'
210
+ @text.text_cut
211
+ break
212
+ when 'v'
213
+ _b = @text.index('insert').split('.')[0].to_i
214
+ @text.text_paste
215
+ _e = @text.index('insert').split('.')[0].to_i
216
+ if @highlighting
217
+ for j in _b..._e
218
+ rehighlightline(j)
219
+ end
220
+ end
221
+ break
222
+ end
223
+ case e.keysym
224
+ when 's'
225
+ save
226
+ when 'f'
227
+ _r = @text.tag_ranges('sel')
228
+ if _r.length>0
229
+ _text=@text.get(_r[0][0],_r[0][1])
230
+ if _text.length > 0
231
+ @find.e_what.text(_text)
232
+ end
233
+ else
234
+ end
235
+ @find.use(self)
236
+ @find.e_what.focus
237
+ @find.show
238
+ when 'egrave'
239
+ @text.insert('insert',"{")
240
+ when 'plus'
241
+ @text.insert('insert',"}")
242
+ end
243
+ }
244
+
245
+ @text.bind("Control-Shift-KeyPress"){|e|
246
+ case e.keysym
247
+ when 'I'
248
+ _r = @text.tag_ranges('sel')
249
+ _row_begin = _r[0][0].split('.')[0].to_i
250
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
251
+ n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
252
+ if n_space > 0
253
+ suf = "\s"*n_space
254
+ else
255
+ suf = "\t"
256
+ end
257
+
258
+ for _row in _row_begin..._row_end
259
+ @text.insert(_row.to_s+'.0',suf)
260
+ end
261
+ when 'U'
262
+ _r = @text.tag_ranges('sel')
263
+ _row_begin = _r[0][0].split('.')[0].to_i
264
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
265
+ n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
266
+ if n_space > 0
267
+ suf = "\s"*n_space
268
+ else
269
+ suf = "\t"
270
+ end
271
+ _l_suf = suf.length.to_s
272
+ for _row in _row_begin..._row_end
273
+ if @text.get(_row.to_s+'.0',_row.to_s+'.'+_l_suf) == suf
274
+ @text.delete(_row.to_s+'.0',_row.to_s+'.'+_l_suf)
275
+ end
276
+ end
277
+ when 'C'
278
+ _r = @text.tag_ranges('sel')
279
+ _row_begin = _r[0][0].split('.')[0].to_i
280
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
281
+
282
+ for _row in _row_begin..._row_end
283
+ if @text.get(_row.to_s+'.0',_row.to_s+'.1') == "#"
284
+ @text.delete(_row.to_s+'.0',_row.to_s+'.1')
285
+ else
286
+ @text.insert(_row.to_s+'.0',"#")
287
+ end
288
+ rehighlightline(_row) if @highlighting
289
+ end
290
+
291
+ end
292
+ }
293
+
294
+ @text.bind("KeyPress"){|e|
295
+ case e.keysym
296
+ #when 'Return'
297
+ when 'BackSpace'
298
+ _index = @text.index('insert')
299
+ _row, _col = _index.split('.')
300
+ rehighlightline(_row.to_i) if @highlighting
301
+ when 'Delete'
302
+ _index = @text.index('insert')
303
+ _row, _col = _index.split('.')
304
+ rehighlightline(_row.to_i) if @highlighting
305
+ when 'F5'
306
+ save
307
+ $arcadia['shell'].run(@file.to_s)
308
+ when 'F3'
309
+ @find.do_find_next
310
+ when 'F1'
311
+ line, col = @text.index('insert').split('.')
312
+ _file = create_temp_file
313
+ _x, _y = @controller.xy_insert
314
+ EditorContract.instance.doc_code(@controller, 'file'=>_file, 'line'=>line.to_s, 'col'=>col.to_s, 'xdoc'=>_x, 'ydoc'=>_y)
315
+ when 'Tab'
316
+ n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
317
+ _r = @text.tag_ranges('sel')
318
+ if _r && _r[0]
319
+ _row_begin = _r[0][0].split('.')[0].to_i
320
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
321
+ if n_space > 0
322
+ suf = "\s"*n_space
323
+ else
324
+ suf = "\t"
325
+ end
326
+ for _row in _row_begin..._row_end
327
+ @text.insert(_row.to_s+'.0', suf)
328
+ end
329
+ break
330
+ elsif n_space > 0
331
+ @text.insert('insert', "\s"*n_space)
332
+ break
333
+ end
334
+ end
335
+ }
336
+
337
+ @text.bind("KeyRelease"){|e|
338
+ case e.keysym
339
+ when 'Control_L','Return', 'Control_V', 'BackSpace', 'Delete'
340
+ if modified?
341
+ set_modify
342
+ else
343
+ reset_modify
344
+ end
345
+ do_line_update
346
+ when 'Right','Left','Down', 'Up'
347
+ # do nil
348
+ else
349
+ check_modify
350
+ end
351
+
352
+ case e.keysym
353
+ when 'Return'
354
+ _index = @text.index('insert')
355
+ _row, _col = _index.split('.')
356
+ _txt = @text.get((_row.to_i-1).to_s+'.0',_index)
357
+ if _txt.length > 0
358
+ m = /\s*/.match(_txt)
359
+ if m
360
+ if (m[0] != "\n")
361
+ _sm = m[0]
362
+ _sm = _sm.sub(/\n/,"")
363
+ @text.insert('insert',_sm)
364
+ end
365
+ end
366
+ end
367
+ if _row.to_i + 1 == @text.index('end').split('.')[0].to_i
368
+ do_line_update
369
+ end
370
+ else
371
+ if @highlighting && /\w/.match(e.keysym)
372
+ rehighlightline(@text.index('insert').split('.')[0].to_i)
373
+ end
374
+ end
375
+ }
376
+
377
+
378
+ @text.bind("Shift-KeyPress"){|e|
379
+ case e.keysym
380
+ when 'Tab'
381
+ _r = @text.tag_ranges('sel')
382
+ if _r && _r[0]
383
+ _row_begin = _r[0][0].split('.')[0].to_i
384
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
385
+
386
+ n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
387
+ if n_space > 0
388
+ suf = "\s"*n_space
389
+ else
390
+ suf = "\t"
391
+ n_space = 1
392
+ end
393
+ for _row in _row_begin..._row_end
394
+ if @text.get(_row.to_s+'.0',_row.to_s+'.'+n_space.to_s) == suf
395
+ @text.delete(_row.to_s+'.0',_row.to_s+'.'+n_space.to_s)
396
+ end
397
+ end
398
+ break
399
+ end
400
+ end
401
+ }
402
+
403
+ end
404
+
405
+ def initialize_line_number(_frame)
406
+ @text_line_num = TkText.new(_frame){
407
+ wrap 'none'
408
+ relief 'flat'
409
+ undo false
410
+ takefocus 0
411
+ insertofftime 0
412
+ exportselection true
413
+ autoseparators true
414
+ cursor nil
415
+ insertwidth 0
416
+ background $arcadia['conf']['editor.line_number_panel.color.background']
417
+ foreground $arcadia['conf']['editor.line_number_panel.color.foreground']
418
+ place(
419
+ 'x'=>0,
420
+ 'y'=>0,
421
+ 'relheight'=>1,
422
+ 'relwidth'=>1,
423
+ 'bordermode'=>'outside'
424
+ )
425
+ }
426
+ delta = @font_metrics_bold[2][1]-@font_metrics[2][1]
427
+ @text_line_num.tag_configure('bold_case', 'spacing1'=>delta)
428
+ @text_line_num.tag_configure('breakpoint', 'background'=>'red','foreground'=>'yellow','borderwidth'=>1, 'relief'=>'raised')
429
+ @text_line_num.tag_configure('sel',
430
+ 'background'=>$arcadia['conf']['editor.line_number_panel.color.background'],
431
+ 'foreground'=>$arcadia['conf']['editor.line_number_panel.color.foreground'])
432
+ @text_line_num.bind("Double-ButtonPress-1", proc{|x,y|
433
+ _index = @text_line_num.index("@#{x},#{y}")
434
+ _line = @text_line_num.get(_index+' linestart',_index+' lineend').strip
435
+ if @controller.breakpoint_lines_on_file(@file).include?(_line)
436
+ @text_line_num.tag_remove('breakpoint',_index+' linestart',_index+' lineend')
437
+ @controller.breakpoint_del(@file, _line)
438
+ else
439
+ @text_line_num.tag_add('breakpoint',_index+' linestart',_index+' lineend')
440
+ # @text_line_num.tag_add('breakpoint',_index+' linestart',_index+' linestart + 1 chars')
441
+ @controller.breakpoint_add(@file, _line)
442
+ end
443
+ },
444
+ "%x %y")
445
+
446
+ @text_line_num.configure('font', @font);
447
+ @text_line_num.tag_configure('line_num',
448
+ 'foreground' => '#FFFFFF',
449
+ 'background' =>'#0000a0',
450
+ 'borderwidth'=>2,
451
+ 'relief'=>'raised'
452
+ )
453
+ end
454
+
455
+ def initialize_highlight
456
+ @highlighting = true
457
+ @highlight_zone = Hash.new;
458
+ # @highlight_zone_length = 45;
459
+ @highlight_zone_length = 8;
460
+ @last_line_begin = 0
461
+ @last_line_end = 0
462
+ @last_zone_begin=0;
463
+ @last_zone_end=0;
464
+ @is_line_bold = Hash.new
465
+ @is_tag_bold = Hash.new
466
+
467
+ @keyword = ['__FILE__', 'and', 'def', 'end', 'in', 'or', 'self', 'unless',
468
+ '__LINE__', 'begin', 'defined?', 'ensure', 'module', 'redo', 'super', 'until',
469
+ 'BEGIN', 'break', 'do', 'false', 'next', 'rescue', 'then', 'when',
470
+ 'END', 'case', 'else', 'for', 'nil', 'retry', 'true', 'while',
471
+ 'alias', 'class', 'elsif', 'if', 'not', 'return', 'undef', 'yield','require','include']
472
+ _re_string = ''
473
+ @keyword.each{|word|
474
+ if _re_string.length > 0
475
+ _re_string << '|'
476
+ end
477
+ if ['class','module','def'].include?(word)
478
+ _re_string << '([\s]*'+word+'[\s])'
479
+ else
480
+ _re_string << '\b('+word+')([.,+\(\s])'
481
+ end
482
+ }
483
+ @re_keyword = Regexp::new(_re_string)
484
+ @re_instance_variable = /([\s]*@)[A-Za-z0-9_]*/
485
+ @re_string = /'([\/A-Za-z0-9_@+\-!?=<>\[\]\{\}\(\).\s]*)'|"([\/A-Za-z0-9_@+\-!?=<>\[\]\{\}\(\).\s]*)"/
486
+ @re_number = /\d/
487
+ @re_operator = /[\(\)\[\]\(\)\{\}.:;,=><|]/
488
+ @re_method_name = /(def[\s][\s]*)[A-Za-z0-9_]*/
489
+ @re_class_name = /(class[\s][\s]*)[A-Za-z0-9_]*/
490
+ @re_module_name = /(module[\s][\s]*)[A-Za-z0-9_]*/
491
+ do_tag_configure('keyword')
492
+ do_tag_configure('method_name')
493
+ do_tag_configure('instance_variable')
494
+ do_tag_configure('class_name')
495
+ do_tag_configure('module_name')
496
+ do_tag_configure('comment')
497
+ do_tag_configure('string')
498
+ do_tag_configure('number')
499
+ do_tag_configure('sel')
500
+ do_tag_configure('selected')
501
+ do_tag_configure('operator')
502
+ do_tag_configure('tabs')
503
+ do_tag_configure('spaces')
504
+ end
505
+
506
+ def do_tag_configure(_name)
507
+ h = Hash.new
508
+ if $arcadia['conf']['editor.hightlight.'+_name+'.color.foreground']
509
+ h['foreground']=$arcadia['conf']['editor.hightlight.'+_name+'.color.foreground']
510
+ end
511
+ if $arcadia['conf']['editor.hightlight.'+_name+'.color.background']
512
+ h['background']=$arcadia['conf']['editor.hightlight.'+_name+'.color.background']
513
+ end
514
+ if $arcadia['conf']['editor.hightlight.'+_name+'.style']== 'bold'
515
+ h['font']=@font_bold
516
+ @is_tag_bold[_name]= true
517
+ end
518
+ if $arcadia['conf']['editor.hightlight.'+_name+'.relief']
519
+ h['relief']=$arcadia['conf']['editor.hightlight.'+_name+'.relief']
520
+ end
521
+ if $arcadia['conf']['editor.hightlight.'+_name+'.borderwidth']
522
+ h['borderwidth']=$arcadia['conf']['editor.hightlight.'+_name+'.borderwidth']
523
+ end
524
+ @text.tag_configure(_name, h)
525
+ end
526
+
527
+ def pop_up_menu
528
+ @pop_up = TkMenu.new(
529
+ :parent=>@text,
530
+ :tearoff=>1,
531
+ :title => 'Menu'
532
+ )
533
+ @pop_up.insert('end',
534
+ :command,
535
+ :label=>'Save as',
536
+ :hidemargin => false,
537
+ :command=> proc{save_as}
538
+ )
539
+ @pop_up.insert('end',
540
+ :command,
541
+ :label=>'Save',
542
+ :hidemargin => false,
543
+ :command=> proc{save}
544
+ )
545
+
546
+ @pop_up.insert('end',
547
+ :command,
548
+ :label=>'Close',
549
+ :hidemargin => false,
550
+ :command=> proc{@controller.close_editor(self)}
551
+ )
552
+
553
+ @pop_up.insert('end',
554
+ :command,
555
+ :label=>'Close others',
556
+ :hidemargin => false,
557
+ :command=> proc{@controller.close_others_editor(self)}
558
+ )
559
+
560
+ @pop_up.insert('end',
561
+ :command,
562
+ :label=>'Close all',
563
+ :hidemargin => false,
564
+ :command=> proc{@controller.close_all_editor(self)}
565
+ )
566
+
567
+
568
+ @pop_up.insert('end', :separator)
569
+
570
+ @pop_up.insert('end',
571
+ :command,
572
+ :label=>'Color',
573
+ :hidemargin => false,
574
+ :command=> proc{
575
+ @text.insert('insert',Tk.chooseColor)
576
+ }
577
+ )
578
+ @pop_up.insert('end',
579
+ :command,
580
+ :label=>'Font',
581
+ :hidemargin => false,
582
+ :command=> proc{
583
+ @text.insert('insert', $arcadia['action.get.font'].call)
584
+ }
585
+ )
586
+
587
+
588
+ @pop_up.insert('end', :separator)
589
+
590
+ #---- debug menu
591
+ _sub_debug = TkMenu.new(
592
+ :parent=>@pop_up,
593
+ :tearoff=>0,
594
+ :title => 'Debug'
595
+ )
596
+
597
+ _sub_debug.insert('end',
598
+ :command,
599
+ :label=>'Eval selected',
600
+ :hidemargin => false,
601
+ :command=> proc{
602
+ _r = @text.tag_ranges('sel')
603
+ if _r.length>0
604
+ _text=@text.get(_r[0][0],_r[0][1])
605
+ if _text.length > 0
606
+ EditorContract.instance.eval_expression(self, 'text'=>_text)
607
+ end
608
+ end
609
+ }
610
+ )
611
+
612
+ @pop_up.insert('end',
613
+ :cascade,
614
+ :label=>'Debug',
615
+ :menu=>_sub_debug,
616
+ :hidemargin => false
617
+ )
618
+
619
+
620
+ #---- code menu
621
+ _sub_code = TkMenu.new(
622
+ :parent=>@pop_up,
623
+ :tearoff=>0,
624
+ :title => 'Code'
625
+ )
626
+
627
+ _sub_code.insert('end',
628
+ :command,
629
+ :label=>'Show tabs',
630
+ :hidemargin => false,
631
+ :command=> proc{show_tabs}
632
+ )
633
+
634
+
635
+ _sub_code.insert('end',
636
+ :command,
637
+ :label=>'Hide tabs',
638
+ :hidemargin => false,
639
+ :command=> proc{hide_tabs}
640
+ )
641
+
642
+ _sub_code.insert('end',
643
+ :command,
644
+ :label=>'Show spaces',
645
+ :hidemargin => false,
646
+ :command=> proc{show_spaces}
647
+ )
648
+
649
+
650
+ _sub_code.insert('end',
651
+ :command,
652
+ :label=>'Hide spaces',
653
+ :hidemargin => false,
654
+ :command=> proc{hide_spaces}
655
+ )
656
+
657
+
658
+ _sub_code.insert('end',
659
+ :command,
660
+ :label=>'Space to tabs indentation',
661
+ :hidemargin => false,
662
+ :command=> proc{indentation_space_2_tabs}
663
+ )
664
+
665
+ _sub_code.insert('end',
666
+ :command,
667
+ :label=>'Tabs to space indentation',
668
+ :hidemargin => false,
669
+ :command=> proc{indentation_tabs_2_space}
670
+ )
671
+
672
+
673
+ @pop_up.insert('end',
674
+ :cascade,
675
+ :label=>'Code',
676
+ :menu=>_sub_code,
677
+ :hidemargin => false
678
+ )
679
+
680
+
681
+
682
+
683
+ @text.bind("Button-3",
684
+ proc{|x,y|
685
+ _x = TkWinfo.pointerx(@text)
686
+ _y = TkWinfo.pointery(@text)
687
+ @pop_up.popup(_x,_y)
688
+ },
689
+ "%x %y")
690
+ end
691
+
692
+ def unmark_debug(_index)
693
+ @text.tag_remove('debug',_index +' linestart', _index +' +1 lines linestart')
694
+ #@text.tag_remove('debug',_index+' linestart', _index+' lineend')
695
+ end
696
+
697
+ def mark_debug(_index)
698
+ @text.tag_add('debug',_index +' linestart', _index +' +1 lines linestart')
699
+ #@text.tag_add('debug',_index +' linestart', _index +' lineend')
700
+ end
701
+
702
+ def mark_selected(_index)
703
+ @text.tag_remove('selected','1.0', 'end')
704
+ @text.tag_add('selected',_index +' linestart', _index +' +1 lines linestart')
705
+ end
706
+
707
+
708
+ def build_tree_from_source(_source)
709
+ _row = 1
710
+ _liv = 0
711
+ _livs = Array.new
712
+ root = TreeNode.new(nil, 'KRoot'){|_node|
713
+ _node.rif= 'root'
714
+ _node.label=''
715
+ }
716
+ _livs[_liv]=root
717
+ _source.each_line{|line|
718
+ line = "\s"+line.split("#")[0]+"\s"
719
+ m = /[\s\n\t\;]+(module|class|def|if|unless|begin|case|for|while|do)[\s\n\t\;]+/.match(line)
720
+ if m
721
+ index = m.post_match.strip.length - 1
722
+ if m.post_match.strip[index,index]=='{'
723
+ _row = _row +1
724
+ next
725
+ end
726
+ _liv>=0? _liv = _liv + 1:_liv=1
727
+ _pliv = _liv
728
+ _parent = nil
729
+ while (_parent == nil && _pliv>=0)
730
+ _pliv = _pliv -1
731
+ _parent = _livs[_pliv]
732
+ end
733
+ if _parent
734
+ _helptext = m.post_match.strip
735
+ _label = _helptext.split('<')[0]
736
+ if _label == nil || _label.strip.length==0
737
+ _label = _helptext
738
+ end
739
+ if (m[0].strip[0..4] == "class" && m.pre_match.strip.length==0)
740
+ _kind = 'KClass'
741
+ elsif (m[0].strip[0..4] == "class" && m.pre_match.strip.length>0)
742
+ _row = _row +1
743
+ _liv = _liv - 1
744
+ next
745
+ elsif (m[0].strip[0..5] == "module" && m.pre_match.strip.length==0)
746
+ _kind = 'KModule'
747
+ elsif (m[0].strip[0..5] == "module" && m.pre_match.strip.length>0)
748
+ _row = _row +1
749
+ _liv = _liv - 1
750
+ next
751
+ elsif ((m[0].strip[0..4] == "begin")||(m[0].strip[0..3] == "case") ||(m[0].strip[0..4] == "while") || (m[0].strip[0..2] == "for") || (m[0].strip[0..1] == "do") || ((m[0].strip[0..1] == "if" || m[0].strip[0..5] == "unless") && m.pre_match.strip.length==0))
752
+ _row = _row +1
753
+ next
754
+ elsif ((m[0].strip[0..1] == "if" || m[0].strip[0..5] == "unless") && m.pre_match.strip.length>0)
755
+ _row = _row +1
756
+ _liv = _liv - 1
757
+ next
758
+ elsif (m[0].strip[0..2] == "def" && m.pre_match.strip.length==0)
759
+ _kind = 'KDef'
760
+ if _label.include?(_parent.label + '.')
761
+ _kind = 'KDefClass'
762
+ end
763
+ # elsif (m[0].strip[0..10] == "attr_reader" && m.pre_match.strip.length==0)
764
+ # _kind = 'KAttr_reader'
765
+ # _liv = _liv - 1
766
+ # _row = _row +1
767
+ end
768
+
769
+ TreeNode.new(_parent, _kind){|_node|
770
+ _node.label = _label
771
+ _node.helptext = _helptext
772
+ _node.rif = _row.to_s
773
+ _livs[_pliv + 1]=_node
774
+ }
775
+ else
776
+ _row = _row +1
777
+ _liv = _liv - 1
778
+ next
779
+ end
780
+ end
781
+ m_end = /[\s\n\t\;]+end[\s\n\t\;]+/.match(line)
782
+ if m_end
783
+ _liv = _liv - 1
784
+ end
785
+ _row = _row +1
786
+ }
787
+ return root
788
+ end
789
+
790
+ def build_tree_from_node(_node, _label_match=nil)
791
+
792
+ @image_kclass = TkPhotoImage.new('dat' => TREE_NODE_CLASS_GIF)
793
+ @image_kmodule = TkPhotoImage.new('dat' => TREE_NODE_MODULE_GIF)
794
+ @image_kdef = TkPhotoImage.new('dat' => TREE_NODE_DEF_GIF)
795
+ @image_kdefclass = TkPhotoImage.new('dat' => TREE_NODE_DEFCLASS_GIF)
796
+
797
+ _sorted_sons = _node.sons.sort
798
+ for inode in 0.._sorted_sons.length - 1
799
+ _son = _sorted_sons[inode]
800
+ if _son.kind == 'KClass'
801
+ _image = @image_kclass
802
+ elsif _son.kind == 'KModule'
803
+ _image = @image_kmodule
804
+ elsif _son.kind == 'KDef'
805
+ _image = @image_kdef
806
+ elsif _son.kind == 'KDefClass'
807
+ _image = @image_kdefclass
808
+ end
809
+ @tree_exp.insert('end', _son.parent.rif ,_son.rif, {
810
+ 'text' => _son.label ,
811
+ 'helptext' => _son.helptext,
812
+ 'font'=>$arcadia['conf']['editor.explorer_panel.tree.font'],
813
+ 'image'=> _image
814
+ }
815
+ )
816
+ if (_label_match) && (_label_match.strip == _son.label.strip)
817
+ @selected = _son
818
+ end
819
+ build_tree_from_node(_son, _label_match)
820
+ end
821
+ end
822
+
823
+ def build_tree(_sel=nil)
824
+ if _sel
825
+ _label_sel = @tree_exp.itemcget(_sel,'text')
826
+ end
827
+
828
+ #clear tree
829
+ begin
830
+ @tree_exp.delete(@tree_exp.nodes('root'))
831
+ rescue Exception
832
+ # workaround on windows
833
+ @tree_exp.delete(@tree_exp.nodes('root'))
834
+ end
835
+
836
+
837
+ #(re)build tree
838
+ _txt = @text.get('1.0','end')
839
+ @root = build_tree_from_source(_txt)
840
+ @selected = nil
841
+ build_tree_from_node(@root, _label_sel)
842
+ if @selected
843
+ @tree_exp.selection_add(@selected.rif)
844
+ @tree_exp.open_tree(@selected.parent.rif)
845
+ @tree_exp.see(@selected.rif)
846
+ end
847
+ end
848
+
849
+ def insert_popup_menu_item(_where, *args)
850
+ @pop_up.insert(_where,*args)
851
+ end
852
+
853
+ def text_value
854
+ return @text.value
855
+ end
856
+
857
+ # vertical scrollbar : ON/OFF
858
+ def vscroll(mode)
859
+ st = TkGrid.info(@v_scroll)
860
+ if mode && st == [] then
861
+ @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns')
862
+ elsif !mode && st != [] then
863
+ @v_scroll.ungrid
864
+ end
865
+ self
866
+ end
867
+
868
+ # horizontal scrollbar : ON/OFF
869
+ def hscroll(mode, wrap_mode="char")
870
+ st = TkGrid.info(@h_scroll)
871
+ if mode && st == [] then
872
+ @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew')
873
+ @text.configure('wrap'=> 'none')
874
+ elsif !mode && st != [] then
875
+ @h_scroll.ungrid
876
+ @text.configure('wrap'=> wrap_mode)
877
+ end
878
+ self
879
+ end
880
+
881
+ def rowcol(_index, _gap_row = nil, _gap_col = nil)
882
+ _riga, _colonna = _index.split('.')
883
+ if _gap_row == nil
884
+ _riga = '1'
885
+ _gap_row = 0
886
+ end
887
+ if _gap_col == nil
888
+ _colonna = '0'
889
+ _gap_col = 0
890
+ end
891
+ return (_riga.to_i + _gap_row).to_s + '.'+ (_colonna.to_i + _gap_col).to_s
892
+ end
893
+
894
+ def find_and_set_tag(_re, _row, _txt, _tag, _tag_rem = nil)
895
+ m = _re.match(_txt)
896
+ _end = 0
897
+ if m && @is_tag_bold[_tag]
898
+ @is_line_bold[_row]=true
899
+ end
900
+ while m
901
+ _txt = m.post_match
902
+ _ibegin = _row.to_s+'.'+(m.begin(0)+_end).to_s
903
+ _end = m.end(0) + _end
904
+ _iend = _row.to_s+'.'+(_end.to_s)
905
+ if _tag_rem
906
+ _tag_rem.each {|value|
907
+ @text.tag_remove(value,_ibegin, _iend)
908
+ }
909
+ end
910
+ @text.tag_add(_tag,_ibegin, _iend)
911
+ m = _re.match(_txt)
912
+ end
913
+ end
914
+
915
+ def show_spaces
916
+ @spaces_show = true
917
+ _row = 1
918
+ @text.value.each{|_line|
919
+ show_chars_line(_row, _line, /[ ^\t]\s*/, 'spaces')
920
+ _row = _row+1
921
+ }
922
+ end
923
+
924
+
925
+ def show_tabs
926
+ @tabs_show = true
927
+ _row = 1
928
+ @text.value.each{|_line|
929
+ show_chars_line(_row, _line, /\t/, 'tabs')
930
+ _row = _row+1
931
+ }
932
+ end
933
+
934
+
935
+ def show_chars_line(_row, _line, _re, _tag)
936
+ m = _re.match(_line)
937
+ _end = 0
938
+ while m
939
+ _txt = m.post_match
940
+ _ibegin = _row.to_s+'.'+(m.begin(0)+_end).to_s
941
+ _end = m.end(0) + _end
942
+ _iend = _row.to_s+'.'+(_end.to_s)
943
+ @text.tag_add(_tag,_ibegin, _iend)
944
+ m = _re.match(_txt)
945
+ end
946
+ end
947
+
948
+ def indentation_space_2_tabs(_n_space=2)
949
+ _row = 1
950
+ @text.value.each{|_line|
951
+ m = /\s*/.match(_line)
952
+ _end = 0
953
+ if m && m.begin(0)==0
954
+ _s = m[0]
955
+ if !_s.include?("\n") && !_s.include?("\t")
956
+ _ibegin = _row.to_s+'.0'
957
+ _iend = _row.to_s+'.'+m.end(0).to_s
958
+ _n_tab = (_s.length / _n_space).round
959
+ @text.delete(_ibegin, _iend)
960
+ @text.insert(_ibegin,"\t"*_n_tab )
961
+ end
962
+ end
963
+ _row = _row+1
964
+ }
965
+ check_modify
966
+ end
967
+
968
+ def indentation_tabs_2_space(_n_space=2)
969
+ _row = 1
970
+ @text.value.each{|_line|
971
+ m = /\t*/.match(_line)
972
+ _end = 0
973
+ if m && m.begin(0)==0
974
+ _s = m[0]
975
+ if !_s.include?("\n")
976
+ _ibegin = _row.to_s+'.0'
977
+ _iend = _row.to_s+'.'+m.end(0).to_s
978
+ @text.delete(_ibegin, _iend)
979
+ @text.insert(_ibegin,"\s"*_s.length*_n_space )
980
+ end
981
+ end
982
+ _row = _row+1
983
+ }
984
+ check_modify
985
+ end
986
+
987
+
988
+ def hide_tabs
989
+ @text.tag_remove('tabs','1.0', 'end')
990
+ @tabs_show = false
991
+ end
992
+
993
+ def hide_spaces
994
+ @text.tag_remove('spaces','1.0', 'end')
995
+ @spaces_show = false
996
+ end
997
+
998
+
999
+ def modified?
1000
+ return !(@buffer === text_value)
1001
+ end
1002
+
1003
+ def set_modify
1004
+ if !@set_mod
1005
+ @set_mod = true
1006
+ @controller.change_tab_set_modify(@page_frame)
1007
+ end
1008
+ end
1009
+
1010
+ def reset_modify
1011
+ @controller.change_tab_reset_modify(@page_frame)
1012
+ @set_mod = false
1013
+ @file_last_access_time = File.mtime(@file) if @file
1014
+ end
1015
+
1016
+ def highlightline(_row, _line, _check_mod = false)
1017
+ if _check_mod
1018
+ check_modify
1019
+ end
1020
+ _txt = _line
1021
+ _end = 0
1022
+
1023
+ #if line is a comment
1024
+ m_c = /#/.match(_txt)
1025
+ if m_c then
1026
+ _ibegin = _row.to_s+'.'+(m_c.begin(0)).to_s
1027
+ _iend = _row.to_s+'.'+(_line.length - 1).to_s
1028
+ @text.tag_add('comment',_ibegin, _iend)
1029
+ _txt = m_c.pre_match
1030
+ end
1031
+ arem = Array.new
1032
+ if _txt.strip.length > 0
1033
+ find_and_set_tag(@re_number, _row, _txt, 'number')
1034
+ arem << 'number'
1035
+ find_and_set_tag(@re_method_name, _row, _txt, 'method_name',arem)
1036
+ arem << 'method_name'
1037
+ find_and_set_tag(@re_class_name, _row, _txt, 'class_name',arem)
1038
+ arem << 'class_name'
1039
+ find_and_set_tag(@re_module_name, _row, _txt, 'module_name',arem)
1040
+ arem << 'module_name'
1041
+ find_and_set_tag(@re_keyword, _row, _txt, 'keyword',arem)
1042
+ arem << 'keyword'
1043
+ find_and_set_tag(@re_instance_variable, _row, _txt, 'instance_variable',arem)
1044
+ arem << 'instance_variable'
1045
+ find_and_set_tag(@re_operator, _row, _txt, 'operator')
1046
+ arem << 'operator'
1047
+ find_and_set_tag(@re_string, _row, _txt, 'string', arem)
1048
+ end
1049
+ find_and_set_tag(/\t/, _row, _txt, 'tabs', arem) if @tabs_show
1050
+ find_and_set_tag(/[ ^\t]\s*/, _row, _txt, 'spaces', arem) if @spaces_show
1051
+ end
1052
+
1053
+ def rehighlightline(_row)
1054
+ _ibegin = _row.to_s+'.0'
1055
+ _iend = (_row+1).to_s+'.0'
1056
+ @text.tag_remove('keyword',_ibegin, _iend)
1057
+ @text.tag_remove('comment',_ibegin, _iend)
1058
+ @text.tag_remove('string',_ibegin, _iend)
1059
+ @text.tag_remove('number',_ibegin, _iend)
1060
+ @text.tag_remove('operator',_ibegin, _iend)
1061
+ @text.tag_remove('capitalize',_ibegin, _iend)
1062
+ _line = @text.get(_ibegin, _iend)
1063
+ highlightline(_row, _line)
1064
+ end
1065
+
1066
+ def row(_index='insert')
1067
+ _row = @text.index(_index).split('.')[0].to_i
1068
+ print "def row(_index='insert')",_row.to_s,"\n"
1069
+ return _row
1070
+ end
1071
+
1072
+ def do_line_update
1073
+ #renum in @text_line_num the portion of visibled screen of @text
1074
+ if @text_line_num
1075
+ #p '@is_line_bold='+@is_line_bold.to_s
1076
+ #incr = 1 + (@font_metrics[2][1]+@font_metrics_bold[2][1]) / 4
1077
+ line_begin = @text.index('@0,0').split('.')[0].to_i
1078
+ line_end = @text.index('@0,'+TkWinfo.height(@text).to_s).split('.')[0].to_i + 1
1079
+ # breakpoint
1080
+ b = @controller.breakpoint_lines_on_file(@file)
1081
+ @text_line_num.delete('1.0','end')
1082
+ for j in line_begin...line_end
1083
+ nline = j.to_s.rjust(6)
1084
+ _index = @text_line_num.index('end')
1085
+ if @highlighting && @is_line_bold[j]
1086
+ @text_line_num.insert('end', nline+"\n",'bold_case')
1087
+ else
1088
+ @text_line_num.insert('end', nline+"\n")
1089
+ end
1090
+ if b.include?(j.to_s)
1091
+ @text_line_num.tag_add('breakpoint',_index+' -1 lines',_index+' -1 lines lineend')
1092
+ # @text_line_num.tag_add('breakpoint',_index+' -1 lines',_index+' -1 lines + 1 chars')
1093
+ end
1094
+ end
1095
+
1096
+ if @highlighting
1097
+ _zone_begin = ((line_begin) / @highlight_zone_length).to_i + 1
1098
+ _zone_end = ((line_end) / @highlight_zone_length).to_i + 1
1099
+
1100
+ (_zone_begin >=@last_zone_begin)?_zone_begin.upto(_zone_end+1){|_zone|
1101
+ highlight_zone(_zone)
1102
+ }:_zone_end.downto(_zone_begin-1){|_zone|
1103
+ highlight_zone(_zone)
1104
+ }
1105
+ @last_line_begin = line_begin
1106
+ @last_line_end = line_end
1107
+ @last_zone_begin = _zone_begin
1108
+ @last_zone_end = _zone_end
1109
+ end
1110
+ end
1111
+ end
1112
+
1113
+ def highlight_zone(_zone)
1114
+ if !@highlight_zone[_zone]
1115
+ _b = @highlight_zone_length*(_zone - 1)
1116
+ _e = @highlight_zone_length*(_zone) + 1
1117
+ for j in _b..._e
1118
+ rehighlightline(j)
1119
+ end
1120
+ @highlight_zone[_zone] = true
1121
+ end
1122
+ end
1123
+
1124
+ def text_see(_index=nil)
1125
+ if _index
1126
+ @text.see(_index)
1127
+ end
1128
+ end
1129
+
1130
+ def text_insert_index
1131
+ @text.index('insert')
1132
+ end
1133
+
1134
+ def text_insert(index, chars, *tags, &b)
1135
+ if block_given?
1136
+ instance_eval(&b)
1137
+ end
1138
+ _index = @text.index(index)
1139
+ _row, _col = _index.split('.')
1140
+ _row = (_row.to_i - 1).to_s
1141
+ chars.each_line {|line|
1142
+ @text.insert(_row+'.0', line, *tags)
1143
+ if !defined?(m_begin)||(m_begin == nil)
1144
+ m_begin = /=begin/.match(line)
1145
+ end
1146
+ if @highlighting
1147
+ if m_begin &&(m_begin.begin(0)==0)
1148
+ _ibegin = _row+'.0'
1149
+ _iend = _row+'.'+(line.length - 1).to_s
1150
+ @text.tag_add('comment',_ibegin, _iend)
1151
+ else
1152
+ highlightline(_row.to_i, line, false)
1153
+ end
1154
+ end
1155
+ _row = (_row.to_i + 1).to_s
1156
+ }
1157
+ if defined?(_edit_reset)
1158
+ if _edit_reset
1159
+ @text.edit_reset
1160
+ end
1161
+ else
1162
+ @text.edit_reset
1163
+ end
1164
+ end
1165
+
1166
+ def save
1167
+ if !@file
1168
+ save_as
1169
+ else
1170
+ f = File.new(@file, "w")
1171
+ begin
1172
+ if f
1173
+ f.syswrite(text_value)
1174
+ @buffer = text_value
1175
+ reset_modify
1176
+ end
1177
+ ensure
1178
+ f.close unless f.nil?
1179
+ end
1180
+ EditorContract.instance.file_saved(self,'file' =>@file)
1181
+ end
1182
+ end
1183
+
1184
+ def save_as
1185
+ @file = Tk.getSaveFile("filetypes"=>[["Ruby Files", [".rb", ".rbw"]]])
1186
+ @file = nil if @file == "" # cancelled
1187
+ if @file
1188
+ save
1189
+ @controller.change_file_name(@page_frame, @file)
1190
+ EditorContract.instance.file_created(self, 'file'=>@file)
1191
+ end
1192
+ end
1193
+
1194
+ def check_modify
1195
+ if modified?
1196
+ set_modify if !@set_mod
1197
+ else
1198
+ reset_modify
1199
+ end
1200
+ end
1201
+
1202
+ def check_file_last_access_time
1203
+ if @file && @file_last_access_time
1204
+
1205
+ ftime = File.mtime(@file)
1206
+ if @file_last_access_time != ftime
1207
+ msg = 'File "'+@file+'" is changed! Reload?'
1208
+ if Tk.messageBox('icon' => 'error', 'type' => 'yesno',
1209
+ 'title' => '(Arcadia) Libs', 'parent' => @text,
1210
+ 'message' => msg) == 'yes'
1211
+ @text.delete('1.0','end')
1212
+ load_file(@file)
1213
+ else
1214
+ @file_last_access_time = ftime
1215
+ end
1216
+ end
1217
+ end
1218
+ end
1219
+
1220
+ def init_editing(_ext='rb')
1221
+ case _ext
1222
+ when 'rb'
1223
+ @fm = AGTkVSplittedFrames.new(@page_frame,150)
1224
+ @fm1 = AGTkVSplittedFrames.new(@fm.right_frame,60)
1225
+ initialize_text(@fm1.right_frame)
1226
+ initialize_text_binding
1227
+ initialize_highlight
1228
+ initialize_line_number(@fm1.left_frame)
1229
+ initialize_tree(@fm.left_frame)
1230
+ when nil
1231
+ @fm1 = AGTkVSplittedFrames.new(@page_frame,60)
1232
+ initialize_text(@fm1.right_frame)
1233
+ initialize_text_binding
1234
+ initialize_highlight
1235
+ initialize_line_number(@fm1.left_frame)
1236
+ else
1237
+ @fm1 = AGTkVSplittedFrames.new(@page_frame,60)
1238
+ initialize_text(@fm1.right_frame)
1239
+ initialize_text_binding
1240
+ initialize_line_number(@fm1.left_frame)
1241
+ end
1242
+ end
1243
+
1244
+ def file_extension(_filename=nil)
1245
+ if _filename
1246
+ _m = /(.*\.)(.*$)/.match(File.basename(_filename))
1247
+ end
1248
+ _ret = (_m && _m.length > 1)?_m[2]: nil
1249
+ end
1250
+
1251
+ def load_file(_filename = nil)
1252
+ #if filename is nil then open a new tab
1253
+ @file = _filename
1254
+ if _filename
1255
+ #init_editing(file_extension(_filename))
1256
+ File::open(_filename,'r'){ |file|
1257
+ @text.insert('end',file.readlines.collect!{| line | line.chomp+"\n" }.to_s)
1258
+ }
1259
+ end
1260
+ reset
1261
+ refresh
1262
+ end
1263
+
1264
+ def reset
1265
+ @buffer = text_value
1266
+ reset_modify
1267
+ @text.edit_reset
1268
+ end
1269
+
1270
+ def refresh
1271
+ build_tree if @classbrowsing
1272
+ end
1273
+ end
1274
+
1275
+ class AgMultiEditorView
1276
+ attr_reader :enb
1277
+ def initialize(parent=nil)
1278
+ @enb = Tk::BWidget::NoteBook.new(parent){
1279
+ tabbevelsize 0
1280
+ internalborderwidth 2
1281
+ activeforeground 'red'
1282
+ activebackground 'yellow'
1283
+ #background 'black'
1284
+ borderwidth 1
1285
+ side $arcadia['conf']['editor.tabs.side']
1286
+ font $arcadia['conf']['editor.tabs.font']
1287
+ pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
1288
+ }
1289
+ end
1290
+
1291
+ end
1292
+
1293
+ class AgMultiEditor < ArcadiaExt
1294
+ attr_reader :breakpoints
1295
+ attr_reader :splitted_frame
1296
+ def before_build
1297
+ ArcadiaContractListener.new(self, DebugContract, :do_debug_event)
1298
+ ArcadiaContractListener.new(self, EditorContract, :do_editor_event)
1299
+ ArcadiaContractListener.new(self, MainContract, :do_main_event)
1300
+ end
1301
+
1302
+ def build
1303
+ if @arcadia.layout.headed?
1304
+ title_frame = @arcadia.layout.domain(conf('frame'))['root']
1305
+ #@close_button = title_frame.add_button(nil,nil,TAB_CLOSE_GIF,'left')
1306
+ end
1307
+
1308
+ #@splitted_frame = AGTkOSplittedFrames.new(self.frame,20)
1309
+ #@main_frame = AgMultiEditorView.new(@splitted_frame.bottom_frame)
1310
+ @main_frame = AgMultiEditorView.new(self.frame)
1311
+ #@close_button.bind('1',proc{close_raised})
1312
+ @tabs_file =Hash.new
1313
+ @tabs_editor =Hash.new
1314
+ @breakpoints =Array.new
1315
+ create_find
1316
+ pop_up_menu
1317
+ end
1318
+
1319
+ def after_build
1320
+ self.open_last_files
1321
+ end
1322
+
1323
+ def pop_up_menu
1324
+ @pop_up = TkMenu.new(
1325
+ :parent=>@main_frame.enb,
1326
+ :tearoff=>0,
1327
+ :title => 'Menu'
1328
+ )
1329
+ @pop_up.insert('end',
1330
+ :command,
1331
+ :label=>'...',
1332
+ :state=>'disabled',
1333
+ :background=>'blue',
1334
+ :font => conf('font.bold'),
1335
+ :hidemargin => true
1336
+ )
1337
+ @c = @pop_up.insert('end',
1338
+ :command,
1339
+ :label=>'Close',
1340
+ :font => conf('font'),
1341
+ :hidemargin => false,
1342
+ :command=> proc{
1343
+ if @selected_tab_name_from_popup != nil
1344
+ _e = @tabs_editor[@selected_tab_name_from_popup]
1345
+ self.close_editor(_e)
1346
+ end
1347
+ }
1348
+ )
1349
+ @c = @pop_up.insert('end',
1350
+ :command,
1351
+ :label=>'Close others',
1352
+ :font => conf('font'),
1353
+ :hidemargin => false,
1354
+ :command=> proc{
1355
+ if @selected_tab_name_from_popup != nil
1356
+ _e = @tabs_editor[@selected_tab_name_from_popup]
1357
+ self.close_others_editor(_e)
1358
+ end
1359
+ }
1360
+ )
1361
+ @c = @pop_up.insert('end',
1362
+ :command,
1363
+ :label=>'Close all',
1364
+ :font => conf('font'),
1365
+ :hidemargin => false,
1366
+ :command=> proc{
1367
+ if @selected_tab_name_from_popup != nil
1368
+ _e = @tabs_editor[@selected_tab_name_from_popup]
1369
+ self.close_all_editor(_e)
1370
+ end
1371
+ }
1372
+ )
1373
+
1374
+ @main_frame.enb.tabbind("Button-3",
1375
+ proc{|*x|
1376
+ _x = TkWinfo.pointerx(@main_frame.enb)
1377
+ _y = TkWinfo.pointery(@main_frame.enb)
1378
+ @selected_tab_name_from_popup = x[0].split(':')[0]
1379
+ _index = @main_frame.enb.index(@selected_tab_name_from_popup)
1380
+ if _index == -1
1381
+ @selected_tab_name_from_popup = 'ff'+@selected_tab_name_from_popup
1382
+ _index = @main_frame.enb.index(@selected_tab_name_from_popup)
1383
+ end
1384
+ if _index != -1
1385
+ _file = @main_frame.enb.itemcget(@selected_tab_name_from_popup, 'text')
1386
+ @pop_up.entryconfigure(0, 'label'=>_file)
1387
+ @pop_up.popup(_x,_y)
1388
+ end
1389
+ })
1390
+ end
1391
+
1392
+
1393
+ def do_debug_event(_event)
1394
+ #@arcadia.outln('_sender ----> '+_sender.to_s)
1395
+ #@arcadia.outln('_event.signature ----> '+_event.signature)
1396
+ case _event.signature
1397
+ when DebugContract::DEBUG_BEGIN
1398
+ self.debug_begin
1399
+ when DebugContract::DEBUG_END
1400
+ self.debug_end
1401
+ when DebugContract::DEBUG_STEP
1402
+ if _event.context.file
1403
+ self.open_file_in_debug(_event.context.file, _event.context.line)
1404
+ end
1405
+ end
1406
+ end
1407
+
1408
+ def do_editor_event(_event)
1409
+ case _event.signature
1410
+ when EditorContract::OPEN_FILE
1411
+ if _event.context.file
1412
+ if _event.context.line
1413
+ _index = _event.context.line.to_s+'.0'
1414
+ end
1415
+ self.open_file(_event.context.file, _index)
1416
+ _event.handled(self)
1417
+ end
1418
+ when EditorContract::CLOSE_FILE
1419
+ if _event.context.file
1420
+ self.close_file(_event.context.file)
1421
+ _event.handled(self)
1422
+ end
1423
+ when EditorContract::SAVE_FILE_RAISED
1424
+ self.raised.save
1425
+ _event.handled(self)
1426
+ when EditorContract::SAVE_FILE
1427
+ if _event.context.file
1428
+ self.save_file(_event.context.file)
1429
+ _event.handled(self)
1430
+ end
1431
+ when EditorContract::SAVE_AS_FILE_RAISED
1432
+ self.raised.save_as
1433
+ _event.handled(self)
1434
+ when EditorContract::SAVE_AS_FILE
1435
+ if _event.context.file
1436
+ self.save_as_file(_event.context.file)
1437
+ _event.handled(self)
1438
+ end
1439
+ when EditorContract::OPEN_TEXT
1440
+ if _event.context.title
1441
+ _tab_name = self.tab_name(_event.context.title)
1442
+ self.open_buffer(_tab_name, _event.context.title)
1443
+ _e = @tabs_editor[_tab_name]
1444
+ _e.text_insert('end',_event.context.text) if _event.context.text
1445
+ _e.reset
1446
+ _e.refresh
1447
+ add_reverse_item(_e)
1448
+ _event.handled(self)
1449
+ end
1450
+ when EditorContract::SHOW_SEARCH_DIALOG
1451
+ @find.show
1452
+ when EditorContract::SHOW_GOTO_LINE_DIALOG
1453
+ @find.show_go_to_line_dialog
1454
+ end
1455
+ end
1456
+
1457
+ def xy_insert
1458
+ _text = self.raised.text
1459
+ _index_now = _text.index('insert')
1460
+ _rx, _ry, _widht, _heigth = _text.bbox(_index_now);
1461
+ _x = _rx + TkWinfo.rootx(_text)
1462
+ _y = _ry + TkWinfo.rooty(_text) + TkFont.new(conf('font')).metrics[2][1]
1463
+ _xroot = _x - TkWinfo.rootx(@arcadia.layout.root)
1464
+ _yroot = _y - TkWinfo.rooty(@arcadia.layout.root)
1465
+ return _xroot, _yroot
1466
+ end
1467
+
1468
+
1469
+
1470
+ def raise_complete_code(_context)
1471
+ # delete the file used for completion
1472
+ if File.exist?(_context.file) && _context.file.include?('~~')
1473
+ File.delete(_context.file)
1474
+ end
1475
+ @raised_listbox.destroy if @raised_listbox != nil
1476
+
1477
+ _text = self.raised.text
1478
+ _index_call = _context.line+'.'+_context.col
1479
+ _index_now = _text.index('insert')
1480
+ if _index_call == _index_now
1481
+ _target = _text.get('insert - 1 chars wordstart','insert')
1482
+ if _target.length > 0 && _target != '.'
1483
+ extra_len = _target.length.+@
1484
+ _begin_index = _index_now<<' - '<<extra_len.to_s<<' chars'
1485
+ _text.tag_add('sel', _begin_index, _index_now)
1486
+ else
1487
+ _begin_index = _index_now
1488
+ extra_len = 0
1489
+ end
1490
+ if _context.candidates.length > 1
1491
+ _rx, _ry, _widht, heigth = _text.bbox(_begin_index);
1492
+ _x = _rx + TkWinfo.rootx(_text)
1493
+ _y = _ry + TkWinfo.rooty(_text) + TkFont.new(conf('font')).metrics[2][1]
1494
+
1495
+ _xroot = _x - TkWinfo.rootx(@arcadia.layout.root)
1496
+ _yroot = _y - TkWinfo.rooty(@arcadia.layout.root)
1497
+
1498
+ _max_height = TkWinfo.screenheight(@arcadia.layout.root) - _y - 5
1499
+
1500
+ @raised_listbox = TkListbox.new(@arcadia.layout.root,
1501
+ 'takefocus'=>true,
1502
+ :background=>conf('color.background'),
1503
+ :foreground=>conf('color.foreground'),
1504
+ :selectbackground=>'yellow',
1505
+ :selectforeground=>'red',
1506
+ :activestyle=>'none',
1507
+ :font => conf('font'),
1508
+ :borderwidth=>1
1509
+ )
1510
+ _font = TkFont.new(conf('font'))
1511
+ _char_height = _font.metrics[2][1]
1512
+ _width = 0
1513
+ _docs_entries = Hash.new
1514
+ _context.candidates.each{|value|
1515
+ _key, _doc = value.split
1516
+ _docs_entries[_key]= _doc
1517
+ @raised_listbox.insert('end', _key)
1518
+ _temp_width = _font.measure(_key) + _font.measure('X')
1519
+ _width = _temp_width if _temp_width > _width
1520
+ }
1521
+ _height = (_context.candidates.length+1)*_char_height
1522
+ _height = _max_height if _height > _max_height
1523
+ @raised_listbox.place('x'=>_xroot,'y'=>_yroot, 'width'=>_width, 'height'=>_height)
1524
+
1525
+ @raised_listbox.focus
1526
+ @raised_listbox.bind_append('KeyPress'){|e|
1527
+ case e.keysym
1528
+ when 'Escape'
1529
+ @raised_listbox.destroy
1530
+ #_menu.destroy
1531
+ Tk.callback_break
1532
+ when 'Return'
1533
+ _value = @raised_listbox.get('active')
1534
+ _text.delete(_begin_index,'insert')
1535
+ _text.insert('insert',_value)
1536
+ @raised_listbox.destroy
1537
+ #_menu.destroy
1538
+ Tk.callback_break
1539
+ when 'F1'
1540
+ _key = @raised_listbox.get('active')
1541
+ _x, _y = xy_insert
1542
+ EditorContract.instance.doc_code(self, 'doc_entry'=>_docs_entries[_key], 'xdoc'=>_x, 'ydoc'=>_y)
1543
+ end
1544
+ }
1545
+ elsif _context.candidates.length == 1 && _context.candidates[0].length>0
1546
+ _text.delete(_begin_index,'insert');
1547
+ _text.insert('insert',_context.candidates[0].split[0])
1548
+ end
1549
+ end
1550
+ end
1551
+
1552
+ def do_main_event(_event)
1553
+ case _event.signature
1554
+ when MainContract::EVENT_HANDLED
1555
+ _cause = _event.context.caused_by
1556
+ if _cause.signature == EditorContract::COMPLETE_CODE &&
1557
+ _cause.context.sender == self.raised
1558
+ raise_complete_code(_cause.context)
1559
+ elsif _cause.signature == EditorContract::DOC_CODE && _cause.context.file != nil
1560
+ # delete the file used for completion
1561
+ if File.exist?(_cause.context.file) && _cause.context.file.include?('~~')
1562
+ File.delete(_cause.context.file)
1563
+ end
1564
+ end
1565
+ end
1566
+ end
1567
+
1568
+ def add_reverse_item(_editor)
1569
+ code2form = proc{
1570
+ Revparsel.new(_editor.text_value)
1571
+ self.close_editor(_editor, false)
1572
+ InspectorContract.instance.raise_last_widget(self)
1573
+ }
1574
+ _editor.insert_popup_menu_item('end',
1575
+ :command,
1576
+ :label=>'View as form',
1577
+ :hidemargin => false,
1578
+ :command=> code2form
1579
+ )
1580
+
1581
+ end
1582
+
1583
+ # def editor_state
1584
+ # r = EditorContract::SObj.new
1585
+ # r.raised_file = self.raised.file
1586
+ # r.breakpoints = @breakpoints
1587
+ # return r
1588
+ # end
1589
+
1590
+ def get_find
1591
+ @find
1592
+ end
1593
+
1594
+ def create_find
1595
+ #find_frame = @arcadia.layout.register_panel(conf('find.frame'),'Find', 'Find')
1596
+ # @find = Find.new(@splitted_frame.top_frame, self)
1597
+ @find = Find.new(@arcadia.layout.root, self)
1598
+ @find.on_close=proc{@find.hide}
1599
+ @find.hide
1600
+ end
1601
+
1602
+ def finalize
1603
+ _files =''
1604
+ @tabs_editor.each_value{|editor|
1605
+ _files=_files+'|'+ editor.file if editor.file != nil
1606
+ close_editor(editor)
1607
+ }
1608
+ @arcadia['pers']['editor.files.open']=_files
1609
+ end
1610
+
1611
+ def raised
1612
+ _page = @main_frame.enb.raise
1613
+ return @tabs_editor[_page]
1614
+ end
1615
+
1616
+ def close_raised
1617
+ close_editor(@tabs_editor[@main_frame.enb.raise])
1618
+
1619
+ #_page = @main_frame.enb.raise
1620
+ #_editor = @tabs_editor[_page]
1621
+ #_row = _editor.text_insert_index.split('.')[0].strip.to_i
1622
+ #close_editor(_editor)
1623
+ end
1624
+
1625
+ def breakpoint_add(_file,_line)
1626
+ EditorContract.instance.breakpoint_created(self, 'file'=>_file, 'line'=>_line)
1627
+ @breakpoints << {:file=>_file,:line=>_line}
1628
+ end
1629
+
1630
+ def breakpoint_del(_file,_line)
1631
+ EditorContract.instance.breakpoint_deleted(self, 'file'=>_file, 'line'=>_line)
1632
+ @breakpoints.delete_if{|b| (b[:file]==_file && b[:line]==_line)}
1633
+ end
1634
+
1635
+ def breakpoint_lines_on_file(_file)
1636
+ result = Array.new
1637
+ @breakpoints.each{|value|
1638
+ if value[:file]==_file
1639
+ result << value[:line]
1640
+ end
1641
+ }
1642
+ return result
1643
+ end
1644
+
1645
+ def open_last_files
1646
+ if $arcadia['pers']['editor.files.open']
1647
+ _files_index =$arcadia['pers']['editor.files.open'].split("|")
1648
+ _files_index.each{|value|
1649
+ _file,_index = value.split(';')
1650
+ if _file
1651
+ open_file(_file,_index)
1652
+ end
1653
+ }
1654
+ end
1655
+ self
1656
+ end
1657
+
1658
+ def bookmark_add(_file, _index)
1659
+ if @bookmarks == nil
1660
+ @bookmarks = Array.new
1661
+ @bookmarks_index = - 1
1662
+ else
1663
+ _cur_file, _cur_index = @bookmarks[@bookmarks_index]
1664
+ if _cur_file == _file && _cur_index == _index
1665
+ #@arcadia.outln('uguale ----> '+_file+':'+_index)
1666
+ return
1667
+ end
1668
+ @bookmarks = @bookmarks[0..@bookmarks_index]
1669
+ end
1670
+ @bookmarks << [_file, _index]
1671
+ @bookmarks_index = @bookmarks.length - 1
1672
+ #@arcadia.outln('add ----> '+_file+':'+_index)
1673
+ end
1674
+
1675
+ def bookmark_clear
1676
+ @bookmarks.clear
1677
+ @bookmarks_index = - 1
1678
+ end
1679
+
1680
+ def bookmark_next
1681
+ return if @bookmarks == nil || @bookmarks_index >= @bookmarks.length - 1
1682
+ bookmark_move(+1)
1683
+ end
1684
+
1685
+ def bookmark_move(_n=0)
1686
+ @bookmarks_index = @bookmarks_index + _n
1687
+ #Tk.messageBox('message'=>@bookmarks_index.to_s)
1688
+ _file, _index = @bookmarks[@bookmarks_index]
1689
+ _line, _col = _index.split('.') if _index
1690
+ open_file(_file, _index)
1691
+ #openfile(@bookmarks[@bookmarks_index])
1692
+ end
1693
+
1694
+
1695
+ def bookmark_prev
1696
+ return if @bookmarks == nil || @bookmarks_index <= 0
1697
+ bookmark_move(-1)
1698
+ end
1699
+
1700
+
1701
+ def get_tab_from_name(_name=nil)
1702
+ return @main_frame.enb.get_frame(_name)
1703
+ # if _name
1704
+ # @tabs_name.each{
1705
+ # |key,value|
1706
+ # if value.to_s==_name.to_s
1707
+ # return key
1708
+ # end
1709
+ # }
1710
+ # return nil
1711
+ # end
1712
+ end
1713
+
1714
+ def change_tab_set_modify(_tab)
1715
+ _new_name = '(...)'+@main_frame.enb.itemcget(page_name(_tab), 'text')
1716
+ change_tab_title(_tab, _new_name)
1717
+ end
1718
+
1719
+ def page_name(_page_frame)
1720
+ TkWinfo.appname(_page_frame).sub('f','')
1721
+ end
1722
+
1723
+ def change_tab_reset_modify(_tab)
1724
+ #_new_name = @main_frame.enb.itemcget(@tabs_name[_tab], 'text').gsub!("(...)",'')
1725
+ _new_name = @main_frame.enb.itemcget(page_name(_tab), 'text').gsub!("(...)",'')
1726
+ if _new_name
1727
+ change_tab_title(_tab, _new_name)
1728
+ end
1729
+ end
1730
+
1731
+ def change_tab_title(_tab, _new_text)
1732
+ @main_frame.enb.itemconfigure(page_name(_tab), 'text'=> _new_text)
1733
+ end
1734
+
1735
+ def change_file_name(_tab, _new_file)
1736
+ _new_label = File.basename(_new_file)
1737
+ change_tab_title(_tab, _new_label)
1738
+ @tabs_file[page_name(_tab)] = _new_file
1739
+ end
1740
+
1741
+ def debug_begin
1742
+ if @editors_in_debug != nil
1743
+ @editors_in_debug.clear
1744
+ else
1745
+ @editors_in_debug = Array.new
1746
+ end
1747
+ end
1748
+
1749
+ def debug_end
1750
+ debug_reset
1751
+ @editors_in_debug.each{|e|
1752
+ close_editor(e)
1753
+ }
1754
+ end
1755
+
1756
+ def debug_reset
1757
+ if @last_index && @last_e
1758
+ @last_e.unmark_debug(@last_index)
1759
+ end
1760
+ end
1761
+
1762
+ def open_file_in_debug(_filename=nil, _line=nil)
1763
+ debug_reset
1764
+ if _filename && _line
1765
+
1766
+ @last_index = _line.to_s+'.0'
1767
+ _editor_exist = editor_exist?(_filename)
1768
+ @last_e = open_file(_filename, @last_index, false)
1769
+ if !_editor_exist
1770
+ @editors_in_debug << @last_e
1771
+ end
1772
+ @last_e.mark_debug(@last_index) if @last_e
1773
+
1774
+ end
1775
+ end
1776
+
1777
+ def do_buffer_raise(_name, _title='...')
1778
+ _index = @main_frame.enb.index(_name)
1779
+ _new_caption = '...'
1780
+ if _index != -1
1781
+ #_name = @main_frame.enb.pages(_index)
1782
+ #_tab = get_tab_from_name(_name)
1783
+ #@main_frame.enb.raise(_name)
1784
+ _e = @tabs_editor[_name]
1785
+ if _e && _e.file != nil
1786
+ _new_caption = _e.file
1787
+ @find.use(_e)
1788
+ _e.check_file_last_access_time
1789
+ else
1790
+ _new_caption = _title
1791
+ end
1792
+ end
1793
+ if @arcadia.layout.headed?
1794
+ @arcadia.layout.domain(@arcadia['conf'][@name+'.frame'])['root'].top_text(_new_caption)
1795
+ end
1796
+ _title = @tabs_file[_name] != nil ? File.basename(@tabs_file[_name]) :_name
1797
+ EditorContract.instance.buffer_raised(self, 'title'=>_title, 'file'=>@tabs_file[_name])
1798
+ end
1799
+
1800
+ def editor_exist?(_filename)
1801
+ _basefilename = File.basename(_filename)
1802
+ #_basename = _basefilename.split('.')[0]+'_'+_basefilename.split('.')[1]
1803
+
1804
+
1805
+ _index = @main_frame.enb.index(self.tab_name(_filename))
1806
+ return _index != -1
1807
+ end
1808
+
1809
+ def tab_name(_str="")
1810
+ 'ff'+_str.gsub("/","_").gsub(".","_").gsub(":","_").gsub("\\","_")
1811
+ end
1812
+
1813
+ def tab_file_name(_filename="")
1814
+ _fstr = File.expand_path(_filename)
1815
+ _fstr = _filename if _fstr == nil
1816
+ tab_name(_fstr)
1817
+ end
1818
+
1819
+ def open_file(_filename = nil, _text_index='1.0', _mark_selected=true)
1820
+ return if _filename == nil || !File.exist?(_filename)
1821
+ _basefilename = File.basename(_filename)
1822
+ _tab_name = self.tab_file_name(_filename)
1823
+ _index = @main_frame.enb.index(_tab_name)
1824
+ _exist_buffer = _index != -1
1825
+
1826
+ if _exist_buffer
1827
+ open_buffer(_tab_name)
1828
+ else
1829
+ open_buffer(_tab_name, _basefilename)
1830
+ @tabs_file[_tab_name]= _filename
1831
+ @tabs_editor[_tab_name].load_file(_filename)
1832
+ EditorContract.instance.file_opened(self, 'file'=>_filename)
1833
+ end
1834
+
1835
+ if _text_index != nil && _text_index != '1.0'
1836
+ @tabs_editor[_tab_name].text_see(_text_index)
1837
+ @tabs_editor[_tab_name].mark_selected(_text_index) if _mark_selected
1838
+ end
1839
+
1840
+ return @tabs_editor[_tab_name]
1841
+ end
1842
+
1843
+
1844
+ def open_buffer(_buffer_name = nil, _title = nil)
1845
+ _index = @main_frame.enb.index(_buffer_name)
1846
+ if _buffer_name == nil
1847
+ _buffer_name = tab_name('new')
1848
+ _title_new = '*new'
1849
+ end
1850
+
1851
+ if _index != -1
1852
+ _tab = @main_frame.enb.get_frame(_buffer_name)
1853
+ @main_frame.enb.raise(_buffer_name)
1854
+ else
1855
+ _n = 1
1856
+ while @main_frame.enb.index(_buffer_name) != -1
1857
+ _title_new = '*new'+_n.to_s
1858
+ _buffer_name = tab_name('new')+_n.to_s
1859
+ _n =_n+1
1860
+ end
1861
+ if _title == nil
1862
+ _title = _title_new
1863
+ end
1864
+ _tab = @main_frame.enb.insert('end', _buffer_name ,
1865
+ 'text'=> _title,
1866
+ 'raisecmd'=>proc{do_buffer_raise(_buffer_name, _title)}
1867
+ )
1868
+ _e = AgEditor.new(self, _tab)
1869
+ _e.init_editing(_e.file_extension(_title))
1870
+ @tabs_file[_buffer_name]= nil
1871
+ @tabs_editor[_buffer_name]=_e
1872
+ end
1873
+ @main_frame.enb.move(_buffer_name, 1)
1874
+ @main_frame.enb.raise(_buffer_name)
1875
+ @main_frame.enb.see(_buffer_name)
1876
+ return _tab
1877
+ end
1878
+
1879
+ def close_others_editor(_editor, _mod=true)
1880
+ @tabs_editor.values.each do |_e|
1881
+ close_editor(_e) if _e != _editor
1882
+ end
1883
+ end
1884
+
1885
+ def close_all_editor(_editor, _mod=true)
1886
+ @tabs_editor.values.each do |_e|
1887
+ close_editor(_e)
1888
+ end
1889
+ end
1890
+
1891
+ def close_editor(_editor, _mod=true)
1892
+ if ((_mod)&&(_editor.modified?))
1893
+ _message = @main_frame.enb.itemcget(page_name(_editor.page_frame), 'text')+"\n modified. Save?"
1894
+ _r = TkDialog2.new('message'=>_message, 'buttons'=>['Ok','No','Cancel']).show()
1895
+ if _r == 0
1896
+ _editor.save
1897
+ elsif _r == 1
1898
+ close_tab(_editor.page_frame)
1899
+ elsif _r == 2
1900
+ return
1901
+ end
1902
+ else
1903
+ close_tab(_editor.page_frame)
1904
+ end
1905
+ EditorContract.instance.file_closed(self, 'file'=>_editor.file)
1906
+ end
1907
+
1908
+ def close_tab(_page_frame)
1909
+ _name = page_name(_page_frame)
1910
+ @tabs_editor.delete(_name)
1911
+ _index = @main_frame.enb.index(_name)
1912
+ @main_frame.enb.delete(_name)
1913
+ if !@main_frame.enb.pages.empty?
1914
+ @main_frame.enb.raise(@main_frame.enb.pages[_index-1])
1915
+ end
1916
+ end
1917
+
1918
+ def close_file(_filename)
1919
+ close_editor(@tabs_editor[tab_name(_filename)])
1920
+ end
1921
+
1922
+ def save_file(_filename)
1923
+ @tabs_editor[tab_name(_filename)].save
1924
+ end
1925
+
1926
+ def save_as_file(_filename)
1927
+ @tabs_editor[tab_name(_filename)].save_as
1928
+ end
1929
+
1930
+ end
1931
+
1932
+ class Findview < TkFloatTitledFrame
1933
+ def initialize(_parent)
1934
+ super(_parent)
1935
+ #stop_resizing
1936
+ y0 = 10
1937
+ d = 23
1938
+ TkLabel.new(self.frame){
1939
+ text 'Find what:'
1940
+ place('x' => 8,'y' => y0,'height' => 19)
1941
+ }
1942
+ y0 = y0 + d
1943
+ @e_what = Tk::BWidget::ComboBox.new(self.frame){
1944
+ editable true
1945
+ justify 'left'
1946
+ relief 'ridge'
1947
+ autocomplete 'true'
1948
+ #insertbackground '#FFFFFF'
1949
+ entrybg '#FFFFFF'
1950
+ expand 'tab'
1951
+ takefocus 'true'
1952
+ #pack('padx'=>10, 'fill'=>'x')
1953
+ place('relwidth' => 1, 'width'=>-16,'x' => 8,'y' => y0,'height' => 19)
1954
+ }
1955
+ y0 = y0 + d
1956
+ TkLabel.new(self.frame){
1957
+ text 'Replace with:'
1958
+ place('x' => 8,'y' => y0,'height' => 19)
1959
+ }
1960
+ y0 = y0 + d
1961
+
1962
+ @e_with = Tk::BWidget::ComboBox.new(self.frame){
1963
+ editable true
1964
+ justify 'left'
1965
+ relief 'ridge'
1966
+ autocomplete 'true'
1967
+ #insertbackground '#FFFFFF'
1968
+ entrybg '#FFFFFF'
1969
+ expand 'tab'
1970
+ takefocus 'true'
1971
+ #pack('padx'=>10, 'fill'=>'x')
1972
+ place('relwidth' => 1, 'width'=>-16,'x' => 8,'y' => y0,'height' => 19)
1973
+ }
1974
+
1975
+ y0 = y0 + d
1976
+ @cb_reg = TkCheckButton.new(self.frame){|_cb_reg|
1977
+ text 'Use Regular Expression'
1978
+ justify 'left'
1979
+ relief 'flat'
1980
+ #pack('side'=>'left', 'anchor'=>'e')
1981
+ place('x' => 8,'y' => y0,'height' => 22)
1982
+ }
1983
+ y0 = y0 + d
1984
+ @cb_back = TkCheckButton.new(self.frame){|_cb_reg|
1985
+ text 'Search backwards'
1986
+ justify 'left'
1987
+ relief 'flat'
1988
+ #pack('side'=>'left', 'anchor'=>'e')
1989
+ place('x' => 8,'y' => y0,'height' => 22)
1990
+ }
1991
+
1992
+ y0 = y0 + d
1993
+ y0 = y0 + d
1994
+ @buttons_frame = TkFrame.new(self.frame).pack('fill'=>'x', 'side'=>'bottom')
1995
+
1996
+ @b_replace_all = TkButton.new(@buttons_frame){|_b_go|
1997
+ state 'disabled'
1998
+ default 'disabled'
1999
+ text 'Replace All'
2000
+ overrelief 'raised'
2001
+ justify 'center'
2002
+ #width 15
2003
+ pack('side'=>'right','ipadx'=>5, 'padx'=>5)
2004
+ #place('width' => 50,'x' => 0,'y' => y0,'height' => 23,'bordermode' => 'inside')
2005
+ }
2006
+
2007
+
2008
+ @b_replace = TkButton.new(@buttons_frame){|_b_go|
2009
+ state 'disabled'
2010
+ default 'disabled'
2011
+ text 'Replace'
2012
+ overrelief 'raised'
2013
+ justify 'center'
2014
+ #width 15
2015
+ pack('side'=>'right','ipadx'=>5, 'padx'=>5)
2016
+ #place('width' => 50,'x' => 0,'y' => y0,'height' => 23,'bordermode' => 'inside')
2017
+ }
2018
+
2019
+
2020
+ @b_go = TkButton.new(@buttons_frame){|_b_go|
2021
+ compound 'none'
2022
+ default 'disabled'
2023
+ text 'Find Next'
2024
+ #background '#ffffff'
2025
+ #image TkPhotoImage.new('dat' => FIND_GIF)
2026
+ overrelief 'raised'
2027
+ justify 'center'
2028
+ #relief 'ridge'
2029
+ #width 15
2030
+ pack('side'=>'right','ipadx'=>5, 'padx'=>5)
2031
+ #place('width' => 50,'x' => 0,'y' => y0,'height' => 23,'bordermode' => 'inside')
2032
+ }
2033
+ #place('x'=>0,'y'=>0,'relheight'=> 1,'relwidth'=> 1)
2034
+ place('x'=>100,'y'=>100,'height'=> 220,'width'=> 300)
2035
+
2036
+ end
2037
+ end
2038
+
2039
+ class Find < Findview
2040
+ attr_reader :e_what
2041
+ def initialize(_frame, _controller)
2042
+ super(_frame)
2043
+ #@l_file.configure('text'=>_title)
2044
+ #Tk.tk_call('wm', 'title', self, _title )
2045
+ @controller = _controller
2046
+ @forwards = true
2047
+ @find_action = proc{
2048
+ #_radio = @rb.get_value
2049
+
2050
+ #if _radio == 'line'
2051
+ # go_line
2052
+ #else
2053
+ do_find_next
2054
+ #end
2055
+ }
2056
+ @b_go.bind('1', @find_action)
2057
+
2058
+ @b_replace.bind('1', proc{do_replace})
2059
+
2060
+ @b_replace_all.bind('1', proc{do_replace_all})
2061
+
2062
+ e = TkWinfo.children(@e_what)[0]
2063
+ e.bind_append('KeyPress'){|e|
2064
+ case e.keysym
2065
+ when 'Return'
2066
+ @find_action.call
2067
+ hide
2068
+ @editor_caller.text.focus
2069
+ Tk.callback_break
2070
+ else
2071
+ widget_state
2072
+ end
2073
+ }
2074
+ e2 = TkWinfo.children(@e_with)[0]
2075
+ e2.bind_append('KeyPress'){|e|
2076
+ widget_state
2077
+ }
2078
+ @last_index='insert'
2079
+
2080
+ @goto_line_dialog = GoToLine.new(_frame).hide
2081
+ @goto_line_dialog.on_close=proc{@goto_line_dialog.hide}
2082
+
2083
+ @goto_line_dialog.b_go.bind('1',proc{go_line})
2084
+ end
2085
+
2086
+ def do_replace
2087
+ if do_find_next
2088
+ _message = 'Replace "'+@e_what.value+'" with "'+@e_with.value+'" ?'
2089
+ if TkDialog2.new('message'=>_message, 'buttons'=>['Yes','No']).show() == 0
2090
+ self.editor.text.delete(@idx1,@idx2)
2091
+ self.editor.text.insert(@idx1,@e_with.value)
2092
+ self.editor.check_modify
2093
+ end
2094
+ end
2095
+ end
2096
+
2097
+ def do_replace_all
2098
+ while do_find_next
2099
+ _message = 'Replace "'+@e_what.value+'" with "'+@e_with.value+'" ?'
2100
+ _rc = TkDialog2.new('message'=>_message, 'buttons'=>['Yes','No','Annulla']).show()
2101
+ if _rc == 0
2102
+ self.editor.text.delete(@idx1,@idx2)
2103
+ self.editor.text.insert(@idx1,@e_with.value)
2104
+ self.editor.check_modify
2105
+ elsif _rc == 2
2106
+ break
2107
+ end
2108
+ end
2109
+ end
2110
+
2111
+ def widget_state
2112
+ if (@e_what.value.length > 0) && (@e_with.value.length > 0)
2113
+ @b_replace.configure('state'=>'active')
2114
+ @b_replace_all.configure('state'=>'active')
2115
+ else
2116
+ @b_replace.configure('state'=>'disabled')
2117
+ @b_replace_all.configure('state'=>'disabled')
2118
+ end
2119
+ end
2120
+
2121
+
2122
+ def editor
2123
+ if @editor_caller == nil
2124
+ @editor_caller = @controller.raised
2125
+ end
2126
+ return @editor_caller
2127
+ end
2128
+
2129
+ def show_go_to_line_dialog
2130
+ @goto_line_dialog.show
2131
+ end
2132
+
2133
+ def go_line
2134
+ if @goto_line_dialog.e_line.value.length > 0
2135
+ _row = @goto_line_dialog.e_line.value
2136
+ _index = _row+'.1'
2137
+ self.editor.text.see(_index)
2138
+ self.editor.text.tag_add('sel', _index,_index+' lineend')
2139
+ self.editor.text.set_insert(_index)
2140
+ @controller.bookmark_add(self.editor.file, _index)
2141
+ @goto_line_dialog.hide
2142
+ end
2143
+ #self.hide()
2144
+ end
2145
+
2146
+ def use(_editor)
2147
+ if (_editor != @editor_caller)
2148
+ @last_index='insert'
2149
+ @editor_caller = _editor
2150
+ title(_editor.file)
2151
+ end
2152
+ end
2153
+
2154
+ def update_combo(_txt)
2155
+ values = @e_what.cget('values')
2156
+ if (values != nil && !values.include?(_txt))
2157
+ @e_what.insert('end', @e_what.value)
2158
+ end
2159
+ end
2160
+
2161
+ def do_find(_istart=nil)
2162
+ @forwards = @cb_back.cget('onvalue') != @cb_back.cget('variable').value.to_i
2163
+ _found = false
2164
+ @idx1 = nil
2165
+ @idx2 = nil
2166
+ if @e_what.text.length > 0
2167
+ update_combo(@e_what.text)
2168
+ if !_istart && self.editor.text.index('insert')!=nil
2169
+ _istart ='insert'
2170
+ elsif defined?(@last_index)
2171
+ _istart = @last_index
2172
+ else
2173
+ _istart = '1.0'
2174
+ end
2175
+ if @forwards
2176
+ if @cb_reg.cget('onvalue')==@cb_reg.cget('variable').value.to_i
2177
+ _index = self.editor.text.tksearch(['regexp'],@e_what.text,_istart)
2178
+ else
2179
+ _index = self.editor.text.search(@e_what.text,_istart)
2180
+ end
2181
+ else
2182
+
2183
+ if @cb_reg.cget('onvalue')==@cb_reg.cget('variable').value.to_i
2184
+ _index = self.editor.text.tksearch(['regexp','backwards'],@e_what.text,_istart)
2185
+ else
2186
+ _index = self.editor.text.tksearch(['backwards'],@e_what.text,_istart)
2187
+ end
2188
+ end
2189
+ if _index && _index.length>0
2190
+ self.editor.text.see(_index)
2191
+ _row, _col = _index.split('.')
2192
+ _index_sel_end = _row.to_i.to_s+'.'+(_col.to_i+@e_what.text.length).to_i.to_s
2193
+ if @forwards
2194
+ @last_index= _index_sel_end
2195
+ else
2196
+ @last_index= _row.to_i.to_s+'.'+(_col.to_i-1).to_i.to_s
2197
+ end
2198
+ self.editor.text.tag_add('sel', _index,_index_sel_end)
2199
+ self.editor.text.set_insert(_index)
2200
+ @idx1 =_index
2201
+ @idx2 =_index_sel_end
2202
+ _found = true
2203
+ @controller.bookmark_add(self.editor.file, _index)
2204
+ else
2205
+ _message = '"'+@e_what.value+'" not found'
2206
+ TkDialog2.new('message'=>_message, 'buttons'=>['Ok']).show()
2207
+ end
2208
+
2209
+ else
2210
+ self.show()
2211
+ end
2212
+ return _found
2213
+ end
2214
+
2215
+ def do_find_next
2216
+ if @idx1 != nil
2217
+ self.editor.text.tag_remove('sel',@idx1,@idx2)
2218
+ end
2219
+ do_find(@last_index)
2220
+ end
2221
+ end
2222
+
2223
+
2224
+ class KeyTestView < TkToplevel
2225
+ attr_reader :ttest
2226
+ def initialize
2227
+ super
2228
+
2229
+ Tk.tk_call('wm', 'title', self, '...hello' )
2230
+ Tk.tk_call('wm', 'geometry', self, '638x117+200+257' )
2231
+
2232
+ @ttest = TkText.new(self){
2233
+ background '#FFF454'
2234
+ place('relwidth' => '1','relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => '0','bordermode' => 'inside','width' => '0')
2235
+ }
2236
+
2237
+ end
2238
+ end
2239
+
2240
+ class KetTest
2241
+ def initialize
2242
+ kt = KeyTestView.new
2243
+ kt.ttest.bind("KeyPress"){|e|
2244
+ kt.ttest.insert('end'," [ "+e.keysym+" ] ")
2245
+ break
2246
+ }
2247
+ end
2248
+ end
2249
+
2250
+ class CodeInsight
2251
+ end
2252
+
2253
+ class GoToLine < TkFloatTitledFrame
2254
+ attr_reader :e_line
2255
+ attr_reader :b_go
2256
+ def initialize(_parent)
2257
+ super(_parent)
2258
+ #stop_resizing
2259
+ y0 = 10
2260
+ d = 23
2261
+ TkLabel.new(self.frame){
2262
+ text 'Go to line:'
2263
+ place('x' => 8,'y' => y0,'height' => 19)
2264
+ }
2265
+ y0 = y0 + d
2266
+ @e_line = TkEntry.new(self.frame){
2267
+ justify 'left'
2268
+ relief 'ridge'
2269
+ place('relwidth' => 1, 'width'=>-16,'x' => 8,'y' => y0,'height' => 19)
2270
+ }
2271
+
2272
+ y0 = y0 + d
2273
+ y0 = y0 + d
2274
+ @buttons_frame = TkFrame.new(self.frame).pack('fill'=>'x', 'side'=>'bottom')
2275
+
2276
+ @b_go = TkButton.new(@buttons_frame){|_b_go|
2277
+ compound 'none'
2278
+ default 'disabled'
2279
+ text 'Go'
2280
+ overrelief 'raised'
2281
+ justify 'center'
2282
+ pack('side'=>'right','ipadx'=>5, 'padx'=>5)
2283
+ }
2284
+ place('x'=>150,'y'=>150,'height'=> 120,'width'=> 100)
2285
+
2286
+ end
2287
+ end