arcadia 0.1.3 → 0.2.0

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