arcadia 0.1.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.
@@ -0,0 +1,92 @@
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
+ tab-chars=0.5c
9
+ tab-replace-width-space=2
10
+ find.frame=0.0
11
+ #tabs
12
+ tabs.font=courier 9
13
+ i386-freebsd6:tabs.font=courier 12
14
+ i386-mswin32:tabs.font={Courier New} 9
15
+ #tabs.side=bottom
16
+ tabs.side=top
17
+ # editor
18
+ font=courier 9
19
+ font.bold=courier 9 bold
20
+ i386-freebsd6:font=courier 12
21
+ i386-freebsd6:font.bold=courier 12 bold
22
+ i386-mswin32:font={Courier New} 9
23
+ i386-mswin32:font.bold={Courier New} 9 bold
24
+ #+--------------------------------------------------
25
+ #color.background=#000040
26
+ #color.foreground=white
27
+ #color.insertbackground=#ff8000
28
+ #hightlight.keyword.color.foreground=#800000
29
+ #hightlight.variable.color.foreground=#f9c6f8
30
+ #hightlight.comment.color.foreground=#4aff4a
31
+ #hightlight.string.color.foreground=#8080ff
32
+ #hightlight.number.color.foreground=red
33
+ #hightlight.capitalize.color.foreground=#ffff00
34
+ #hightlight.select.color.foreground=yellow
35
+ #hightlight.select.color.background=blue
36
+ #hightlight.goto.color.foreground=blue
37
+ #hightlight.goto.color.background=yellow
38
+ #+--------------------------------------------------
39
+ #+--------------------------------------------------
40
+ color.background=#FFFFFF
41
+ color.foreground=#7F7F7F
42
+ color.insertbackground=#ff8000
43
+ hightlight.keyword.color.foreground=#00007F
44
+ hightlight.keyword.style=bold
45
+ hightlight.method_name.color.foreground=#007F7F
46
+ hightlight.method_name.style=bold
47
+ hightlight.class_name.color.foreground=#0000FF
48
+ hightlight.class_name.style=bold
49
+ hightlight.module_name.color.foreground=#0000FF
50
+ hightlight.module_name.style=bold
51
+ hightlight.instance_variable.color.foreground=#7F7F7F
52
+ hightlight.instance_variable.style=bold
53
+ hightlight.comment.color.foreground=#007F00
54
+ hightlight.string.color.foreground=#7F007F
55
+ hightlight.number.color.foreground=#007F7F
56
+ #hightlight.capitalize.color.foreground=#0000FF
57
+ hightlight.operator.color.foreground=#000000
58
+ hightlight.operator.style=bold
59
+ #hightlight.sel.color.foreground=yellow
60
+ hightlight.sel.color.background=#cccccc
61
+ hightlight.sel.borderwidth=1
62
+ hightlight.sel.relief=raised
63
+ #hightlight.goto.color.foreground=blue
64
+ hightlight.selected.color.background=yellow
65
+ #+--------------------------------------------------
66
+
67
+
68
+ # line number
69
+ #line_number_panel.color.background=#6e6e6e
70
+ #line_number_panel.color.foreground=white
71
+
72
+ line_number_panel.color.background=#e1e1e1
73
+ line_number_panel.color.foreground=#333333
74
+
75
+
76
+ # tree explorer
77
+ explorer_panel.tree.color.background=#ffffff
78
+ explorer_panel.tree.color.foreground=white
79
+ explorer_panel.tree.font=courier 9
80
+ i386-freebsd6:explorer_panel.tree.font=courier 12
81
+ i386-mswin32:explorer_panel.tree.font={Courier New} 9
82
+ explorer_panel.tree.class.color.foreground=#a42019
83
+ explorer_panel.tree.class.font=times 10 bold
84
+ i386-mswin32:explorer_panel.tree.class.font=times 10 bold
85
+ explorer_panel.tree.def.color.foreground=blue
86
+ explorer_panel.tree.def.font=times 10
87
+ i386-mswin32:explorer_panel.tree.def.font=times 10
88
+ explorer_panel.tree.module.color.foreground=#1b691e
89
+ explorer_panel.tree.module.font=times 8 bold
90
+ i386-mswin32:explorer_panel.tree.module.font={Courier New} 9 bold
91
+
92
+ #:::::::::::::::: Editor group ::::::::::::::::::::::<end>
@@ -0,0 +1,1744 @@
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
+ # @fm = AGTkVSplittedFrames.new(@page_frame,150)
41
+ # @fm1 = AGTkVSplittedFrames.new(@fm.right_frame,60)
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
+ # initialize_text
47
+ # initialize_text_binding
48
+ # initialize_highlight
49
+ # initialize_line_number
50
+ # initialize_tree
51
+ @highlighting = false
52
+ @classbrowsing = false
53
+ @find = @controller.get_find
54
+ end
55
+
56
+ def initialize_tree(_frame)
57
+ @classbrowsing = true
58
+ @nb = Tk::BWidget::NoteBook.new(_frame){
59
+ tabbevelsize 0
60
+ internalborderwidth 0
61
+ activeforeground 'red'
62
+ activebackground 'yellow'
63
+ borderwidth 1
64
+ side $arcadia['conf']['editor.tabs.side']
65
+ font $arcadia['conf']['editor.tabs.font']
66
+ pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
67
+ }
68
+ @nb_tab_exp = @nb.insert('end','exp' ,'text'=>'Class Tree' )
69
+ @nb.raise('exp')
70
+ _tree_goto = proc{|_self|
71
+ _line = _self.selection_get[0]
72
+ _index =_line.to_s+'.0'
73
+ _hinner_text = @tree_exp.itemcget(_line,'text').strip
74
+ _editor_line = @text.get(_index, _index+ ' lineend')
75
+ if !_editor_line.include?(_hinner_text)
76
+ MsgContract.instance.out_simple(self, "... rebuild tree \n")
77
+ if @tree_thread && @tree_thread.alive?
78
+ @tree_thread.exit
79
+ end
80
+ @tree_thread = Thread.new{
81
+ build_tree(_line)
82
+ Tk.update
83
+ }
84
+ _line = _self.selection_get[0]
85
+ _index =_line.to_s+'.0'
86
+ end
87
+ @text.see(_index)
88
+ @text.tag_remove('selected','1.0','end')
89
+ @text.tag_add('selected',_line.to_s+'.0',(_line+1).to_s+'.0')
90
+ }
91
+ @tree_exp = Tk::BWidget::Tree.new(@nb_tab_exp){
92
+ background '#FFFFFF'
93
+ relief 'flat'
94
+ showlines false
95
+ deltay 18
96
+ dragenabled true
97
+ selectcommand proc{ _tree_goto.call(self) }
98
+ place('relwidth' => 1,'relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => 1,'bordermode' => 'inside','width' => '50')
99
+ }
100
+ @nodes = Array.new
101
+ _c_explo = proc{|*args| @tree_exp.yview(*args)}
102
+ _s_explo = TkScrollbar.new(@nb_tab_exp){|s|
103
+ width 8
104
+ command _c_explo
105
+ }.pack('side'=>'right', 'fill'=>'y')
106
+ @tree_exp.yscrollcommand proc{|first,last| _s_explo.set first,last}
107
+
108
+ end
109
+
110
+ def initialize_text(_frame)
111
+ @v_scroll = TkScrollbar.new(_frame,
112
+ 'orient'=>'vertical',
113
+ 'relief'=>'flat'
114
+ ).pack('side' => 'right', 'fill' => 'y')
115
+ @text = TkText.new(@fm1.right_frame){|j|
116
+ wrap 'none'
117
+ relief 'flat'
118
+ undo true
119
+ insertofftime 200
120
+ insertontime 200
121
+ insertbackground $arcadia['conf']['editor.color.insertbackground']
122
+ background $arcadia['conf']['editor.color.background']
123
+ foreground $arcadia['conf']['editor.color.foreground']
124
+ insertwidth 3
125
+ exportselection true
126
+ autoseparators true
127
+ padx 0
128
+ tabs $arcadia['conf']['editor.tab-chars']
129
+ place(
130
+ 'x'=>0,
131
+ 'y'=>0,
132
+ 'width' => -15,
133
+ 'relheight'=>1,
134
+ 'relwidth'=>1,
135
+ 'bordermode'=>'outside'
136
+ )
137
+ }
138
+ @text.configure('font', @font);
139
+
140
+ @text.tag_configure('eval','foreground' => 'yellow', 'background' =>'red','borderwidth'=>1, 'relief'=>'raised')
141
+ @text.tag_configure('errline','borderwidth'=>1, 'relief'=>'groove')
142
+ @text.tag_configure('debug', 'background' =>'#b9c6d9', 'borderwidth'=>1 ,'relief'=>'raise')
143
+ @buffer = text_value
144
+ pop_up_menu
145
+ end
146
+
147
+ def initialize_text_binding
148
+ @v_scroll.command(proc{|*args|
149
+ @text.yview *args
150
+ })
151
+ @text.yscrollcommand(proc{|first,last| @v_scroll.set(first,last)
152
+ self.do_line_update()
153
+ })
154
+ @text.tag_bind('selected', 'Enter', proc{@text.tag_remove('selected','1.0','end')})
155
+
156
+ @text.bind("Enter", proc{check_file_last_access_time})
157
+ @text.bind("ButtonPress-1", proc{
158
+ _code = $arcadia['palette'].give_me_code
159
+ @text.insert('insert', _code) if _code
160
+ })
161
+
162
+ @text.bind("Control-KeyPress"){|e|
163
+ case e.keysym
164
+ when 'z'
165
+ _b = @text.index('insert').split('.')[0].to_i
166
+ @text.edit_undo
167
+ _e = @text.index('insert').split('.')[0].to_i
168
+ if @highlighting
169
+ for j in _b..._e
170
+ rehighlightline(j)
171
+ end
172
+ end
173
+ break
174
+ when 'c'
175
+ @text.text_copy
176
+ break
177
+ when 'x'
178
+ @text.text_cut
179
+ break
180
+ when 'v'
181
+ _b = @text.index('insert').split('.')[0].to_i
182
+ @text.text_paste
183
+ _e = @text.index('insert').split('.')[0].to_i
184
+ if @highlighting
185
+ for j in _b..._e
186
+ rehighlightline(j)
187
+ end
188
+ end
189
+ break
190
+ end
191
+ case e.keysym
192
+ when 's'
193
+ save
194
+ when 'f'
195
+ _r = @text.tag_ranges('sel')
196
+ if _r.length>0
197
+ _text=@text.get(_r[0][0],_r[0][1])
198
+ if _text.length > 0
199
+ @find.e_what.text(_text)
200
+ end
201
+ else
202
+ end
203
+ @find.use(self)
204
+ @find.e_what.focus
205
+ when 'egrave'
206
+ @text.insert('insert',"{")
207
+ when 'plus'
208
+ @text.insert('insert',"}")
209
+ end
210
+ }
211
+
212
+ @text.bind("Control-Shift-KeyPress"){|e|
213
+ case e.keysym
214
+ when 'I'
215
+ _r = @text.tag_ranges('sel')
216
+ _row_begin = _r[0][0].split('.')[0].to_i
217
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
218
+
219
+ for _row in _row_begin..._row_end
220
+ @text.insert(_row.to_s+'.0',"\s\s")
221
+ end
222
+ when 'U'
223
+ _r = @text.tag_ranges('sel')
224
+ _row_begin = _r[0][0].split('.')[0].to_i
225
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
226
+
227
+ for _row in _row_begin..._row_end
228
+ if @text.get(_row.to_s+'.0',_row.to_s+'.2') == "\s\s"
229
+ @text.delete(_row.to_s+'.0',_row.to_s+'.2')
230
+ end
231
+ end
232
+ when 'C'
233
+ _r = @text.tag_ranges('sel')
234
+ _row_begin = _r[0][0].split('.')[0].to_i
235
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
236
+
237
+ for _row in _row_begin..._row_end
238
+ if @text.get(_row.to_s+'.0',_row.to_s+'.1') == "#"
239
+ @text.delete(_row.to_s+'.0',_row.to_s+'.1')
240
+ else
241
+ @text.insert(_row.to_s+'.0',"#")
242
+ end
243
+ rehighlightline(_row) if @highlighting
244
+ end
245
+
246
+ end
247
+ }
248
+ @text.bind("KeyPress"){|e|
249
+ case e.keysym
250
+ when 'BackSpace'
251
+ _index = @text.index('insert')
252
+ _row, _col = _index.split('.')
253
+ rehighlightline(_row.to_i) if @highlighting
254
+ when 'Delete'
255
+ _index = @text.index('insert')
256
+ _row, _col = _index.split('.')
257
+ rehighlightline(_row.to_i) if @highlighting
258
+ when 'F5'
259
+ save
260
+ $arcadia['shell'].run(@file.to_s)
261
+ when 'F3'
262
+ @find.do_find_next
263
+ when 'Tab'
264
+ _r = @text.tag_ranges('sel')
265
+ if _r && _r[0]
266
+ _row_begin = _r[0][0].split('.')[0].to_i
267
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
268
+ n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
269
+ if n_space > 0
270
+ suf = "\s"*n_space
271
+ else
272
+ suf = "\t"
273
+ end
274
+ for _row in _row_begin..._row_end
275
+ @text.insert(_row.to_s+'.0', suf)
276
+ end
277
+ break
278
+ end
279
+ end
280
+ }
281
+
282
+ @text.bind("Shift-KeyPress"){|e|
283
+ case e.keysym
284
+ when 'Tab'
285
+ _r = @text.tag_ranges('sel')
286
+ if _r && _r[0]
287
+ _row_begin = _r[0][0].split('.')[0].to_i
288
+ _row_end = _r[_r.length - 1][1].split('.')[0].to_i
289
+
290
+ n_space = $arcadia['conf']['editor.tab-replace-width-space'].to_i
291
+ if n_space > 0
292
+ suf = "\s"*n_space
293
+ else
294
+ suf = "\t"
295
+ n_space = 1
296
+ end
297
+ for _row in _row_begin..._row_end
298
+ if @text.get(_row.to_s+'.0',_row.to_s+'.'+n_space.to_s) == suf
299
+ @text.delete(_row.to_s+'.0',_row.to_s+'.'+n_space.to_s)
300
+ end
301
+ end
302
+ break
303
+ end
304
+ end
305
+ }
306
+
307
+ @text.bind("KeyRelease"){|e|
308
+ case e.keysym
309
+ when 'Control_L','Return', 'Control_V', 'BackSpace', 'Delete'
310
+ if modified?
311
+ set_modify
312
+ else
313
+ reset_modify
314
+ end
315
+ do_line_update
316
+ when 'Right','Left','Down', 'Up'
317
+ # do nil
318
+ else
319
+ if modified?
320
+ if !@set_mod
321
+ set_modify
322
+ end
323
+ else
324
+ reset_modify
325
+ end
326
+ end
327
+ case e.keysym
328
+ when 'Return'
329
+ _index = @text.index('insert')
330
+ _row, _col = _index.split('.')
331
+ _txt = @text.get((_row.to_i-1).to_s+'.0',_index)
332
+ if _txt.length > 0
333
+ m = /\s*/.match(_txt)
334
+ if m
335
+ if (m[0] != "\n")
336
+ _sm = m[0]
337
+ _sm = _sm.sub(/\n/,"")
338
+ @text.insert('insert',_sm)
339
+ end
340
+ end
341
+ end
342
+ if _row.to_i + 1 == @text.index('end').split('.')[0].to_i
343
+ do_line_update
344
+ end
345
+ else
346
+ if @highlighting && /\w/.match(e.keysym)
347
+ rehighlightline(@text.index('insert').split('.')[0].to_i)
348
+ end
349
+ end
350
+ }
351
+
352
+
353
+ end
354
+
355
+ def initialize_line_number(_frame)
356
+ @text_line_num = TkText.new(_frame){
357
+ wrap 'none'
358
+ relief 'flat'
359
+ undo false
360
+ takefocus 0
361
+ insertofftime 0
362
+ exportselection true
363
+ autoseparators true
364
+ background $arcadia['conf']['editor.line_number_panel.color.background']
365
+ foreground $arcadia['conf']['editor.line_number_panel.color.foreground']
366
+ place(
367
+ 'x'=>0,
368
+ 'y'=>0,
369
+ 'relheight'=>1,
370
+ 'relwidth'=>1,
371
+ 'bordermode'=>'outside'
372
+ )
373
+ }
374
+ delta = @font_metrics_bold[2][1]-@font_metrics[2][1]
375
+ @text_line_num.tag_configure('bold_case', 'spacing1'=>delta)
376
+ @text_line_num.tag_configure('breakpoint', 'background'=>'red','borderwidth'=>1, 'relief'=>'raised')
377
+ @text_line_num.bind("Double-ButtonPress-1", proc{
378
+ _index = @text_line_num.index('insert')
379
+ _line = @text_line_num.get(_index+' linestart',_index+' lineend').strip
380
+ if @controller.breakpoint_lines_on_file(@file).include?(_line)
381
+ @text_line_num.tag_remove('breakpoint',_index+' linestart',_index+' lineend')
382
+ @controller.breakpoint_del(@file, _line)
383
+ else
384
+ @text_line_num.tag_add('breakpoint',_index+' linestart',_index+' linestart + 1 chars')
385
+ @controller.breakpoint_add(@file, _line)
386
+ end
387
+ })
388
+ @text_line_num.configure('font', @font);
389
+ @text_line_num.tag_configure('line_num',
390
+ 'foreground' => '#FFFFFF',
391
+ 'background' =>'#0000a0',
392
+ 'borderwidth'=>2,
393
+ 'relief'=>'raised'
394
+ )
395
+ end
396
+
397
+ def initialize_highlight
398
+ @highlighting = true
399
+ @highlight_zone = Hash.new;
400
+ # @highlight_zone_length = 45;
401
+ @highlight_zone_length = 8;
402
+ @last_line_begin = 0
403
+ @last_line_end = 0
404
+ @last_zone_begin=0;
405
+ @last_zone_end=0;
406
+ @is_line_bold = Hash.new
407
+ @is_tag_bold = Hash.new
408
+
409
+ @keyword = ['__FILE__', 'and', 'def', 'end', 'in', 'or', 'self', 'unless',
410
+ '__LINE__', 'begin', 'defined?', 'ensure', 'module', 'redo', 'super', 'until',
411
+ 'BEGIN', 'break', 'do', 'false', 'next', 'rescue', 'then', 'when',
412
+ 'END', 'case', 'else', 'for', 'nil', 'retry', 'true', 'while',
413
+ 'alias', 'class', 'elsif', 'if', 'not', 'return', 'undef', 'yield','require']
414
+ _re_string = ''
415
+ @keyword.each{|word|
416
+ if _re_string.length > 0
417
+ _re_string << '|'
418
+ end
419
+ if ['class','module','def'].include?(word)
420
+ _re_string << '([\s]*'+word+'[\s])'
421
+ else
422
+ _re_string << '\b('+word+')([.,+\(\s])'
423
+ end
424
+ }
425
+ @re_keyword = Regexp::new(_re_string)
426
+ @re_instance_variable = /([\s]*@)[A-Za-z0-9_]*/
427
+ @re_string = /'([\/A-Za-z0-9_@+\-!?=<>\[\]\{\}\(\).\s]*)'|"([\/A-Za-z0-9_@+\-!?=<>\[\]\{\}\(\).\s]*)"/
428
+ @re_number = /\d/
429
+ @re_operator = /[\(\)\[\]\(\)\{\}.:;,=><|]/
430
+ @re_method_name = /(def[\s][\s]*)[A-Za-z0-9_]*/
431
+ @re_class_name = /(class[\s][\s]*)[A-Za-z0-9_]*/
432
+ @re_module_name = /(module[\s][\s]*)[A-Za-z0-9_]*/
433
+ do_tag_configure('keyword')
434
+ do_tag_configure('method_name')
435
+ do_tag_configure('instance_variable')
436
+ do_tag_configure('class_name')
437
+ do_tag_configure('module_name')
438
+ do_tag_configure('comment')
439
+ do_tag_configure('string')
440
+ do_tag_configure('number')
441
+ do_tag_configure('sel')
442
+ do_tag_configure('selected')
443
+ do_tag_configure('operator')
444
+
445
+ end
446
+
447
+ def do_tag_configure(_name)
448
+ h = Hash.new
449
+ if $arcadia['conf']['editor.hightlight.'+_name+'.color.foreground']
450
+ h['foreground']=$arcadia['conf']['editor.hightlight.'+_name+'.color.foreground']
451
+ end
452
+ if $arcadia['conf']['editor.hightlight.'+_name+'.color.background']
453
+ h['background']=$arcadia['conf']['editor.hightlight.'+_name+'.color.background']
454
+ end
455
+ if $arcadia['conf']['editor.hightlight.'+_name+'.style']== 'bold'
456
+ h['font']=@font_bold
457
+ @is_tag_bold[_name]= true
458
+ end
459
+ if $arcadia['conf']['editor.hightlight.'+_name+'.relief']
460
+ h['relief']=$arcadia['conf']['editor.hightlight.'+_name+'.relief']
461
+ end
462
+ if $arcadia['conf']['editor.hightlight.'+_name+'.borderwidth']
463
+ h['borderwidth']=$arcadia['conf']['editor.hightlight.'+_name+'.borderwidth']
464
+ end
465
+ @text.tag_configure(_name, h)
466
+ end
467
+
468
+ def pop_up_menu
469
+ @pop_up = TkMenu.new(
470
+ :parent=>@text,
471
+ :tearoff=>1,
472
+ :title => 'Menu'
473
+ )
474
+ @pop_up.insert('end',
475
+ :command,
476
+ :label=>'Save as',
477
+ :hidemargin => false,
478
+ :command=> proc{save_as}
479
+ )
480
+ @pop_up.insert('end',
481
+ :command,
482
+ :label=>'Save',
483
+ :hidemargin => false,
484
+ :command=> proc{save}
485
+ )
486
+ # @pop_up.insert('end',
487
+ # :command,
488
+ # :label=>'New',
489
+ # :hidemargin => false,
490
+ # :command=> proc{@controller.open_buffer()}
491
+ # )
492
+ # @pop_up.insert('end',
493
+ # :command,
494
+ # :label=>'Open',
495
+ # :hidemargin => false,
496
+ # :command=> proc{ @controller.open_file(Tk.getOpenFile)}
497
+ # )
498
+ # @pop_up.insert('end',
499
+ # :command,
500
+ # :label=>'Close',
501
+ # :hidemargin => false,
502
+ # :command=> proc{
503
+ # @controller.close_editor(self)
504
+ # }
505
+ # )
506
+
507
+ @pop_up.insert('end',
508
+ :command,
509
+ :label=>'Color',
510
+ :hidemargin => false,
511
+ :command=> proc{
512
+ @text.insert('insert',Tk.chooseColor)
513
+ }
514
+ )
515
+ @pop_up.insert('end',
516
+ :command,
517
+ :label=>'Font',
518
+ :hidemargin => false,
519
+ :command=> proc{
520
+ @text.insert('insert', $arcadia['action.get.font'].call)
521
+ }
522
+ )
523
+ # @pop_up.insert('end',
524
+ # :command,
525
+ # :label=>'Eval Toplevel',
526
+ # :hidemargin => false,
527
+ # :command=> proc{
528
+ # _r = @text.tag_ranges('sel')
529
+ # _ibegin = _r[_r.length - 1][0]
530
+ # _iend = _r[_r.length - 1][1]
531
+ # _cod = @text.get(_ibegin, _iend)
532
+ # Revparsel.new(_cod, @file)
533
+ # @text.tag_add('eval',_ibegin, _iend)
534
+ # _reset = proc{
535
+ # _message = 'Replace code with new '+$arcadia['objic'].active.agobj_start.i_name+'?'
536
+ # _r = TkDialog2.new('message'=>_message, 'buttons'=>['Yes','No','Cancel']).show()
537
+ # if _r == '0'
538
+ # @text.tag_remove('eval',_ibegin, _iend)
539
+ # @text.delete(_ibegin, _iend)
540
+ # text_insert(_ibegin,$arcadia['objic'].active.objects2code.to_s){_edit_reset=false}
541
+ # @text.tag_remove('sel','1.0', 'end')
542
+ # $arcadia['objic'].del($arcadia['objic'].active)
543
+ # end
544
+ # }
545
+ # @text.tag_bind('eval',"Double-ButtonPress-1",_reset)
546
+ # }
547
+ # )
548
+ @text.bind("Button-3",
549
+ proc{|x,y|
550
+ _x = TkWinfo.pointerx(@text)
551
+ _y = TkWinfo.pointery(@text)
552
+ @pop_up.popup(_x,_y)
553
+ },
554
+ "%x %y")
555
+ end
556
+
557
+ def unmark_debug(_index)
558
+ @text.tag_remove('debug',_index+' linestart', _index+' lineend')
559
+ end
560
+
561
+ def mark_debug(_index)
562
+ #@text.tag_add('debug',_index +' linestart', _index +' +1 lines linestart')
563
+ @text.tag_add('debug',_index +' linestart', _index +' lineend')
564
+ end
565
+
566
+ def mark_selected(_index)
567
+ @text.tag_remove('selected','1.0', 'end')
568
+ @text.tag_add('selected',_index +' linestart', _index +' +1 lines linestart')
569
+ end
570
+
571
+
572
+ def build_tree_from_source(_source)
573
+ _row = 1
574
+ _liv = 0
575
+ _livs = Array.new
576
+ root = TreeNode.new(nil, 'KRoot'){|_node|
577
+ _node.rif= 'root'
578
+ _node.label=''
579
+ }
580
+ _livs[_liv]=root
581
+ _source.each_line{|line|
582
+ line = "\s"+line.split("#")[0]+"\s"
583
+ m = /[\s\n\t\;]+(module|class|def|if|unless|begin|case|for|while|do)[\s\n\t\;]+/.match(line)
584
+ if m
585
+ index = m.post_match.strip.length - 1
586
+ if m.post_match.strip[index,index]=='{'
587
+ _row = _row +1
588
+ next
589
+ end
590
+ _liv>=0? _liv = _liv + 1:_liv=1
591
+ _pliv = _liv
592
+ _parent = nil
593
+ while (_parent == nil && _pliv>=0)
594
+ _pliv = _pliv -1
595
+ _parent = _livs[_pliv]
596
+ end
597
+ if _parent
598
+ _helptext = m.post_match.strip
599
+ _label = _helptext.split('<')[0]
600
+ if _label == nil || _label.strip.length==0
601
+ _label = _helptext
602
+ end
603
+ if (m[0].strip[0..4] == "class" && m.pre_match.strip.length==0)
604
+ _kind = 'KClass'
605
+ elsif (m[0].strip[0..4] == "class" && m.pre_match.strip.length>0)
606
+ _row = _row +1
607
+ _liv = _liv - 1
608
+ next
609
+ elsif (m[0].strip[0..5] == "module" && m.pre_match.strip.length==0)
610
+ _kind = 'KModule'
611
+ elsif (m[0].strip[0..5] == "module" && m.pre_match.strip.length>0)
612
+ _row = _row +1
613
+ _liv = _liv - 1
614
+ next
615
+ 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))
616
+ _row = _row +1
617
+ next
618
+ elsif ((m[0].strip[0..1] == "if" || m[0].strip[0..5] == "unless") && m.pre_match.strip.length>0)
619
+ _row = _row +1
620
+ _liv = _liv - 1
621
+ next
622
+ elsif (m[0].strip[0..2] == "def" && m.pre_match.strip.length==0)
623
+ _kind = 'KDef'
624
+ if _label.include?(_parent.label + '.')
625
+ _kind = 'KDefClass'
626
+ end
627
+ # elsif (m[0].strip[0..10] == "attr_reader" && m.pre_match.strip.length==0)
628
+ # _kind = 'KAttr_reader'
629
+ # _liv = _liv - 1
630
+ # _row = _row +1
631
+ end
632
+
633
+ @nodes << _row.to_s
634
+ TreeNode.new(_parent, _kind){|_node|
635
+ _node.label = _label
636
+ _node.helptext = _helptext
637
+ _node.rif = _row.to_s
638
+ _livs[_pliv + 1]=_node
639
+ }
640
+ else
641
+ _row = _row +1
642
+ _liv = _liv - 1
643
+ next
644
+ end
645
+ end
646
+ m_end = /[\s\n\t\;]+end[\s\n\t\;]+/.match(line)
647
+ if m_end
648
+ _liv = _liv - 1
649
+ end
650
+ _row = _row +1
651
+ }
652
+ return root
653
+ end
654
+
655
+ def build_tree_from_node(_node, _label_match=nil)
656
+ _sorted_sons = _node.sons.sort
657
+ for inode in 0.._sorted_sons.length - 1
658
+ _son = _sorted_sons[inode]
659
+ if _son.kind == 'KClass'
660
+ _window = TkLabel.new(@tree_exp){
661
+ image TkPhotoImage.new('dat' => TREE_NODE_CLASS_GIF)
662
+ background($arcadia['conf']['editor.explorer_panel.tree.color.background'])
663
+ }
664
+ elsif _son.kind == 'KModule'
665
+ _window = TkLabel.new(@tree_exp){
666
+ image TkPhotoImage.new('dat' => TREE_NODE_MODULE_GIF)
667
+ background($arcadia['conf']['editor.explorer_panel.tree.color.background'])
668
+ }
669
+ elsif _son.kind == 'KDef'
670
+ _window = TkLabel.new(@tree_exp){
671
+ image TkPhotoImage.new('dat' => TREE_NODE_DEF_GIF)
672
+ background($arcadia['conf']['editor.explorer_panel.tree.color.background'])
673
+ }
674
+ elsif _son.kind == 'KDefClass'
675
+ _window = TkLabel.new(@tree_exp){
676
+ image TkPhotoImage.new('dat' => TREE_NODE_DEFCLASS_GIF)
677
+ background($arcadia['conf']['editor.explorer_panel.tree.color.background'])
678
+ }
679
+ end
680
+ @tree_exp.insert('end', _son.parent.rif ,_son.rif, {
681
+ 'text' => _son.label ,
682
+ 'helptext' => _son.helptext,
683
+ 'font'=>$arcadia['conf']['editor.explorer_panel.tree.font'],
684
+ 'window'=> _window
685
+ }
686
+ )
687
+ @nodes << _son.rif
688
+ if (_label_match) && (_label_match.strip == _son.label.strip)
689
+ @selected = _son
690
+ end
691
+ build_tree_from_node(_son, _label_match)
692
+ end
693
+ end
694
+
695
+ def build_tree(_sel=nil)
696
+ if _sel
697
+ _label_sel = @tree_exp.itemcget(_sel,'text')
698
+ end
699
+ #clear tree
700
+ @tree_exp.delete(@nodes)
701
+ @nodes.clear
702
+ #(re)build tree
703
+ _txt = @text.get('1.0','end')
704
+ @root = build_tree_from_source(_txt)
705
+ @selected = nil
706
+ build_tree_from_node(@root, _label_sel)
707
+ if @selected
708
+ @tree_exp.selection_add(@selected.rif)
709
+ end
710
+ end
711
+
712
+ def insert_popup_menu_item(_where, *args)
713
+ @pop_up.insert(_where,*args)
714
+ end
715
+
716
+ def text_value
717
+ return @text.value
718
+ end
719
+
720
+ # vertical scrollbar : ON/OFF
721
+ def vscroll(mode)
722
+ st = TkGrid.info(@v_scroll)
723
+ if mode && st == [] then
724
+ @v_scroll.grid('row'=>0, 'column'=>1, 'sticky'=>'ns')
725
+ elsif !mode && st != [] then
726
+ @v_scroll.ungrid
727
+ end
728
+ self
729
+ end
730
+
731
+ # horizontal scrollbar : ON/OFF
732
+ def hscroll(mode, wrap_mode="char")
733
+ st = TkGrid.info(@h_scroll)
734
+ if mode && st == [] then
735
+ @h_scroll.grid('row'=>1, 'column'=>0, 'sticky'=>'ew')
736
+ @text.configure('wrap'=> 'none')
737
+ elsif !mode && st != [] then
738
+ @h_scroll.ungrid
739
+ @text.configure('wrap'=> wrap_mode)
740
+ end
741
+ self
742
+ end
743
+
744
+ def rowcol(_index, _gap_row = nil, _gap_col = nil)
745
+ _riga, _colonna = _index.split('.')
746
+ if _gap_row == nil
747
+ _riga = '1'
748
+ _gap_row = 0
749
+ end
750
+ if _gap_col == nil
751
+ _colonna = '0'
752
+ _gap_col = 0
753
+ end
754
+ return (_riga.to_i + _gap_row).to_s + '.'+ (_colonna.to_i + _gap_col).to_s
755
+ end
756
+
757
+ def find_and_set_tag(_re, _row, _txt, _tag, _tag_rem = nil)
758
+ m = _re.match(_txt)
759
+ _end = 0
760
+ if m && @is_tag_bold[_tag]
761
+ @is_line_bold[_row]=true
762
+ end
763
+ while m
764
+ _txt = m.post_match
765
+ _ibegin = _row.to_s+'.'+(m.begin(0)+_end).to_s
766
+ _end = m.end(0) + _end
767
+ _iend = _row.to_s+'.'+(_end.to_s)
768
+ if _tag_rem
769
+ _tag_rem.each {|value|
770
+ @text.tag_remove(value,_ibegin, _iend)
771
+ }
772
+ end
773
+ @text.tag_add(_tag,_ibegin, _iend)
774
+ m = _re.match(_txt)
775
+ end
776
+ end
777
+
778
+ # def find_next_and_set_tag(_re, _row, _col, _txt, _tag)
779
+ # m = _re.match(_txt)
780
+ # if m
781
+ # _txt = m.post_match
782
+ # _ibegin = _row.to_s+'.'+(m.begin(0)+_end).to_s
783
+ # _col = m.end(0)+ _col
784
+ # _iend = _row.to_s+'.'+(_col.to_s)
785
+ # @text.tag_add(_tag,_ibegin, _iend)
786
+ # end
787
+ # end
788
+
789
+ def modified?
790
+ return !(@buffer === text_value)
791
+ end
792
+
793
+ def set_modify
794
+ if !@set_mod
795
+ @set_mod = true
796
+ @controller.change_tab_set_modify(@page_frame)
797
+ end
798
+ end
799
+
800
+ def reset_modify
801
+ @controller.change_tab_reset_modify(@page_frame)
802
+ @set_mod = false
803
+ @file_last_access_time = File.mtime(@file) if @file
804
+ end
805
+
806
+ def highlightline(_row, _line, _check_mod = false)
807
+ if _check_mod && modified?
808
+ set_modify
809
+ end
810
+ _txt = _line
811
+ _end = 0
812
+
813
+ #if line is a comment
814
+ m_c = /#/.match(_txt)
815
+ if m_c then
816
+ _ibegin = _row.to_s+'.'+(m_c.begin(0)).to_s
817
+ _iend = _row.to_s+'.'+(_line.length - 1).to_s
818
+ @text.tag_add('comment',_ibegin, _iend)
819
+ _txt = m_c.pre_match
820
+ end
821
+ arem = Array.new
822
+ if _txt.strip.length > 0
823
+ find_and_set_tag(@re_number, _row, _txt, 'number')
824
+ arem << 'number'
825
+ find_and_set_tag(@re_method_name, _row, _txt, 'method_name',arem)
826
+ arem << 'method_name'
827
+ find_and_set_tag(@re_class_name, _row, _txt, 'class_name',arem)
828
+ arem << 'class_name'
829
+ find_and_set_tag(@re_module_name, _row, _txt, 'module_name',arem)
830
+ arem << 'module_name'
831
+ find_and_set_tag(@re_keyword, _row, _txt, 'keyword',arem)
832
+ arem << 'keyword'
833
+ find_and_set_tag(@re_instance_variable, _row, _txt, 'instance_variable',arem)
834
+ arem << 'instance_variable'
835
+ find_and_set_tag(@re_operator, _row, _txt, 'operator')
836
+ arem << 'operator'
837
+ find_and_set_tag(@re_string, _row, _txt, 'string', arem)
838
+ end
839
+ end
840
+
841
+ def rehighlightline(_row)
842
+ _ibegin = _row.to_s+'.0'
843
+ _iend = (_row+1).to_s+'.0'
844
+ @text.tag_remove('keyword',_ibegin, _iend)
845
+ @text.tag_remove('comment',_ibegin, _iend)
846
+ @text.tag_remove('string',_ibegin, _iend)
847
+ @text.tag_remove('number',_ibegin, _iend)
848
+ @text.tag_remove('operator',_ibegin, _iend)
849
+ @text.tag_remove('capitalize',_ibegin, _iend)
850
+ _line = @text.get(_ibegin, _iend)
851
+ highlightline(_row, _line)
852
+ end
853
+
854
+ def row(_index='insert')
855
+ _row = @text.index(_index).split('.')[0].to_i
856
+ print "def row(_index='insert')",_row.to_s,"\n"
857
+ return _row
858
+ end
859
+
860
+ def do_line_update
861
+ #renum in @text_line_num the portion of visibled screen of @text
862
+ if @text_line_num
863
+ incr = 1 + (@font_metrics[2][1]+@font_metrics_bold[2][1]) / 4
864
+ line_begin = @text.index('@0,0').split('.')[0].to_i
865
+ line_end = @text.index('@0,'+TkWinfo.height(@text).to_s).split('.')[0].to_i + 1
866
+ # breakpoint
867
+ b = @controller.breakpoint_lines_on_file(@file)
868
+ @text_line_num.delete('1.0','end')
869
+ for j in line_begin...line_end
870
+ nline = j.to_s.rjust(6)
871
+ _index = @text_line_num.index('end')
872
+ if @hightliting && @is_line_bold[j]
873
+ @text_line_num.insert('end', nline+"\n",'bold_case')
874
+ else
875
+ @text_line_num.insert('end', nline+"\n")
876
+ end
877
+ if b.include?(j.to_s)
878
+ @text_line_num.tag_add('breakpoint',_index+' -1 lines',_index+' -1 lines + 1 chars')
879
+ end
880
+ end
881
+
882
+ if @highlighting
883
+ _zone_begin = ((line_begin) / @highlight_zone_length).to_i + 1
884
+ _zone_end = ((line_end) / @highlight_zone_length).to_i + 1
885
+
886
+ (_zone_begin >=@last_zone_begin)?_zone_begin.upto(_zone_end+1){|_zone|
887
+ highlight_zone(_zone)
888
+ }:_zone_end.downto(_zone_begin-1){|_zone|
889
+ highlight_zone(_zone)
890
+ }
891
+ @last_line_begin = line_begin
892
+ @last_line_end = line_end
893
+ @last_zone_begin = _zone_begin
894
+ @last_zone_end = _zone_end
895
+ end
896
+ end
897
+ end
898
+
899
+ def highlight_zone(_zone)
900
+ if !@highlight_zone[_zone]
901
+ _b = @highlight_zone_length*(_zone - 1)
902
+ _e = @highlight_zone_length*(_zone) + 1
903
+ for j in _b..._e
904
+ rehighlightline(j)
905
+ end
906
+ @highlight_zone[_zone] = true
907
+ end
908
+ end
909
+
910
+ def text_see(_index=nil)
911
+ if _index
912
+ @text.see(_index)
913
+ end
914
+ end
915
+
916
+ def text_insert_index
917
+ @text.index('insert')
918
+ end
919
+
920
+ def text_insert(index, chars, *tags, &b)
921
+ if block_given?
922
+ instance_eval(&b)
923
+ end
924
+ _index = @text.index(index)
925
+ _row, _col = _index.split('.')
926
+ _row = (_row.to_i - 1).to_s
927
+ chars.each_line {|line|
928
+ @text.insert(_row+'.0', line, *tags)
929
+ if !defined?(m_begin)||(m_begin == nil)
930
+ m_begin = /=begin/.match(line)
931
+ end
932
+ if @highlighting
933
+ if m_begin &&(m_begin.begin(0)==0)
934
+ _ibegin = _row+'.0'
935
+ _iend = _row+'.'+(line.length - 1).to_s
936
+ @text.tag_add('comment',_ibegin, _iend)
937
+ else
938
+ highlightline(_row.to_i, line, false)
939
+ end
940
+ end
941
+ _row = (_row.to_i + 1).to_s
942
+ }
943
+ if defined?(_edit_reset)
944
+ if _edit_reset
945
+ @text.edit_reset
946
+ end
947
+ else
948
+ @text.edit_reset
949
+ end
950
+ end
951
+
952
+ def save
953
+ if !@file
954
+ save_as
955
+ else
956
+ f = File.new(@file, "w")
957
+ begin
958
+ if f
959
+ f.syswrite(text_value)
960
+ @buffer = text_value
961
+ reset_modify
962
+ end
963
+ ensure
964
+ f.close unless f.nil?
965
+ end
966
+ end
967
+ end
968
+
969
+ def save_as
970
+ @file = Tk.getSaveFile
971
+ if @file
972
+ save
973
+ @controller.change_file_name(@page_frame, @file)
974
+ end
975
+ end
976
+
977
+
978
+ def check_file_last_access_time
979
+ if @file && @file_last_access_time
980
+
981
+ ftime = File.mtime(@file)
982
+ if @file_last_access_time != ftime
983
+ msg = 'File "'+@file+'" is changed! Reload?'
984
+ if Tk.messageBox('icon' => 'error', 'type' => 'yesno',
985
+ 'title' => '(Arcadia) Libs', 'parent' => @text,
986
+ 'message' => msg) == 'yes'
987
+ @text.delete('1.0','end')
988
+ load_file(@file)
989
+ else
990
+ @file_last_access_time = ftime
991
+ end
992
+ end
993
+ end
994
+ end
995
+
996
+ def init_editing(_ext='rb')
997
+ case _ext
998
+ when 'rb'
999
+ @fm = AGTkVSplittedFrames.new(@page_frame,150)
1000
+ @fm1 = AGTkVSplittedFrames.new(@fm.right_frame,60)
1001
+ initialize_text(@fm1.right_frame)
1002
+ initialize_text_binding
1003
+ initialize_highlight
1004
+ initialize_line_number(@fm1.left_frame)
1005
+ initialize_tree(@fm.left_frame)
1006
+ else
1007
+ @fm1 = AGTkVSplittedFrames.new(@page_frame,60)
1008
+ initialize_text(@fm1.right_frame)
1009
+ initialize_text_binding
1010
+ initialize_line_number(@fm1.left_frame)
1011
+ end
1012
+ end
1013
+
1014
+ def file_extension(_filename=nil)
1015
+ if _filename
1016
+ _m = /(.*\.)(.*$)/.match(File.basename(_filename))
1017
+ return _m[2] if _m && _m.length > 1
1018
+ end
1019
+ end
1020
+
1021
+ def load_file(_filename = nil)
1022
+ #if filename is nil then open a new tab
1023
+ @file = _filename
1024
+ if _filename
1025
+ #init_editing(file_extension(_filename))
1026
+ File::open(_filename,'r'){ |file|
1027
+ @text.insert('end',file.readlines.collect!{| line | line.chomp+"\n" }.to_s)
1028
+ }
1029
+ end
1030
+ @buffer = text_value
1031
+ reset_modify
1032
+ @text.edit_reset
1033
+ build_tree if @classbrowsing
1034
+ end
1035
+ end
1036
+
1037
+ class AgMultiEditorView
1038
+ attr_reader :enb
1039
+ def initialize(parent=nil)
1040
+ @enb = Tk::BWidget::NoteBook.new(parent){
1041
+ tabbevelsize 0
1042
+ internalborderwidth 2
1043
+ activeforeground 'red'
1044
+ activebackground 'yellow'
1045
+ #background 'black'
1046
+ borderwidth 1
1047
+ side $arcadia['conf']['editor.tabs.side']
1048
+ font $arcadia['conf']['editor.tabs.font']
1049
+ pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
1050
+ }
1051
+ end
1052
+
1053
+ end
1054
+
1055
+ class AgMultiEditor < ArcadiaExt
1056
+ attr_reader :breakpoints
1057
+ attr_reader :splitted_frame
1058
+ def before_build
1059
+ ArcadiaContractListener.new(self, DebugContract, :do_debug_event)
1060
+ ArcadiaContractListener.new(self, EditorContract, :do_editor_event)
1061
+ end
1062
+
1063
+ def build
1064
+ if @arcadia.layout.headed?
1065
+ title_frame = @arcadia.layout.domain(conf('frame'))['root']
1066
+ #@close_button = title_frame.add_button(nil,nil,TAB_CLOSE_GIF,'left')
1067
+ end
1068
+
1069
+ @splitted_frame = AGTkOSplittedFrames.new(self.frame,20)
1070
+ @main_frame = AgMultiEditorView.new(@splitted_frame.bottom_frame)
1071
+ #@close_button.bind('1',proc{close_raised})
1072
+ @tabs_file =Hash.new
1073
+ @tabs_editor =Hash.new
1074
+ @breakpoints =Array.new
1075
+ create_find
1076
+ pop_up_menu
1077
+ end
1078
+
1079
+ def after_build
1080
+ self.open_last_files
1081
+ end
1082
+
1083
+ def pop_up_menu
1084
+ @pop_up = TkMenu.new(
1085
+ :parent=>@main_frame.enb,
1086
+ :tearoff=>0,
1087
+ :title => 'Menu'
1088
+ )
1089
+ @pop_up.insert('end',
1090
+ :command,
1091
+ :label=>'...',
1092
+ :state=>'disabled',
1093
+ :background=>'yellow',
1094
+ :activebackground=>'yellow',
1095
+ :hidemargin => true
1096
+ )
1097
+ @c = @pop_up.insert('end',
1098
+ :command,
1099
+ :label=>'Close',
1100
+ :hidemargin => false,
1101
+ :command=> proc{
1102
+ if @selected_tab_name_from_popup != nil
1103
+ _e = @tabs_editor[@selected_tab_name_from_popup]
1104
+ self.close_editor(_e)
1105
+ end
1106
+ }
1107
+ )
1108
+ @c = @pop_up.insert('end',
1109
+ :command,
1110
+ :label=>'Close others',
1111
+ :hidemargin => false,
1112
+ :command=> proc{
1113
+ if @selected_tab_name_from_popup != nil
1114
+ _e = @tabs_editor[@selected_tab_name_from_popup]
1115
+ self.close_others_editor(_e)
1116
+ end
1117
+ }
1118
+ )
1119
+
1120
+ @main_frame.enb.tabbind("Button-3",
1121
+ proc{|x|
1122
+ #p x
1123
+ _x = TkWinfo.pointerx(@main_frame.enb)
1124
+ _y = TkWinfo.pointery(@main_frame.enb)
1125
+ @selected_tab_name_from_popup = 'ff'+x[0].split(':')[0]
1126
+ _file = @main_frame.enb.itemcget(@selected_tab_name_from_popup, 'text')
1127
+ @pop_up.entryconfigure(0, 'label'=>_file)
1128
+ @pop_up.popup(_x,_y)
1129
+ })
1130
+ end
1131
+
1132
+
1133
+ def do_debug_event(_event)
1134
+ #@arcadia.outln('_sender ----> '+_sender.to_s)
1135
+ #@arcadia.outln('_event.signature ----> '+_event.signature)
1136
+ case _event.signature
1137
+ when DebugContract::DEBUG_BEGIN
1138
+ self.debug_begin
1139
+ when DebugContract::DEBUG_END
1140
+ self.debug_end
1141
+ when DebugContract::DEBUG_STEP
1142
+ if _event.context.file
1143
+ self.open_file_in_debug(_event.context.file, _event.context.line)
1144
+ end
1145
+ end
1146
+ end
1147
+
1148
+ def do_editor_event(_event)
1149
+ case _event.signature
1150
+ when EditorContract::OPEN_FILE
1151
+ if _event.context.file
1152
+ if _event.context.line
1153
+ _index = _event.context.line.to_s+'.0'
1154
+ end
1155
+ self.open_file(_event.context.file, _index)
1156
+ _event.handled(self)
1157
+ end
1158
+ when EditorContract::OPEN_TEXT
1159
+ if _event.context.title
1160
+ self.open_buffer(_event.context.title)
1161
+ _e = @tabs_editor[_event.context.title]
1162
+ _e.text_insert('end',_event.context.text) if _event.context.text
1163
+ add_reverse_item(_e)
1164
+ _event.handled(self)
1165
+ end
1166
+ when EditorContract::CLOSE_FILE
1167
+ if _event.context.file
1168
+ self.close_file(_event.context.file)
1169
+ _event.handled(self)
1170
+ end
1171
+ end
1172
+ end
1173
+
1174
+ def add_reverse_item(_editor)
1175
+ code2form = proc{
1176
+ Revparsel.new(_editor.text_value)
1177
+ self.close_editor(_editor, false)
1178
+ # $arcadia['objic'].active.select_last
1179
+ }
1180
+ _editor.insert_popup_menu_item('end',
1181
+ :command,
1182
+ :label=>'View as form',
1183
+ :hidemargin => false,
1184
+ :command=> code2form
1185
+ )
1186
+
1187
+ end
1188
+
1189
+ # def editor_state
1190
+ # r = EditorContract::SObj.new
1191
+ # r.raised_file = self.raised.file
1192
+ # r.breakpoints = @breakpoints
1193
+ # return r
1194
+ # end
1195
+
1196
+ def get_find
1197
+ @find
1198
+ end
1199
+
1200
+ def create_find
1201
+ #find_frame = @arcadia.layout.register_panel(conf('find.frame'),'Find', 'Find')
1202
+ @find = Find.new(@splitted_frame.top_frame, self)
1203
+ end
1204
+
1205
+ def finalize
1206
+ _files =''
1207
+ @tabs_editor.each_value{|editor|
1208
+ _files=_files+'|'+ editor.file if editor.file != nil
1209
+ close_editor(editor)
1210
+ }
1211
+ @arcadia['pers']['editor.files.open']=_files
1212
+ end
1213
+
1214
+ def raised
1215
+ _page = @main_frame.enb.raise
1216
+ return @tabs_editor[_page]
1217
+ end
1218
+
1219
+ def close_raised
1220
+ close_editor(@tabs_editor[@main_frame.enb.raise])
1221
+
1222
+ #_page = @main_frame.enb.raise
1223
+ #_editor = @tabs_editor[_page]
1224
+ #_row = _editor.text_insert_index.split('.')[0].strip.to_i
1225
+ #close_editor(_editor)
1226
+ end
1227
+
1228
+ def breakpoint_add(_file,_line)
1229
+ _tobj = EditorContract::TEditorObj.new(self)
1230
+ _tobj.file = _file
1231
+ _tobj.line = _line
1232
+ EditorContract.instance.breakpoint_created(_tobj)
1233
+ @breakpoints << {:file=>_file,:line=>_line}
1234
+ end
1235
+
1236
+ def breakpoint_del(_file,_line)
1237
+ _tobj = EditorContract::TEditorObj.new(self)
1238
+ _tobj.file = _file
1239
+ _tobj.line = _line
1240
+ EditorContract.instance.breakpoint_deleted(_tobj)
1241
+ @breakpoints.delete_if{|b| (b[:file]==_file && b[:line]==_line)}
1242
+ end
1243
+
1244
+ def breakpoint_lines_on_file(_file)
1245
+ result = Array.new
1246
+ @breakpoints.each{|value|
1247
+ if value[:file]==_file
1248
+ result << value[:line]
1249
+ end
1250
+ }
1251
+ return result
1252
+ end
1253
+
1254
+ def open_last_files
1255
+ if $arcadia['pers']['editor.files.open']
1256
+ _files_index =$arcadia['pers']['editor.files.open'].split("|")
1257
+ _files_index.each{|value|
1258
+ _file,_index = value.split(';')
1259
+ if _file
1260
+ open_file(_file,_index)
1261
+ end
1262
+ }
1263
+ end
1264
+ self
1265
+ end
1266
+
1267
+ def bookmark_add(_file, _index)
1268
+ if @bookmarks == nil
1269
+ @bookmarks = Array.new
1270
+ @bookmarks_index = - 1
1271
+ else
1272
+ _cur_file, _cur_index = @bookmarks[@bookmarks_index]
1273
+ if _cur_file == _file && _cur_index == _index
1274
+ #@arcadia.outln('uguale ----> '+_file+':'+_index)
1275
+ return
1276
+ end
1277
+ @bookmarks = @bookmarks[0..@bookmarks_index]
1278
+ end
1279
+ @bookmarks << [_file, _index]
1280
+ @bookmarks_index = @bookmarks.length - 1
1281
+ #@arcadia.outln('add ----> '+_file+':'+_index)
1282
+ end
1283
+
1284
+ def bookmark_clear
1285
+ @bookmarks.clear
1286
+ @bookmarks_index = - 1
1287
+ end
1288
+
1289
+ def bookmark_next
1290
+ return if @bookmarks == nil || @bookmarks_index >= @bookmarks.length - 1
1291
+ bookmark_move(+1)
1292
+ end
1293
+
1294
+ def bookmark_move(_n=0)
1295
+ @bookmarks_index = @bookmarks_index + _n
1296
+ #Tk.messageBox('message'=>@bookmarks_index.to_s)
1297
+ _file, _index = @bookmarks[@bookmarks_index]
1298
+ _line, _col = _index.split('.') if _index
1299
+ open_file(_file, _index)
1300
+ #openfile(@bookmarks[@bookmarks_index])
1301
+ end
1302
+
1303
+
1304
+ def bookmark_prev
1305
+ return if @bookmarks == nil || @bookmarks_index <= 0
1306
+ bookmark_move(-1)
1307
+ end
1308
+
1309
+
1310
+ def get_tab_from_name(_name=nil)
1311
+ return @main_frame.enb.get_frame(_name)
1312
+ # if _name
1313
+ # @tabs_name.each{
1314
+ # |key,value|
1315
+ # if value.to_s==_name.to_s
1316
+ # return key
1317
+ # end
1318
+ # }
1319
+ # return nil
1320
+ # end
1321
+ end
1322
+
1323
+ def change_tab_set_modify(_tab)
1324
+ _new_name = '(...)'+@main_frame.enb.itemcget(page_name(_tab), 'text')
1325
+ change_tab_title(_tab, _new_name)
1326
+ end
1327
+
1328
+ def page_name(_page_frame)
1329
+ TkWinfo.appname(_page_frame).sub('f','')
1330
+ end
1331
+
1332
+ def change_tab_reset_modify(_tab)
1333
+ #_new_name = @main_frame.enb.itemcget(@tabs_name[_tab], 'text').gsub!("(...)",'')
1334
+ _new_name = @main_frame.enb.itemcget(page_name(_tab), 'text').gsub!("(...)",'')
1335
+ if _new_name
1336
+ change_tab_title(_tab, _new_name)
1337
+ end
1338
+ end
1339
+
1340
+ def change_tab_title(_tab, _new_text)
1341
+ @main_frame.enb.itemconfigure(page_name(_tab), 'text'=> _new_text)
1342
+ end
1343
+
1344
+ def change_file_name(_tab, _new_file)
1345
+ _new_label = File.basename(_new_file)
1346
+ change_tab_title(_tab, _new_label)
1347
+ @tabs_file[page_name(_tab)] = _new_file
1348
+ end
1349
+
1350
+ def debug_begin
1351
+ if @editors_in_debug != nil
1352
+ @editors_in_debug.clear
1353
+ else
1354
+ @editors_in_debug = Array.new
1355
+ end
1356
+ end
1357
+
1358
+ def debug_end
1359
+ debug_reset
1360
+ @editors_in_debug.each{|e|
1361
+ close_editor(e)
1362
+ }
1363
+ end
1364
+
1365
+ def debug_reset
1366
+ if @last_index && @last_e
1367
+ @last_e.unmark_debug(@last_index)
1368
+ end
1369
+ end
1370
+
1371
+ def open_file_in_debug(_filename=nil, _line=nil)
1372
+ debug_reset
1373
+ if _filename && _line
1374
+
1375
+ @last_index = _line.to_s+'.0'
1376
+ _editor_exist = editor_exist?(_filename)
1377
+ @last_e = open_file(_filename, @last_index)
1378
+ if !_editor_exist
1379
+ @editors_in_debug << @last_e
1380
+ end
1381
+ @last_e.mark_debug(@last_index) if @last_e
1382
+
1383
+ end
1384
+ end
1385
+
1386
+ def do_buffer_raise(_name, _title='...')
1387
+ _index = @main_frame.enb.index(_name)
1388
+ _new_caption = '...'
1389
+ if _index != -1
1390
+ #_name = @main_frame.enb.pages(_index)
1391
+ #_tab = get_tab_from_name(_name)
1392
+ #@main_frame.enb.raise(_name)
1393
+ _e = @tabs_editor[_name]
1394
+ if _e && _e.file != nil
1395
+ _new_caption = _e.file
1396
+ @find.use(_e)
1397
+ _e.check_file_last_access_time
1398
+ else
1399
+ _new_caption = _title
1400
+ end
1401
+ end
1402
+ if @arcadia.layout.headed?
1403
+ @arcadia.layout.domain(@arcadia['conf'][@name+'.frame'])['root'].top_text(_new_caption)
1404
+ end
1405
+ _title = @tabs_file[_name] != nil ? File.basename(@tabs_file[_name]) :_name
1406
+ EditorContract.instance.buffer_raised(EditorContract::TEditorObj.new(self, 'title'=>_title, 'file'=>@tabs_file[_name]))
1407
+ end
1408
+
1409
+ def editor_exist?(_filename)
1410
+ _basefilename = File.basename(_filename)
1411
+ #_basename = _basefilename.split('.')[0]+'_'+_basefilename.split('.')[1]
1412
+
1413
+
1414
+ _index = @main_frame.enb.index(self.tab_name(_filename))
1415
+ return _index != -1
1416
+ end
1417
+
1418
+ def tab_name(_filename="")
1419
+ 'ff'+File.expand_path(_filename).gsub("/","_").gsub(".","_")
1420
+ end
1421
+
1422
+ def open_file(_filename = nil, _text_index='1.0')
1423
+ return if _filename == nil || !File.exist?(_filename)
1424
+ _basefilename = File.basename(_filename)
1425
+ _tab_name = self.tab_name(_filename)
1426
+ _index = @main_frame.enb.index(_tab_name)
1427
+ _exist_buffer = _index != -1
1428
+
1429
+ if _exist_buffer
1430
+ open_buffer(_tab_name)
1431
+ else
1432
+ open_buffer(_tab_name, _basefilename)
1433
+ # _basefilename.include?('.rb')?_image = RUBY_DOCUMENT_GIF: _image = DOCUMENT_OPEN_GIF
1434
+ # @main_frame.enb.itemconfigure(_tab_name,
1435
+ # 'image'=> TkPhotoImage.new('data' =>_image )
1436
+ # )
1437
+ @tabs_file[_tab_name]= _filename
1438
+ @tabs_editor[_tab_name].load_file(_filename)
1439
+ #do_buffer_raise(_tab_name)
1440
+ _tobj =EditorContract::TEditorObj.new(self)
1441
+ _tobj.file= _filename
1442
+ EditorContract.instance.file_opened(_tobj)
1443
+ end
1444
+
1445
+ if _text_index != nil && _text_index != '1.0'
1446
+ @tabs_editor[_tab_name].text_see(_text_index)
1447
+ #@tabs_editor[_tab_name].mark_selected(_text_index)
1448
+ end
1449
+
1450
+ return @tabs_editor[_tab_name]
1451
+ end
1452
+
1453
+
1454
+ def open_buffer(_buffer_name = nil, _title = nil)
1455
+ _index = @main_frame.enb.index(_buffer_name)
1456
+ _buffer_name = 'new' if _buffer_name == nil
1457
+ if _index != -1
1458
+ _tab = @main_frame.enb.get_frame(_buffer_name)
1459
+ @main_frame.enb.raise(_buffer_name)
1460
+ else
1461
+ _n = 1
1462
+ while @main_frame.enb.index(_buffer_name) != -1
1463
+ _buffer_name = 'new'+_n.to_s
1464
+ _n =_n+1
1465
+ end
1466
+ if _title == nil
1467
+ _title = '*'+_buffer_name
1468
+ end
1469
+ _tab = @main_frame.enb.insert('end', _buffer_name ,
1470
+ 'text'=> _title,
1471
+ 'raisecmd'=>proc{do_buffer_raise(_buffer_name, _title)}
1472
+ )
1473
+ _e = AgEditor.new(self, _tab)
1474
+ _e.init_editing(_e.file_extension(_title))
1475
+ @tabs_file[_buffer_name]= nil
1476
+ @tabs_editor[_buffer_name]=_e
1477
+ end
1478
+ @main_frame.enb.move(_buffer_name, 1)
1479
+ @main_frame.enb.raise(_buffer_name)
1480
+ @main_frame.enb.see(_buffer_name)
1481
+ return _tab
1482
+ end
1483
+
1484
+ def close_others_editor(_editor, _mod=true)
1485
+ @tabs_editor.values.each do |_e|
1486
+ close_editor(_e) if _e != _editor
1487
+ end
1488
+ end
1489
+
1490
+
1491
+ def close_editor(_editor, _mod=true)
1492
+ if ((_mod)&&(_editor.modified?))
1493
+ _message = @main_frame.enb.itemcget(page_name(_editor.page_frame), 'text')+"\n modified. Save?"
1494
+ _r = TkDialog2.new('message'=>_message, 'buttons'=>['Ok','No','Cancel']).show()
1495
+ if _r == 0
1496
+ _editor.save
1497
+ elsif _r == 1
1498
+ close_tab(_editor.page_frame)
1499
+ elsif _r == 2
1500
+ return
1501
+ end
1502
+ else
1503
+ close_tab(_editor.page_frame)
1504
+ end
1505
+ _tobj = EditorContract::TEditorObj.new(self)
1506
+ _tobj.file = _editor.file
1507
+ EditorContract.instance.file_closed(_tobj)
1508
+ end
1509
+
1510
+ def close_tab(_page_frame)
1511
+ _name = page_name(_page_frame)
1512
+ @tabs_editor.delete(_name)
1513
+ _index = @main_frame.enb.index(_name)
1514
+ @main_frame.enb.delete(_name)
1515
+ if !@main_frame.enb.pages.empty?
1516
+ @main_frame.enb.raise(@main_frame.enb.pages[_index-1])
1517
+ end
1518
+ end
1519
+
1520
+ def close_file(_filename)
1521
+ close_editor(@tabs_editor[tab_name(_filename)])
1522
+ end
1523
+ end
1524
+
1525
+ class Findview < TkFrame
1526
+ def initialize(_parent)
1527
+ super(_parent)
1528
+ @cb_reg = TkCheckButton.new(self){|_cb_reg|
1529
+ text 'regexp'
1530
+ justify 'left'
1531
+ relief 'flat'
1532
+ pack('side'=>'left', 'anchor'=>'e')
1533
+ #place('relwidth' => 0,'x' => 8,'y' => 14,'relheight' => 0,'rely' => 0,'height' => 22,'bordermode' => 'inside','width' => 62)
1534
+ }
1535
+ # @e_kind = Tk::BWidget::ComboBox.new(self){
1536
+ # editable true
1537
+ # justify 'left'
1538
+ # relief 'groove'
1539
+ # autocomplete 'true'
1540
+ # insertbackground '#FFFFFF'
1541
+ # expand 'tab'
1542
+ # values 'forwards backwards page'
1543
+ # takefocus 'true'
1544
+ # pack('side'=>'left', 'anchor'=>'e')
1545
+ # }
1546
+ @rb = TkRadioButton.new(self){
1547
+ value 'forwards'
1548
+ text 'forwards'
1549
+ select
1550
+ pack('side'=>'left', 'anchor'=>'e')
1551
+ #place('relx' => 0,'x' => 8,'y' => 64,'relheight' => 0,'rely' => 0,'height' => 23,'bordermode' => 'inside')
1552
+ }
1553
+ TkRadioButton.new(self){
1554
+ value 'backwards'
1555
+ text 'backwards'
1556
+ pack('side'=>'left', 'anchor'=>'e')
1557
+ #place('relx' => 0,'x' => 8,'y' => 84,'relheight' => 0,'rely' => 0,'height' => 23,'bordermode' => 'inside')
1558
+ }
1559
+ TkRadioButton.new(self){
1560
+ value 'line'
1561
+ text 'line'
1562
+ pack('side'=>'left', 'anchor'=>'e')
1563
+ #place('relx' => 0,'x' => 8,'y' => 104,'relheight' => 0,'rely' => 0,'height' => 23,'bordermode' => 'inside')
1564
+ }
1565
+ # TkLabel.new(self){
1566
+ # text 'what'
1567
+ # pack('side'=>'left', 'anchor'=>'e')
1568
+ # }
1569
+ @b_go = TkButton.new(self){|_b_go|
1570
+ compound 'none'
1571
+ default 'disabled'
1572
+ text 'Find'
1573
+ #background '#ffffff'
1574
+ image TkPhotoImage.new('dat' => FIND_GIF)
1575
+ overrelief 'raised'
1576
+ justify 'center'
1577
+ relief 'ridge'
1578
+ width 20
1579
+ pack('side'=>'right','ipadx'=>20)
1580
+ #place('width' => 50,'x' => 0,'y' => 130,'height' => 23,'bordermode' => 'inside')
1581
+ }
1582
+ @e_what = Tk::BWidget::ComboBox.new(self){
1583
+ editable true
1584
+ justify 'left'
1585
+ relief 'ridge'
1586
+ autocomplete 'true'
1587
+ #insertbackground '#FFFFFF'
1588
+ entrybg '#FFFFFF'
1589
+ expand 'tab'
1590
+ takefocus 'true'
1591
+ pack('padx'=>10, 'fill'=>'x')
1592
+ #place('relwidth' => 1, 'x' => 0,'y' => 41,'height' => 19)
1593
+ }
1594
+ place('x'=>0,'y'=>0,'relheight'=> 1,'relwidth'=> 1)
1595
+
1596
+ end
1597
+ end
1598
+
1599
+ class Find < Findview
1600
+ attr_reader :e_what
1601
+ def initialize(_frame, _controller)
1602
+ super(_frame)
1603
+ #@l_file.configure('text'=>_title)
1604
+ #Tk.tk_call('wm', 'title', self, _title )
1605
+ @controller = _controller
1606
+ @forwards = true
1607
+ @find_action = proc{
1608
+ _radio = @rb.get_value
1609
+ if _radio == 'line'
1610
+ go_line
1611
+ else
1612
+ @forwards = _radio == 'forwards'
1613
+ do_find_next
1614
+ end
1615
+ }
1616
+ @b_go.bind('1', @find_action)
1617
+ e = TkWinfo.children(@e_what)[0]
1618
+ e.bind_append('KeyPress'){|e|
1619
+ case e.keysym
1620
+ when 'Return'
1621
+ @find_action.call
1622
+ break
1623
+ end
1624
+ }
1625
+ @last_index='insert'
1626
+ end
1627
+
1628
+ def editor
1629
+ if @editor_caller == nil
1630
+ @editor_caller = @controller.raised
1631
+ end
1632
+ return @editor_caller
1633
+ end
1634
+
1635
+
1636
+ def go_line
1637
+ if @e_what.value.length > 0
1638
+ _row = @e_what.value
1639
+ _index = _row+'.1'
1640
+ self.editor.text.see(_index)
1641
+ self.editor.text.tag_add('sel', _index,_index+' lineend')
1642
+ self.editor.text.set_insert(_index)
1643
+ @controller.bookmark_add(self.editor.file, _index)
1644
+ end
1645
+ #self.hide()
1646
+ end
1647
+
1648
+ def use(_editor)
1649
+ if (_editor != @editor_caller)
1650
+ @last_index='insert'
1651
+ @editor_caller = _editor
1652
+ end
1653
+ end
1654
+
1655
+ def update_combo(_txt)
1656
+ values = @e_what.cget('values')
1657
+ if (values != nil && !values.include?(_txt))
1658
+ @e_what.insert('end', @e_what.value)
1659
+ end
1660
+ end
1661
+
1662
+ def do_find(_istart=nil)
1663
+ if @e_what.text.length > 0
1664
+ update_combo(@e_what.text)
1665
+ if !_istart && self.editor.text.index('insert')!=nil
1666
+ _istart ='insert'
1667
+ elsif defined?(@last_index)
1668
+ _istart = @last_index
1669
+ else
1670
+ _istart = '1.0'
1671
+ end
1672
+ if @forwards
1673
+ if @cb_reg.cget('onvalue')=='1'
1674
+ _index = self.editor.text.rsearch(@e_what.text,_istart)
1675
+ else
1676
+ _index = self.editor.text.search(@e_what.text,_istart)
1677
+ end
1678
+ else
1679
+
1680
+ if @cb_reg.cget('onvalue')=='1'
1681
+ _index = self.editor.text.tkrsearch(['backwards'],@e_what.text,_istart)
1682
+ else
1683
+ _index = self.editor.text.tksearch(['backwards'],@e_what.text,_istart)
1684
+ end
1685
+ end
1686
+ if _index && _index.length>0
1687
+ self.editor.text.see(_index)
1688
+ _row, _col = _index.split('.')
1689
+ _index_sel_end = _row.to_i.to_s+'.'+(_col.to_i+@e_what.text.length).to_i.to_s
1690
+ if @forwards
1691
+ @last_index= _index_sel_end
1692
+ else
1693
+ @last_index= _row.to_i.to_s+'.'+(_col.to_i-1).to_i.to_s
1694
+ end
1695
+ self.editor.text.tag_add('sel', _index,_index_sel_end)
1696
+ self.editor.text.set_insert(_index)
1697
+ @controller.bookmark_add(self.editor.file, _index)
1698
+ else
1699
+ _message = '"'+@e_what.value+'" not found'
1700
+ TkDialog2.new('message'=>_message, 'buttons'=>['Ok']).show()
1701
+ end
1702
+
1703
+ else
1704
+ self.show()
1705
+ end
1706
+ end
1707
+
1708
+ def do_find_next
1709
+ do_find(@last_index)
1710
+ end
1711
+ end
1712
+
1713
+
1714
+ class KeyTestView < TkToplevel
1715
+ attr_reader :ttest
1716
+ def initialize
1717
+ super
1718
+
1719
+ Tk.tk_call('wm', 'title', self, '...hello' )
1720
+ Tk.tk_call('wm', 'geometry', self, '638x117+200+257' )
1721
+
1722
+ @ttest = TkText.new(self){
1723
+ background '#FFF454'
1724
+ place('relwidth' => '1','relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => '0','bordermode' => 'inside','width' => '0')
1725
+ }
1726
+
1727
+ end
1728
+ end
1729
+
1730
+ class KetTest
1731
+ def initialize
1732
+ kt = KeyTestView.new
1733
+ kt.ttest.bind("KeyPress"){|e|
1734
+ kt.ttest.insert('end'," [ "+e.keysym+" ] ")
1735
+ break
1736
+ }
1737
+ end
1738
+ end
1739
+
1740
+ class AgTkEditor < AgEditor
1741
+ end
1742
+
1743
+ class AgTkMultiEditor < AgMultiEditor
1744
+ end