arcadia 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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