arcadia 0.1.2 → 0.1.2.1

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.
data/README CHANGED
@@ -1,126 +1,142 @@
1
- Arcadia Ruby Ide
2
- version 0.1.2
3
-
4
- by Antonio Galeone
5
- on May 8, 2007
6
-
7
- "Thank you for consider this project"
8
-
9
- About
10
- =====
11
- Arcadia is a Integrated Development Environment (IDE) for Ruby language
12
- written in Ruby using the classic tcl/tk GUI toolkit.
13
-
14
- Some of Arcadia ruby ide project features include:
15
- -Editor with source browsing, syntax highlighting, code completion
16
- -Contextual ruby documentation
17
- -Supporting RAD gui building
18
- -Generation of widget-wrapper-independent ruby code
19
- -Working on any platform where ruby and tcl-tk work.
20
- -Highly extensibility architecture.
21
-
22
- This release
23
- ============
24
- -[fixed] Bugs fixed and general restyling
25
- -[new] Added integration with ri--Ruby (F1) for display contextual ruby documentation
26
- -[new] Enhanced find/replace dialog
27
-
28
- Short User guide
29
- ================
30
- I hope that you perceive Arcadia gui enough user frindly.
31
- As you can see the application is splitted in vertical
32
- and horizontal resizing frames. Clicking on vertical splitter
33
- appear two button for left or right one shot frame close.
34
- The horizontal splitter has two little button for the same reason
35
- (perhaps i will conform them to the vertical style).
36
- Every frame has a title and a button to expand or resizing it.
37
- In this beta release there are very essential feature:
38
-
39
- < Toolbar >
40
- The toolbar button are in order:
41
- -new, open, save
42
- (relatively to editor extension)
43
- -run current, run last
44
- (for execute the raised file in the editor or the last file executed)
45
- -debug current, debug last, stop debug
46
- (for the debug extension that is in very unstable state)
47
- -quit (to exit from arcadia)
48
-
49
- < Editor >
50
- Editor use the notebook metaphor. Same command are on the popup menu
51
- that is raised on "Button-3" click event fundamentalally for closing the tab
52
- under the mouse pointer.
53
- These are same editor short-cut:
54
- Ctrl-c => copy selected text
55
- Ctrl-v => paste copied text
56
- Ctrl-x => cut selected text
57
- Ctrl-z => undo
58
- Ctrl-f => copy the selected text on input combobox of find dialog and moves focus
59
- Ctrl-s => save
60
- Ctrl-space => completion code
61
- Ctrl-shift-i => indent the selected block
62
- Ctrl-shift-u => unindent the selected block
63
- Ctrl-shift-c => comment/uncomment the selected code block
64
- F5 => execute the file
65
- F3 => find/ find next
66
- F1 => contextual ruby documentation (called from editor or from code completion item, if
67
- no corrispondation is founded a doc tree is build in left side)
68
-
69
- Double-Click on line number set or unset a debug breckpoint
70
-
71
- < File history >
72
- The last used files are organizing in tree so you can reopen them or there
73
- directory by clicking on the tree node.
74
-
75
- < Palette >
76
- It contain the wrapper components for the tk gui building.
77
- It is in very unstabled and incomplete state.
78
- The first component is a TkTopLevel wrapper, when you click on it a new form is created and a
79
- Object inspector appears.
80
- The other components must be first selected and then created by clicking on container widget.
81
- The so created widgets has a popup menu for deleting them or in the toplevel case to switch
82
- to a code view.
83
- On the palette there are also two button, one for deselect and other for copy from the selected
84
- created widget. The copy action copy also the code into the clipboard, so you can copy the
85
- code rapresenting the gui into the embedded editor or into external editor.
86
-
87
- < Object Inspector >
88
- It is for modify the widget property at runtime
89
-
90
- < Debug >
91
- It is created when a debug session init.
92
- The debug button are: Step Next, Step Into, Step Over, Resume.
93
- The debug frame show the local, instance and global variables for each
94
- step. (you must have patience!)
95
-
96
- <Configuration>
97
- Same Arcadia properties are locally configurabled by editing the file arcadia.conf
98
- under ~/.arcadia directory. The format of property definition are:
99
- <OPERATING SYSTEM IDENTIFY::>PROPERTY_NAME=PROPERTY_VALUE
100
-
101
-
102
- Requirement
103
- ===========
104
- I include into distribution also the BWidget lib (under tcl directory) so
105
- are require realy only the standard tcl tk lib (tested on tcl tk 8.4).
106
- I have tested arcadia with ruby 1.8.4, 1.8.5, 1.8.6 on FreeBsd6, Vector linux and windows 2000/XP os. If you
107
- will test arcadia on other operating system sends me an e-mail.
108
-
109
- Developers information
110
- =====================
111
- Soon i will write samething about the arcadia software architecture (when it is more stable)
112
- in order to allow extensions writing and collaborations.
113
-
114
-
115
-
116
- License
117
- =======
118
- Arcadia is released under the Ruby License
119
-
120
- Contacts
121
- ========
122
- For questions:
123
- antonio-galeone@rubyforge.org
124
- For bugs, support request, feature request https://rubyforge.org/projects/arcadia:
125
-
126
- Bye
1
+ Arcadia Ruby Ide
2
+ version 0.1.2.1
3
+
4
+ by Antonio Galeone
5
+ on May 14, 2007
6
+
7
+ "Thank you for consider this project"
8
+
9
+ About
10
+ =====
11
+ Arcadia is a Integrated Development Environment (IDE) for Ruby language
12
+ written in Ruby using the classic tcl/tk GUI toolkit.
13
+
14
+ Some of Arcadia ruby ide project features include:
15
+ -Editor with source browsing, syntax highlighting, code completion
16
+ -Contextual ruby documentation
17
+ -Supporting RAD gui building
18
+ -Generation of widget-wrapper-independent ruby code
19
+ -Working on any platform where ruby and tcl-tk work.
20
+ -Highly extensibility architecture.
21
+
22
+ This release
23
+ ============
24
+ -[fixed] 10726 - test arcadia on cygwin and config files updated
25
+
26
+ How to install
27
+ ==============
28
+ There are two way:
29
+ 1)exec as root on command line "gem install arcadia"
30
+ 2)a) untar (on unix) tar -xzf arcadia-<version>.tar.gz
31
+ b) unzip (on windows) arcadia-<version>.zip
32
+
33
+
34
+ How to run
35
+ ==========
36
+ exec on comman line "ruby arcadia.rb"
37
+
38
+
39
+ Short User guide
40
+ ================
41
+ I hope that you perceive Arcadia gui enough user frindly.
42
+ As you can see the application is splitted in vertical
43
+ and horizontal resizing frames. Clicking on vertical splitter
44
+ appear two button for left or right one shot frame close.
45
+ The horizontal splitter has two little button for the same reason
46
+ (perhaps i will conform them to the vertical style).
47
+ Every frame has a title and a button to expand or resizing it.
48
+ In this beta release there are very essential feature:
49
+
50
+ < Toolbar >
51
+ The toolbar button are in order:
52
+ -new, open, save
53
+ (relatively to editor extension)
54
+ -run current, run last
55
+ (for execute the raised file in the editor or the last file executed)
56
+ -debug current, debug last, stop debug
57
+ (for the debug extension that is in very unstable state)
58
+ -quit (to exit from arcadia)
59
+
60
+ < Editor >
61
+ Editor use the notebook metaphor. Same command are on the popup menu
62
+ that is raised on "Button-3" click event fundamentalally for closing the tab
63
+ under the mouse pointer.
64
+ These are same editor short-cut:
65
+ Ctrl-c => copy selected text
66
+ Ctrl-v => paste copied text
67
+ Ctrl-x => cut selected text
68
+ Ctrl-z => undo
69
+ Ctrl-f => copy the selected text on input combobox of find dialog and moves focus
70
+ Ctrl-s => save
71
+ Ctrl-space => completion code
72
+ Ctrl-shift-i => indent the selected block
73
+ Ctrl-shift-u => unindent the selected block
74
+ Ctrl-shift-c => comment/uncomment the selected code block
75
+ F5 => execute the file
76
+ F3 => find/ find next
77
+ F1 => contextual ruby documentation (called from editor or from code completion item, if
78
+ no corrispondation is founded a doc tree is build in left side)
79
+
80
+ Double-Click on line number set or unset a debug breckpoint
81
+
82
+ < File history >
83
+ The last used files are organizing in tree so you can reopen them or there
84
+ directory by clicking on the tree node.
85
+
86
+ < Palette >
87
+ It contain the wrapper components for the tk gui building.
88
+ It is in very unstabled and incomplete state.
89
+ The first component is a TkTopLevel wrapper, when you click on it a new form is created and a
90
+ Object inspector appears.
91
+ The other components must be first selected and then created by clicking on container widget.
92
+ The so created widgets has a popup menu for deleting them or in the toplevel case to switch
93
+ to a code view.
94
+ On the palette there are also two button, one for deselect and other for copy from the selected
95
+ created widget. The copy action copy also the code into the clipboard, so you can copy the
96
+ code rapresenting the gui into the embedded editor or into external editor.
97
+
98
+ < Object Inspector >
99
+ It is for modify the widget property at runtime
100
+
101
+ < Debug >
102
+ It is created when a debug session init.
103
+ The debug button are: Step Next, Step Into, Step Over, Resume.
104
+ The debug frame show the local, instance and global variables for each
105
+ step. (you must have patience!)
106
+
107
+ <Configuration>
108
+ Same Arcadia properties are locally configurabled by editing the file arcadia.conf
109
+ under ~/.arcadia directory. The format of property definition are:
110
+ <OPERATING SYSTEM IDENTIFY::>PROPERTY_NAME=PROPERTY_VALUE
111
+
112
+
113
+ Requirement
114
+ ===========
115
+ I include into distribution also the BWidget lib (under tcl directory) so
116
+ are require realy only the standard tcl tk lib (tested on tcl tk 8.4).
117
+ I have tested arcadia with ruby 1.8.4, 1.8.5, 1.8.6 on
118
+ FreeBsd6.x,
119
+ Vector linux 5.8,
120
+ Windows 2000/XP,
121
+ Cygwin (note: same page fault error on dll under cygwin may be solved in this way:
122
+ by ash.exe exec "/bin/rebaseall").
123
+ If you will test arcadia on other operating system sends me an e-mail.
124
+
125
+ Developers information
126
+ =====================
127
+ Soon i will write samething about the arcadia software architecture (when it is more stable)
128
+ in order to allow extensions writing and collaborations.
129
+
130
+
131
+
132
+ License
133
+ =======
134
+ Arcadia is released under the Ruby License
135
+
136
+ Contacts
137
+ ========
138
+ For questions:
139
+ antonio-galeone@rubyforge.org
140
+ For bugs, support request, feature request https://rubyforge.org/projects/arcadia:
141
+
142
+
data/arcadia.rb CHANGED
@@ -1,770 +1,770 @@
1
- #
2
- # arcadia.rb - Arcadia Ruby ide
3
- # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
- #
5
-
6
- Dir.chdir(File.dirname(__FILE__))
7
- if FileTest.exist?('conf/arcadia.init.rb')
8
- require 'conf/arcadia.init'
9
- end
10
- require "conf/arcadia.res"
11
- require 'tkextlib/bwidget'
12
- require "base/a-utils"
13
- require "base/a-ext"
14
- require "base/a-contracts"
15
- require "observer"
16
-
17
- class Arcadia < TkApplication
18
- include Observable
19
- attr_reader :layout
20
- attr_reader :libs
21
- #attr_reader :main_contract
22
- def initialize
23
- super(
24
- ApplicationParams.new(
25
- 'arcadia',
26
- '0.1.2',
27
- 'conf/arcadia.conf',
28
- 'conf/arcadia.pers'
29
- )
30
- )
31
- self.load_local_config(false)
32
- ObjectSpace.define_finalizer($arcadia, self.class.method(:finalize).to_proc)
33
- publish('action.on_exit', proc{do_exit})
34
- _title = "Arcadia Ruby ide :: [Platform = "+RUBY_PLATFORM+'] [Ruby version = ' + RUBY_VERSION+']'
35
- @root = TkRoot.new{
36
- title _title
37
- withdraw
38
- protocol( "WM_DELETE_WINDOW", $arcadia['action.on_exit'])
39
- }
40
- @on_event = Hash.new
41
- @main_menu = TkMenubar.new.pack('fill'=>'x')
42
- @mf_root = Tk::BWidget::MainFrame.new(@root){
43
- menu @main_menu
44
- }.pack(
45
- 'anchor'=> 'center',
46
- 'fill'=> 'both',
47
- 'expand'=> 1
48
- )
49
-
50
- #.place('x'=>0,'y'=>0,'relwidth'=>1,'relheight'=>1)
51
- @mf_root.show_statusbar('none')
52
- @toolbar = @mf_root.add_toolbar
53
- @is_toolbar_show=self['conf']['toolbar_show']=='yes'
54
- @mf_root.show_toolbar(0,@is_toolbar_show)
55
- @splash = ArcadiaAboutSplash.new('... initialize')
56
- @splash.set_progress(50)
57
- @splash.deiconify
58
- Tk.update
59
- sleep(1)
60
- @splash.next_step('..prepare')
61
- prepare
62
- @splash.last_step('..load finish')
63
- geometry = (TkWinfo.screenwidth(@root)-4).to_s+'x'+
64
- (TkWinfo.screenheight(@root)-20).to_s+'+0+0'
65
- @root.deiconify
66
- @root.raise
67
- @root.focus(true)
68
- @root.geometry(geometry)
69
- Tk.update_idletasks
70
- sleep(1)
71
- @splash.destroy
72
- if @first_run
73
- EditorContract.instance.open_file(self, 'file'=>'README')
74
- end
75
- end
76
-
77
- def show_hide_toolbar
78
- if @is_toolbar_show
79
- @mf_root.show_toolbar(0,false)
80
- @is_toolbar_show = false
81
- else
82
- @mf_root.show_toolbar(0,true)
83
- Tk.update
84
- @is_toolbar_show = true
85
- end
86
-
87
- end
88
-
89
-
90
- def Arcadia.finalize(id)
91
- puts "\nArcadia #{id} dying at #{Time.new}"
92
- end
93
-
94
- def load_libs
95
- @libs = ArcadiaLibs.new(self)
96
- libs = self['conf']['libraries'].split(',')
97
- libs.each{|lib|
98
- if lib
99
- @splash.next_step('... loading library '+lib)
100
- begin
101
- require self['conf']['libraries.'+lib+'.source']
102
- @libs.add_lib(
103
- ArcadiaLibs::ArcadiaLibParams.new(
104
- self['conf']['libraries.'+lib+'.name'],
105
- self['conf']['libraries.'+lib+'.source'],
106
- self['conf']['libraries.'+lib+'.require'],
107
- eval(self['conf']['libraries.'+lib+'.collection.class']))
108
- )
109
- rescue Exception
110
- msg = "Loading lib "+'"'+lib+'"'+" ("+$!.class.to_s+") "+" : "+$! + " at : "+$@.to_s
111
- if Tk.messageBox('icon' => 'error', 'type' => 'okcancel',
112
- 'title' => '(Arcadia) Libs', 'parent' => @root,
113
- 'message' => msg) == 'cancel'
114
- raise
115
- exit
116
- else
117
- Tk.update
118
- end
119
- end
120
- end
121
- }
122
- end
123
-
124
- def load_toolbar_buttons
125
- suf = 'toolbar_buttons'
126
- @buttons = Hash.new
127
- toolbar_buttons = self['conf'][suf].split(',')
128
- toolbar_buttons.each{|groups|
129
- if groups
130
- suf1 = suf+'.'+groups
131
- @splash.next_step('... loading '+suf1)
132
- begin
133
- buttons = self['conf'][suf1].split(',')
134
- buttons.each{|button|
135
- suf2 = suf1+'.'+button
136
- name = self['conf'][suf2+'.name']
137
- text = self['conf'][suf2+'.text']
138
- image = self['conf'][suf2+'.image']
139
- font = self['conf'][suf2+'.font']
140
- background = self['conf'][suf2+'.background']
141
- foreground = self['conf'][suf2+'.foreground']
142
- hint = self['conf'][suf2+'.hint']
143
- action = self['conf'][suf2+'.action']
144
- actions = action.split('->') if action
145
- if actions && actions.length>1
146
- _command = proc{
147
- action_obj = $arcadia[actions[0]]
148
- 1.upto(actions.length-2) do |x|
149
- action_obj = action_obj.send(actions[x])
150
- end
151
- action_obj.send(actions[actions.length-1])
152
- }
153
- elsif action
154
- _command = proc{$arcadia[action].call}
155
- end
156
- @buttons[name] = Tk::BWidget::Button.new(@toolbar){
157
- image TkPhotoImage.new('data' => eval(image)) if image
158
- borderwidth 1
159
- font font if font
160
- background background if background
161
- foreground foreground if foreground
162
- command _command if action
163
- relief 'flat'
164
- helptext hint if hint
165
- text text if text
166
- pack('side' =>'left', :padx=>2, :pady=>2)
167
- }
168
- }
169
- rescue Exception
170
- msg = 'Loading '+groups+'" -> '+buttons.to_s+ '" (' + $!.class.to_s + ") : " + $!.to_s + " at : "+$@.to_s
171
- if Tk.messageBox('icon' => 'error', 'type' => 'okcancel',
172
- 'title' => '(Arcadia) Toolbar', 'parent' => @root,
173
- 'message' => msg) == 'cancel'
174
- raise
175
- exit
176
- else
177
- Tk.update
178
- end
179
- end
180
- end
181
- Tk::BWidget::Separator.new(@toolbar, :orient=>'vertical').pack('side' =>'left', :padx=>2, :pady=>2, :fill=>'y',:anchor=> 'w')
182
- }
183
- end
184
-
185
- def ext_active?(_name)
186
- return (self['conf'][_name+'.active'] != nil && self['conf'][_name+'.active']=='yes')||
187
- (self['conf'][_name+'.active'] == nil)
188
- end
189
-
190
- def load_exts_conf
191
- @exts = Array.new
192
- dirs = Array.new
193
- files = Dir['ext/*'].concat(Dir[ENV["HOME"]+'/.arcadia/ext/*'])
194
- files.each{|f|
195
- dirs << f if File.stat(f).directory? && FileTest.exist?(f+'/'+File.basename(f)+'.conf')
196
- }
197
- dirs.each{|ext_dir|
198
- conf_hash = self.config_file2hash(ext_dir+'/'+File.basename(ext_dir)+'.conf')
199
- conf_hash2 = Hash.new
200
- name = conf_hash['name']
201
- conf_hash.each{|key, value|
202
- var_plat = key.split(':')
203
- if var_plat.length > 1
204
- new_key = var_plat[0] + ':' + name + '.' + var_plat[1]
205
- else
206
- new_key = name+'.'+key
207
- end
208
- conf_hash2[new_key]= value
209
- }
210
- @exts << name
211
- self['conf'].update(conf_hash2)
212
- }
213
- end
214
-
215
- def load_exts
216
-
217
- # create extensions
218
- @exts.each{|extension|
219
- if extension && ext_active?(extension)
220
- @splash.next_step('... creating '+extension)
221
- ext_create(extension)
222
- end
223
- }
224
-
225
- # before_build extensions
226
- @exts.each{|extension|
227
- if extension && ext_active?(extension)
228
- @splash.next_step('... before building '+extension)
229
- ext_method(extension, :before_build)
230
- MainContract.instance.extension_before_build(self, 'obj'=>self[extension])
231
- end
232
- }
233
-
234
- # build extensions
235
- @exts.each{|extension|
236
- if extension && ext_active?(extension)
237
- @splash.next_step('... building '+extension)
238
- ext_method(extension, :build)
239
- MainContract.instance.extension_build(self, 'obj'=>self[extension])
240
- end
241
- }
242
-
243
- # after build extensions
244
- @exts.each{|extension|
245
- if extension && ext_active?(extension)
246
- @splash.next_step('... after building '+extension)
247
- ext_method(extension, :after_build)
248
- MainContract.instance.extension_after_build(self, 'obj'=>self[extension])
249
- end
250
- }
251
-
252
- end
253
-
254
- def ext_create(_extension)
255
- begin
256
- source = self['conf'][_extension+'.require']
257
- class_name = self['conf'][_extension+'.class']
258
- if source.strip.length > 0
259
- #p source
260
- eval('require ' + "'" + source + "'")
261
- end
262
- if class_name.strip.length > 0
263
- publish(_extension, eval(class_name).new(self, _extension))
264
- end
265
- rescue Exception
266
- raise
267
- msg = "Loading "+'"'+extension+'"'+" ("+$!.class.to_s+") "+" : "+$! + " at : "+$@.to_s
268
- ans = Tk.messageBox('icon' => 'error', 'type' => 'abortretryignore',
269
- 'title' => '(Arcadia) Extensions', 'parent' => @root,
270
- 'message' => msg)
271
- if ans == 'abort'
272
- raise
273
- exit
274
- elsif ans == 'retry'
275
- retry
276
- else
277
- Tk.update
278
- end
279
- end
280
- end
281
-
282
- def ext_method(_extension, _method)
283
- begin
284
- self[_extension].send(_method)
285
- rescue Exception
286
- msg = _method.to_s+' "'+_extension.to_s+'"'+" ("+$!.class.to_s+") "+" : "+$! + "\n at : "+$@.to_s
287
- ans = Tk.messageBox('icon' => 'warning', 'type' => 'abortretryignore',
288
- 'title' => '(Arcadia) Extensions', 'parent' => @root,
289
- 'message' => msg)
290
- if ans == 'abort'
291
- raise
292
- exit
293
- elsif ans == 'retry'
294
- retry
295
- else
296
- Tk.update
297
- end
298
- end
299
- end
300
-
301
-
302
- def prepare
303
- super
304
- @splash.next_step('...initialize')
305
- @layout = ArcadiaLayout.new(self, @mf_root.get_frame)
306
-
307
- @layout.add_cols(0,0,225)
308
- @layout.add_rows(0,0,180)
309
- # @layout.add_rows(0,1,500)
310
- @layout.add_rows_perc(0,1,70)
311
-
312
-
313
- @layout.add_headers
314
- @splash.next_step
315
- self.load_libs
316
- @splash.next_step
317
- @splash.next_step('... load extensions')
318
- self.load_exts_conf
319
- self.load_local_config
320
- self.load_exts
321
- publish('buffers.code.in_memory',Hash.new)
322
- publish('action.load_code_from_buffers', proc{TkBuffersChoise.new})
323
- publish('output.action.run_last', proc{$arcadia['output'].run_last})
324
- publish('main.action.open_file', proc{self['editor'].open_file(Tk.getOpenFile)})
325
- @splash.next_step('... load obj controller')
326
- @splash.next_step('... load editor')
327
- publish('main.action.new_file',proc{$arcadia['editor'].open_buffer()})
328
- publish('main.action.edit_cut',proc{$arcadia['editor'].raised.text.text_cut()})
329
- publish('main.action.edit_copy',proc{$arcadia['editor'].raised.text.text_copy()})
330
- publish('main.action.edit_paste',proc{$arcadia['editor'].raised.text.text_paste()})
331
- @splash.next_step('... load actions')
332
- publish('action.test.keys', proc{KetTest.new})
333
- publish('action.get.font', proc{Tk::BWidget::SelectFont::Dialog.new.create})
334
- @splash.next_step
335
- publish('action.show_about', proc{ArcadiaAboutSplash.new.deiconify})
336
- # publish('main.menu', @main_menu)
337
- publish('main.menu', AMainMenu.new(@main_menu))
338
- @splash.next_step
339
- publish('objic.action.raise_active_obj',
340
- proc{
341
- InspectorContract.instance.raise_active_toplevel(self)
342
- }
343
- )
344
- load_toolbar_buttons
345
- end
346
-
347
- def do_exit
348
- q1 = (Tk.messageBox('icon' => 'question', 'type' => 'yesno',
349
- 'title' => '(Arcadia) Exit', 'parent' => @root,
350
- 'message' => "Do you want exit?")=='yes')
351
- if q1 && can_exit?
352
- do_finalize
353
- @root.destroy
354
- end
355
- end
356
-
357
- def can_exit?
358
- _can_exit = true
359
- @exts.each{|extension|
360
- if ext_active?(extension) && !self[extension].can_exit_query
361
- _can_exit = false
362
- break
363
- end
364
- }
365
- return _can_exit
366
- end
367
-
368
- def do_finalize
369
- @exts.each{|extension|
370
- self[extension].finalize if ext_active?(extension)
371
- }
372
- self.write_persist
373
- end
374
- end
375
-
376
-
377
- class AMainMenu < TkMenubar
378
-
379
- def initialize(menu)
380
- # create main menu
381
- @menu = menu
382
- build
383
- menu.foreground('grey40')
384
- menu.activeforeground('red')
385
- menu.relief('groove')
386
- menu.borderwidth(0)
387
- menu.font($arcadia['conf']['main.mainmenu.font'])
388
- end
389
-
390
- def build
391
- menu_spec_file = [
392
- ['File', 0],
393
- ['Open', $arcadia['main.action.open_file'], 0],
394
- ['New', $arcadia['main.action.new_file'], 0],
395
- ['Save', proc{EditorContract.instance.save_file_raised(self)},0],
396
- ['Save as ...', proc{EditorContract.instance.save_as_file_raised(self)},0],
397
- '---',
398
- ['Quit', $arcadia['action.on_exit'], 0]]
399
- menu_spec_edit = [['Edit', 0],
400
- ['Cut', $arcadia['main.action.edit_cut'], 2],
401
- ['Copy', $arcadia['main.action.edit_copy'], 0],
402
- ['Paste', $arcadia['main.action.edit_paste'], 0]]
403
- menu_spec_search = [['Search', 0],
404
- ['Find ...', proc{EditorContract.instance.show_search_dialog(self)}, 2],
405
- ['Go to line ...', proc{EditorContract.instance.show_goto_line_dialog(self)}, 2]]
406
- menu_spec_view = [['View', 0],['Show/Hide Toolbar', proc{$arcadia.show_hide_toolbar}, 2]]
407
- menu_spec_tools = [['Utils', 0],
408
- ['Keys-test', $arcadia['action.test.keys'], 2],
409
- ['Load code from buffer', $arcadia['action.load_code_from_buffers'], 2]
410
- ]
411
- menu_spec_help = [['Help', 0],
412
- ['About', $arcadia['action.show_about'], 2],]
413
- @menu.add_menu(menu_spec_file)
414
- @menu.add_menu(menu_spec_edit)
415
- @menu.add_menu(menu_spec_search)
416
- @menu.add_menu(menu_spec_view)
417
- @menu.add_menu(menu_spec_tools)
418
- @menu.add_menu(menu_spec_help)
419
- end
420
-
421
- end
422
-
423
-
424
- class ArcadiaAboutSplash < TkToplevel
425
- attr :progress
426
-
427
- def initialize(_txt=nil)
428
- #_bgcolor = '#B83333'
429
- _bgcolor = '#000000'
430
- super()
431
- relief 'flat'
432
- background _bgcolor
433
- highlightbackground _bgcolor
434
- highlightthickness 6
435
- borderwidth 1
436
- withdraw
437
- overrideredirect(true)
438
-
439
- @tkLabel3 = TkLabel.new(self){
440
- image TkPhotoImage.new('format'=>'GIF','data' =>A_LOGO_GIF)
441
- background _bgcolor
442
- place('x'=> 20,'y' => 20)
443
- }
444
- @tkLabel1 = TkLabel.new(self){
445
- text 'Arcadia'
446
- background _bgcolor
447
- foreground '#ffffff'
448
- font Arcadia.instance['conf']['splash.title.font']
449
- justify 'left'
450
- place('width' => '190','x' => 120,'y' => 10,'height' => 25)
451
- }
452
- @tkLabelRuby = TkLabel.new(self){
453
- image TkPhotoImage.new('data' =>RUBY_DOCUMENT_GIF)
454
- background _bgcolor
455
- place('x'=> 150,'y' => 40)
456
- }
457
- @tkLabel2 = TkLabel.new(self){
458
- text 'Ruby ide'
459
- background _bgcolor
460
- foreground '#ffffff'
461
- font Arcadia.instance['conf']['splash.subtitle.font']
462
- justify 'left'
463
- place('width' => '90','x' => 170,'y' => 40,'height' => 19)
464
- }
465
- @tkLabelVersion = TkLabel.new(self){
466
- text 'version: '+$arcadia['applicationParams'].version
467
- background _bgcolor
468
- foreground '#ffffff'
469
- font Arcadia.instance['conf']['splash.version.font']
470
- justify 'left'
471
- place('width' => '100','x' => 150,'y' => 60,'height' => 19)
472
- }
473
- @tkLabelStep = TkLabel.new(self){
474
- text _txt
475
- background _bgcolor
476
- foreground 'yellow'
477
- font Arcadia.instance['conf']['splash.banner.font']
478
- justify 'left'
479
- anchor 'w'
480
- place('width'=>-5,'relwidth' => 1,'x' => 5,'y' => 175,'height' => 19)
481
- }
482
- @tkLabel21 = TkLabel.new(self){
483
- text 'by Antonio Galeone - 2007'
484
- background _bgcolor
485
- foreground '#ffffff'
486
- font Arcadia.instance['conf']['splash.credits.font']
487
- justify 'left'
488
- place('width' => '190','x' => 130,'y' => 146,'height' => 19)
489
- }
490
- @progress = TkVariable.new
491
- reset
492
- _width = 340
493
- _height = 210
494
- #_width = 0;_height = 0
495
- _x = TkWinfo.screenwidth(self)/2 - _width / 2
496
- _y = TkWinfo.screenheight(self)/2 - _height / 2
497
- geometry = _width.to_s+'x'+_height.to_s+'+'+_x.to_s+'+'+_y.to_s
498
- Tk.tk_call('wm', 'geometry', self, geometry )
499
- bind("Double-Button-1", proc{self.destroy})
500
- end
501
-
502
- def set_progress(_max=10)
503
- @max = _max
504
- Tk::BWidget::ProgressBar.new(self, :width=>150, :height=>10,
505
- :background=>'black',
506
- :foreground=>'yellow',
507
- :variable=>@progress,
508
- :borderwidth=>0,
509
- :relief=>'flat',
510
- :maximum=>_max).place('width' => '150','x' => 145,'y' => 95,'height' => 15)
511
- end
512
-
513
- def reset
514
- @progress.value = -1
515
- end
516
-
517
- def next_step(_txt = nil)
518
- @progress.numeric += 1
519
- labelStep(_txt) if _txt
520
- end
521
-
522
- def labelStep(_txt)
523
- @tkLabelStep.text = _txt
524
- Tk.update
525
- end
526
-
527
- def last_step(_txt = nil)
528
- @progress.numeric = @max
529
- labelStep(_txt) if _txt
530
- end
531
-
532
- end
533
-
534
- class TkBuffersChoiseView < TkToplevel
535
-
536
- def initialize
537
- super
538
- Tk.tk_call('wm', 'title', self, '...hello' )
539
- Tk.tk_call('wm', 'geometry', self, '150x217+339+198' )
540
- @lb = TkListbox.new(self){
541
- background '#fedbd7'
542
- relief 'groove'
543
- place('relwidth' => '1','relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => '0','bordermode' => 'inside','width' => '0')
544
- }
545
- end
546
-
547
- end
548
-
549
- class TkBuffersChoise < TkBuffersChoiseView
550
-
551
- def initialize
552
- super
553
- @lb.value= $arcadia['buffers.code.in_memory'].keys
554
- @lb.bind("Double-ButtonPress-1",proc{
555
- _sel = @lb.get('active')
556
- Revparsel.new($arcadia['buffers.code.in_memory'][_sel])
557
- @lb.delete('active')
558
- $arcadia['buffers.code.in_memory'].delete(_sel)
559
- destroy
560
- })
561
- raise
562
- end
563
-
564
- end
565
-
566
- class ArcadiaLayout
567
- include Observable
568
- ArcadiaPanelInfo = Struct.new( "ArcadiaPanelInfo",
569
- :name,
570
- :title,
571
- :frame
572
- )
573
-
574
- def initialize(_arcadia, _frame, _autotab=true)
575
- @arcadia = _arcadia
576
- @frames = Array.new
577
- @frames[0] = Array.new
578
- @frames[0][0] = _frame
579
- @domains = Array.new
580
- @domains[0] = Array.new
581
- @domains[0][0] = '_domain_root_'
582
- @panels = Hash.new
583
- @panels['_domain_root_']= Hash.new
584
- @panels['_domain_root_']['root']= _frame
585
- @panels['_domain_root_']['sons'] = Hash.new
586
- @autotab = _autotab
587
- @headed = false
588
- ArcadiaContractListener.new(self, MainContract, :do_main_event)
589
- end
590
- def root
591
- @panels['_domain_root_']['root']
592
- end
593
- def do_main_event(_event)
594
- case _event.signature
595
- when MainContract::RAISE_EXTENSION
596
- p = @panels[_event.context.domain]
597
- if p && p['notebook'] != nil && _event.channel == '0'
598
- p['notebook'].raise(_event.context.extension)
599
- end
600
- end
601
- end
602
-
603
- def _prepare_rows(_row,_col, _height, _perc=false, _top_name=nil, _bottom_name=nil)
604
- if (@frames[_row][_col] != nil)
605
- _h = AGTkOSplittedFrames.new(@frames[_row][_col],_height, _perc)
606
- if @frames[_row + 1] == nil
607
- @frames[_row + 1] = Array.new
608
- @domains[_row + 1] = Array.new
609
- end
610
- @frames[_row][_col] = _h.top_frame
611
- @frames[_row + 1][_col] = _h.bottom_frame
612
-
613
- _top_name = _row.to_s+'.'+_col.to_s if _top_name == nil
614
- @panels[_top_name] = Hash.new
615
- @panels[_top_name]['root'] = @frames[_row][_col]
616
- @panels[_top_name]['sons'] = Hash.new
617
- @domains[_row][_col] = _top_name
618
-
619
- _bottom_name = (_row+1).to_s+'.'+_col.to_s if _bottom_name == nil
620
- @panels[_bottom_name] = Hash.new
621
- @panels[_bottom_name]['root'] = @frames[_row + 1][_col]
622
- @panels[_bottom_name]['sons'] = Hash.new
623
- @domains[_row + 1][_col] = _bottom_name
624
- end
625
- end
626
- private :_prepare_rows
627
-
628
- def add_rows(_row,_col, _height, _top_name=nil, _bottom_name=nil)
629
- _prepare_rows(_row,_col, _height, false, _top_name, _bottom_name)
630
- end
631
-
632
- def add_rows_perc(_row,_col, _height, _top_name=nil, _bottom_name=nil)
633
- _prepare_rows(_row,_col, _height, true, _top_name, _bottom_name)
634
- end
635
-
636
-
637
- def add_cols(_row,_col, _width, _left_name=nil, _right_name=nil)
638
- if (@frames[_row][_col] != nil)
639
- _w = AGTkVSplittedFrames.new(@frames[_row][_col],_width)
640
- @frames[_row][_col] = _w.left_frame
641
- @frames[_row][_col + 1] = _w.right_frame
642
-
643
- _left_name = _row.to_s+'.'+_col.to_s if _left_name == nil
644
- @panels[_left_name] = Hash.new
645
- @panels[_left_name]['root'] = @frames[_row][_col]
646
- @panels[_left_name]['sons'] = Hash.new
647
- @domains[_row][_col] = _left_name
648
-
649
- _right_name = _row.to_s+'.'+(_col+1).to_s if _right_name == nil
650
- @panels[_right_name] = Hash.new
651
- @panels[_right_name]['root'] = @frames[_row][_col + 1]
652
- @panels[_right_name]['sons'] = Hash.new
653
- @domains[_row][_col + 1] = _right_name
654
- end
655
- end
656
-
657
- def add_headers
658
- @domains.each{|row|
659
- row.each{|domain|
660
- @panels[domain]['root']= TkTitledFrame.new(@panels[domain]['root'], '...').place('x'=>0, 'y'=>0,'relheight'=>1, 'relwidth'=>1) if @panels[domain]
661
- }
662
- }
663
- @headed = true
664
- end
665
-
666
- def headed?
667
- @headed
668
- end
669
-
670
- def autotab?
671
- @autotab
672
- end
673
-
674
- def registed?(_domain_name, _name)
675
- @panels[_domain_name]['sons'][_name] != nil
676
- end
677
-
678
- def register_panel(_domain_name, _name, _title)
679
- p = @panels[_domain_name]
680
- if p!=nil
681
- num = p['sons'].length
682
- if @headed
683
- p['root'].title(_title)
684
- root_frame = p['root'].frame
685
- else
686
- root_frame = p['root']
687
- end
688
- if (num == 0 && @autotab)
689
- api = ArcadiaPanelInfo.new(_name,_title,nil)
690
- api.frame = TkFrame.new(root_frame).place('x'=>0, 'y'=>0, 'relwidth'=>1, 'relheight'=>1)
691
- p['sons'][_name] = api
692
- return api.frame
693
- else
694
- if num == 1 && @autotab && p['notebook'] == nil
695
- p['notebook'] = Tk::BWidget::NoteBook.new(root_frame){
696
- tabbevelsize 0
697
- internalborderwidth 0
698
- pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
699
- }
700
- api = p['sons'].values[0]
701
- api_tab_frame = p['notebook'].insert('end',
702
- api.name,
703
- 'text'=>api.title,
704
- 'raisecmd'=>proc{
705
- p['root'].title(api.title)
706
- p['root'].top_text('')
707
- changed
708
- notify_observers('RAISE', api.name)
709
- }
710
- )
711
- api.frame.place('in'=>api_tab_frame, 'x'=>0, 'y'=>0, 'relwidth'=>1, 'relheight'=>1)
712
- api.frame.raise
713
- elsif (num==0 && !@autotab)
714
- p['notebook'] = Tk::BWidget::NoteBook.new(root_frame){
715
- tabbevelsize 0
716
- internalborderwidth 0
717
- pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
718
- }
719
- end
720
- _panel = p['notebook'].insert('end',_name ,
721
- 'text'=>_title,
722
- #'background'=>_tab_bg,
723
- 'raisecmd'=>proc{
724
- p['root'].title(_title)
725
- changed
726
- notify_observers('RAISE', _name)
727
- }
728
- )
729
-
730
- # if _tab_bg
731
- # _panel = p['notebook'].insert('end',_name , 'text'=>_title, 'background'=>_tab_bg)
732
- # else
733
- # _panel = p['notebook'].insert('end',_name , 'text'=>_title)
734
- # end
735
- p['sons'][_name] = ArcadiaPanelInfo.new(_name,_title,_panel)
736
- p['notebook'].raise(_name)
737
- return _panel
738
- end
739
- end
740
- end
741
-
742
- def unregister_panel(_domain_name, _name)
743
- @panels[_domain_name]['sons'].delete(_name)
744
- @panels[_domain_name]['notebook'].delete(_name)
745
- new_raise_key = @panels[_domain_name]['sons'].keys[@panels[_domain_name]['sons'].length-1]
746
- @panels[_domain_name]['notebook'].raise(new_raise_key)
747
- end
748
-
749
- def raise_panel(_domain_name, _name)
750
- @panels[_domain_name]['notebook'].raise(_name) if @panels[_domain_name] && @panels[_domain_name]['notebook']
751
- end
752
-
753
- def [](_row, _col)
754
- @frames[_row][_col]
755
- end
756
-
757
- def frame(_domain_name, _name)
758
- @panels[_domain_name]['sons'][_name].frame
759
- end
760
-
761
- def domain(_domain_name)
762
- @panels[_domain_name]
763
- end
764
-
765
- def domain_root_frame(_domain_name)
766
- @panels[_domain_name]['root'].frame
767
- end
768
- end
769
-
770
- Arcadia.new.run
1
+ #
2
+ # arcadia.rb - Arcadia Ruby ide
3
+ # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
+ #
5
+
6
+ Dir.chdir(File.dirname(__FILE__))
7
+ if FileTest.exist?('conf/arcadia.init.rb')
8
+ require 'conf/arcadia.init'
9
+ end
10
+ require "conf/arcadia.res"
11
+ require 'tkextlib/bwidget'
12
+ require "base/a-utils"
13
+ require "base/a-ext"
14
+ require "base/a-contracts"
15
+ require "observer"
16
+
17
+ class Arcadia < TkApplication
18
+ include Observable
19
+ attr_reader :layout
20
+ attr_reader :libs
21
+ #attr_reader :main_contract
22
+ def initialize
23
+ super(
24
+ ApplicationParams.new(
25
+ 'arcadia',
26
+ '0.1.2.1',
27
+ 'conf/arcadia.conf',
28
+ 'conf/arcadia.pers'
29
+ )
30
+ )
31
+ self.load_local_config(false)
32
+ ObjectSpace.define_finalizer($arcadia, self.class.method(:finalize).to_proc)
33
+ publish('action.on_exit', proc{do_exit})
34
+ _title = "Arcadia Ruby ide :: [Platform = "+RUBY_PLATFORM+'] [Ruby version = ' + RUBY_VERSION+']'
35
+ @root = TkRoot.new{
36
+ title _title
37
+ withdraw
38
+ protocol( "WM_DELETE_WINDOW", $arcadia['action.on_exit'])
39
+ }
40
+ @on_event = Hash.new
41
+ @main_menu = TkMenubar.new.pack('fill'=>'x')
42
+ @mf_root = Tk::BWidget::MainFrame.new(@root){
43
+ menu @main_menu
44
+ }.pack(
45
+ 'anchor'=> 'center',
46
+ 'fill'=> 'both',
47
+ 'expand'=> 1
48
+ )
49
+
50
+ #.place('x'=>0,'y'=>0,'relwidth'=>1,'relheight'=>1)
51
+ @mf_root.show_statusbar('none')
52
+ @toolbar = @mf_root.add_toolbar
53
+ @is_toolbar_show=self['conf']['toolbar_show']=='yes'
54
+ @mf_root.show_toolbar(0,@is_toolbar_show)
55
+ @splash = ArcadiaAboutSplash.new('... initialize')
56
+ @splash.set_progress(50)
57
+ @splash.deiconify
58
+ Tk.update
59
+ sleep(1)
60
+ @splash.next_step('..prepare')
61
+ prepare
62
+ @splash.last_step('..load finish')
63
+ geometry = (TkWinfo.screenwidth(@root)-4).to_s+'x'+
64
+ (TkWinfo.screenheight(@root)-20).to_s+'+0+0'
65
+ @root.deiconify
66
+ @root.raise
67
+ @root.focus(true)
68
+ @root.geometry(geometry)
69
+ Tk.update_idletasks
70
+ sleep(1)
71
+ @splash.destroy
72
+ if @first_run
73
+ EditorContract.instance.open_file(self, 'file'=>'README')
74
+ end
75
+ end
76
+
77
+ def show_hide_toolbar
78
+ if @is_toolbar_show
79
+ @mf_root.show_toolbar(0,false)
80
+ @is_toolbar_show = false
81
+ else
82
+ @mf_root.show_toolbar(0,true)
83
+ Tk.update
84
+ @is_toolbar_show = true
85
+ end
86
+
87
+ end
88
+
89
+
90
+ def Arcadia.finalize(id)
91
+ puts "\nArcadia #{id} dying at #{Time.new}"
92
+ end
93
+
94
+ def load_libs
95
+ @libs = ArcadiaLibs.new(self)
96
+ libs = self['conf']['libraries'].split(',')
97
+ libs.each{|lib|
98
+ if lib
99
+ @splash.next_step('... loading library '+lib)
100
+ begin
101
+ require self['conf']['libraries.'+lib+'.source']
102
+ @libs.add_lib(
103
+ ArcadiaLibs::ArcadiaLibParams.new(
104
+ self['conf']['libraries.'+lib+'.name'],
105
+ self['conf']['libraries.'+lib+'.source'],
106
+ self['conf']['libraries.'+lib+'.require'],
107
+ eval(self['conf']['libraries.'+lib+'.collection.class']))
108
+ )
109
+ rescue Exception
110
+ msg = "Loading lib "+'"'+lib+'"'+" ("+$!.class.to_s+") "+" : "+$! + " at : "+$@.to_s
111
+ if Tk.messageBox('icon' => 'error', 'type' => 'okcancel',
112
+ 'title' => '(Arcadia) Libs', 'parent' => @root,
113
+ 'message' => msg) == 'cancel'
114
+ raise
115
+ exit
116
+ else
117
+ Tk.update
118
+ end
119
+ end
120
+ end
121
+ }
122
+ end
123
+
124
+ def load_toolbar_buttons
125
+ suf = 'toolbar_buttons'
126
+ @buttons = Hash.new
127
+ toolbar_buttons = self['conf'][suf].split(',')
128
+ toolbar_buttons.each{|groups|
129
+ if groups
130
+ suf1 = suf+'.'+groups
131
+ @splash.next_step('... loading '+suf1)
132
+ begin
133
+ buttons = self['conf'][suf1].split(',')
134
+ buttons.each{|button|
135
+ suf2 = suf1+'.'+button
136
+ name = self['conf'][suf2+'.name']
137
+ text = self['conf'][suf2+'.text']
138
+ image = self['conf'][suf2+'.image']
139
+ font = self['conf'][suf2+'.font']
140
+ background = self['conf'][suf2+'.background']
141
+ foreground = self['conf'][suf2+'.foreground']
142
+ hint = self['conf'][suf2+'.hint']
143
+ action = self['conf'][suf2+'.action']
144
+ actions = action.split('->') if action
145
+ if actions && actions.length>1
146
+ _command = proc{
147
+ action_obj = $arcadia[actions[0]]
148
+ 1.upto(actions.length-2) do |x|
149
+ action_obj = action_obj.send(actions[x])
150
+ end
151
+ action_obj.send(actions[actions.length-1])
152
+ }
153
+ elsif action
154
+ _command = proc{$arcadia[action].call}
155
+ end
156
+ @buttons[name] = Tk::BWidget::Button.new(@toolbar){
157
+ image TkPhotoImage.new('data' => eval(image)) if image
158
+ borderwidth 1
159
+ font font if font
160
+ background background if background
161
+ foreground foreground if foreground
162
+ command _command if action
163
+ relief 'flat'
164
+ helptext hint if hint
165
+ text text if text
166
+ pack('side' =>'left', :padx=>2, :pady=>2)
167
+ }
168
+ }
169
+ rescue Exception
170
+ msg = 'Loading '+groups+'" -> '+buttons.to_s+ '" (' + $!.class.to_s + ") : " + $!.to_s + " at : "+$@.to_s
171
+ if Tk.messageBox('icon' => 'error', 'type' => 'okcancel',
172
+ 'title' => '(Arcadia) Toolbar', 'parent' => @root,
173
+ 'message' => msg) == 'cancel'
174
+ raise
175
+ exit
176
+ else
177
+ Tk.update
178
+ end
179
+ end
180
+ end
181
+ Tk::BWidget::Separator.new(@toolbar, :orient=>'vertical').pack('side' =>'left', :padx=>2, :pady=>2, :fill=>'y',:anchor=> 'w')
182
+ }
183
+ end
184
+
185
+ def ext_active?(_name)
186
+ return (self['conf'][_name+'.active'] != nil && self['conf'][_name+'.active']=='yes')||
187
+ (self['conf'][_name+'.active'] == nil)
188
+ end
189
+
190
+ def load_exts_conf
191
+ @exts = Array.new
192
+ dirs = Array.new
193
+ files = Dir['ext/*'].concat(Dir[ENV["HOME"]+'/.arcadia/ext/*'])
194
+ files.each{|f|
195
+ dirs << f if File.stat(f).directory? && FileTest.exist?(f+'/'+File.basename(f)+'.conf')
196
+ }
197
+ dirs.each{|ext_dir|
198
+ conf_hash = self.config_file2hash(ext_dir+'/'+File.basename(ext_dir)+'.conf')
199
+ conf_hash2 = Hash.new
200
+ name = conf_hash['name']
201
+ conf_hash.each{|key, value|
202
+ var_plat = key.split(':')
203
+ if var_plat.length > 1
204
+ new_key = var_plat[0] + ':' + name + '.' + var_plat[1]
205
+ else
206
+ new_key = name+'.'+key
207
+ end
208
+ conf_hash2[new_key]= value
209
+ }
210
+ @exts << name
211
+ self['conf'].update(conf_hash2)
212
+ }
213
+ end
214
+
215
+ def load_exts
216
+
217
+ # create extensions
218
+ @exts.each{|extension|
219
+ if extension && ext_active?(extension)
220
+ @splash.next_step('... creating '+extension)
221
+ ext_create(extension)
222
+ end
223
+ }
224
+
225
+ # before_build extensions
226
+ @exts.each{|extension|
227
+ if extension && ext_active?(extension)
228
+ @splash.next_step('... before building '+extension)
229
+ ext_method(extension, :before_build)
230
+ MainContract.instance.extension_before_build(self, 'obj'=>self[extension])
231
+ end
232
+ }
233
+
234
+ # build extensions
235
+ @exts.each{|extension|
236
+ if extension && ext_active?(extension)
237
+ @splash.next_step('... building '+extension)
238
+ ext_method(extension, :build)
239
+ MainContract.instance.extension_build(self, 'obj'=>self[extension])
240
+ end
241
+ }
242
+
243
+ # after build extensions
244
+ @exts.each{|extension|
245
+ if extension && ext_active?(extension)
246
+ @splash.next_step('... after building '+extension)
247
+ ext_method(extension, :after_build)
248
+ MainContract.instance.extension_after_build(self, 'obj'=>self[extension])
249
+ end
250
+ }
251
+
252
+ end
253
+
254
+ def ext_create(_extension)
255
+ begin
256
+ source = self['conf'][_extension+'.require']
257
+ class_name = self['conf'][_extension+'.class']
258
+ if source.strip.length > 0
259
+ #p source
260
+ eval('require ' + "'" + source + "'")
261
+ end
262
+ if class_name.strip.length > 0
263
+ publish(_extension, eval(class_name).new(self, _extension))
264
+ end
265
+ rescue Exception
266
+ raise
267
+ msg = "Loading "+'"'+extension+'"'+" ("+$!.class.to_s+") "+" : "+$! + " at : "+$@.to_s
268
+ ans = Tk.messageBox('icon' => 'error', 'type' => 'abortretryignore',
269
+ 'title' => '(Arcadia) Extensions', 'parent' => @root,
270
+ 'message' => msg)
271
+ if ans == 'abort'
272
+ raise
273
+ exit
274
+ elsif ans == 'retry'
275
+ retry
276
+ else
277
+ Tk.update
278
+ end
279
+ end
280
+ end
281
+
282
+ def ext_method(_extension, _method)
283
+ begin
284
+ self[_extension].send(_method)
285
+ rescue Exception
286
+ msg = _method.to_s+' "'+_extension.to_s+'"'+" ("+$!.class.to_s+") "+" : "+$! + "\n at : "+$@.to_s
287
+ ans = Tk.messageBox('icon' => 'warning', 'type' => 'abortretryignore',
288
+ 'title' => '(Arcadia) Extensions', 'parent' => @root,
289
+ 'message' => msg)
290
+ if ans == 'abort'
291
+ raise
292
+ exit
293
+ elsif ans == 'retry'
294
+ retry
295
+ else
296
+ Tk.update
297
+ end
298
+ end
299
+ end
300
+
301
+
302
+ def prepare
303
+ super
304
+ @splash.next_step('...initialize')
305
+ @layout = ArcadiaLayout.new(self, @mf_root.get_frame)
306
+
307
+ @layout.add_cols(0,0,225)
308
+ @layout.add_rows(0,0,180)
309
+ # @layout.add_rows(0,1,500)
310
+ @layout.add_rows_perc(0,1,70)
311
+
312
+
313
+ @layout.add_headers
314
+ @splash.next_step
315
+ self.load_libs
316
+ @splash.next_step
317
+ @splash.next_step('... load extensions')
318
+ self.load_exts_conf
319
+ self.load_local_config
320
+ self.load_exts
321
+ publish('buffers.code.in_memory',Hash.new)
322
+ publish('action.load_code_from_buffers', proc{TkBuffersChoise.new})
323
+ publish('output.action.run_last', proc{$arcadia['output'].run_last})
324
+ publish('main.action.open_file', proc{self['editor'].open_file(Tk.getOpenFile)})
325
+ @splash.next_step('... load obj controller')
326
+ @splash.next_step('... load editor')
327
+ publish('main.action.new_file',proc{$arcadia['editor'].open_buffer()})
328
+ publish('main.action.edit_cut',proc{$arcadia['editor'].raised.text.text_cut()})
329
+ publish('main.action.edit_copy',proc{$arcadia['editor'].raised.text.text_copy()})
330
+ publish('main.action.edit_paste',proc{$arcadia['editor'].raised.text.text_paste()})
331
+ @splash.next_step('... load actions')
332
+ publish('action.test.keys', proc{KetTest.new})
333
+ publish('action.get.font', proc{Tk::BWidget::SelectFont::Dialog.new.create})
334
+ @splash.next_step
335
+ publish('action.show_about', proc{ArcadiaAboutSplash.new.deiconify})
336
+ # publish('main.menu', @main_menu)
337
+ publish('main.menu', AMainMenu.new(@main_menu))
338
+ @splash.next_step
339
+ publish('objic.action.raise_active_obj',
340
+ proc{
341
+ InspectorContract.instance.raise_active_toplevel(self)
342
+ }
343
+ )
344
+ load_toolbar_buttons
345
+ end
346
+
347
+ def do_exit
348
+ q1 = (Tk.messageBox('icon' => 'question', 'type' => 'yesno',
349
+ 'title' => '(Arcadia) Exit', 'parent' => @root,
350
+ 'message' => "Do you want exit?")=='yes')
351
+ if q1 && can_exit?
352
+ do_finalize
353
+ @root.destroy
354
+ end
355
+ end
356
+
357
+ def can_exit?
358
+ _can_exit = true
359
+ @exts.each{|extension|
360
+ if ext_active?(extension) && !self[extension].can_exit_query
361
+ _can_exit = false
362
+ break
363
+ end
364
+ }
365
+ return _can_exit
366
+ end
367
+
368
+ def do_finalize
369
+ @exts.each{|extension|
370
+ self[extension].finalize if ext_active?(extension)
371
+ }
372
+ self.write_persist
373
+ end
374
+ end
375
+
376
+
377
+ class AMainMenu < TkMenubar
378
+
379
+ def initialize(menu)
380
+ # create main menu
381
+ @menu = menu
382
+ build
383
+ menu.foreground('grey40')
384
+ menu.activeforeground('red')
385
+ menu.relief('groove')
386
+ menu.borderwidth(0)
387
+ menu.font($arcadia['conf']['main.mainmenu.font'])
388
+ end
389
+
390
+ def build
391
+ menu_spec_file = [
392
+ ['File', 0],
393
+ ['Open', $arcadia['main.action.open_file'], 0],
394
+ ['New', $arcadia['main.action.new_file'], 0],
395
+ ['Save', proc{EditorContract.instance.save_file_raised(self)},0],
396
+ ['Save as ...', proc{EditorContract.instance.save_as_file_raised(self)},0],
397
+ '---',
398
+ ['Quit', $arcadia['action.on_exit'], 0]]
399
+ menu_spec_edit = [['Edit', 0],
400
+ ['Cut', $arcadia['main.action.edit_cut'], 2],
401
+ ['Copy', $arcadia['main.action.edit_copy'], 0],
402
+ ['Paste', $arcadia['main.action.edit_paste'], 0]]
403
+ menu_spec_search = [['Search', 0],
404
+ ['Find ...', proc{EditorContract.instance.show_search_dialog(self)}, 2],
405
+ ['Go to line ...', proc{EditorContract.instance.show_goto_line_dialog(self)}, 2]]
406
+ menu_spec_view = [['View', 0],['Show/Hide Toolbar', proc{$arcadia.show_hide_toolbar}, 2]]
407
+ menu_spec_tools = [['Utils', 0],
408
+ ['Keys-test', $arcadia['action.test.keys'], 2],
409
+ ['Load code from buffer', $arcadia['action.load_code_from_buffers'], 2]
410
+ ]
411
+ menu_spec_help = [['Help', 0],
412
+ ['About', $arcadia['action.show_about'], 2],]
413
+ @menu.add_menu(menu_spec_file)
414
+ @menu.add_menu(menu_spec_edit)
415
+ @menu.add_menu(menu_spec_search)
416
+ @menu.add_menu(menu_spec_view)
417
+ @menu.add_menu(menu_spec_tools)
418
+ @menu.add_menu(menu_spec_help)
419
+ end
420
+
421
+ end
422
+
423
+
424
+ class ArcadiaAboutSplash < TkToplevel
425
+ attr :progress
426
+
427
+ def initialize(_txt=nil)
428
+ #_bgcolor = '#B83333'
429
+ _bgcolor = '#000000'
430
+ super()
431
+ relief 'flat'
432
+ background _bgcolor
433
+ highlightbackground _bgcolor
434
+ highlightthickness 6
435
+ borderwidth 1
436
+ withdraw
437
+ overrideredirect(true)
438
+
439
+ @tkLabel3 = TkLabel.new(self){
440
+ image TkPhotoImage.new('format'=>'GIF','data' =>A_LOGO_GIF)
441
+ background _bgcolor
442
+ place('x'=> 20,'y' => 20)
443
+ }
444
+ @tkLabel1 = TkLabel.new(self){
445
+ text 'Arcadia'
446
+ background _bgcolor
447
+ foreground '#ffffff'
448
+ font Arcadia.instance['conf']['splash.title.font']
449
+ justify 'left'
450
+ place('width' => '190','x' => 120,'y' => 10,'height' => 25)
451
+ }
452
+ @tkLabelRuby = TkLabel.new(self){
453
+ image TkPhotoImage.new('data' =>RUBY_DOCUMENT_GIF)
454
+ background _bgcolor
455
+ place('x'=> 150,'y' => 40)
456
+ }
457
+ @tkLabel2 = TkLabel.new(self){
458
+ text 'Ruby ide'
459
+ background _bgcolor
460
+ foreground '#ffffff'
461
+ font Arcadia.instance['conf']['splash.subtitle.font']
462
+ justify 'left'
463
+ place('width' => '90','x' => 170,'y' => 40,'height' => 19)
464
+ }
465
+ @tkLabelVersion = TkLabel.new(self){
466
+ text 'version: '+$arcadia['applicationParams'].version
467
+ background _bgcolor
468
+ foreground '#ffffff'
469
+ font Arcadia.instance['conf']['splash.version.font']
470
+ justify 'left'
471
+ place('width' => '100','x' => 150,'y' => 60,'height' => 19)
472
+ }
473
+ @tkLabelStep = TkLabel.new(self){
474
+ text _txt
475
+ background _bgcolor
476
+ foreground 'yellow'
477
+ font Arcadia.instance['conf']['splash.banner.font']
478
+ justify 'left'
479
+ anchor 'w'
480
+ place('width'=>-5,'relwidth' => 1,'x' => 5,'y' => 175,'height' => 19)
481
+ }
482
+ @tkLabel21 = TkLabel.new(self){
483
+ text 'by Antonio Galeone - 2007'
484
+ background _bgcolor
485
+ foreground '#ffffff'
486
+ font Arcadia.instance['conf']['splash.credits.font']
487
+ justify 'left'
488
+ place('width' => '190','x' => 130,'y' => 146,'height' => 19)
489
+ }
490
+ @progress = TkVariable.new
491
+ reset
492
+ _width = 340
493
+ _height = 210
494
+ #_width = 0;_height = 0
495
+ _x = TkWinfo.screenwidth(self)/2 - _width / 2
496
+ _y = TkWinfo.screenheight(self)/2 - _height / 2
497
+ geometry = _width.to_s+'x'+_height.to_s+'+'+_x.to_s+'+'+_y.to_s
498
+ Tk.tk_call('wm', 'geometry', self, geometry )
499
+ bind("Double-Button-1", proc{self.destroy})
500
+ end
501
+
502
+ def set_progress(_max=10)
503
+ @max = _max
504
+ Tk::BWidget::ProgressBar.new(self, :width=>150, :height=>10,
505
+ :background=>'black',
506
+ :foreground=>'yellow',
507
+ :variable=>@progress,
508
+ :borderwidth=>0,
509
+ :relief=>'flat',
510
+ :maximum=>_max).place('width' => '150','x' => 145,'y' => 95,'height' => 15)
511
+ end
512
+
513
+ def reset
514
+ @progress.value = -1
515
+ end
516
+
517
+ def next_step(_txt = nil)
518
+ @progress.numeric += 1
519
+ labelStep(_txt) if _txt
520
+ end
521
+
522
+ def labelStep(_txt)
523
+ @tkLabelStep.text = _txt
524
+ Tk.update
525
+ end
526
+
527
+ def last_step(_txt = nil)
528
+ @progress.numeric = @max
529
+ labelStep(_txt) if _txt
530
+ end
531
+
532
+ end
533
+
534
+ class TkBuffersChoiseView < TkToplevel
535
+
536
+ def initialize
537
+ super
538
+ Tk.tk_call('wm', 'title', self, '...hello' )
539
+ Tk.tk_call('wm', 'geometry', self, '150x217+339+198' )
540
+ @lb = TkListbox.new(self){
541
+ background '#fedbd7'
542
+ relief 'groove'
543
+ place('relwidth' => '1','relx' => 0,'x' => '0','y' => '0','relheight' => '1','rely' => 0,'height' => '0','bordermode' => 'inside','width' => '0')
544
+ }
545
+ end
546
+
547
+ end
548
+
549
+ class TkBuffersChoise < TkBuffersChoiseView
550
+
551
+ def initialize
552
+ super
553
+ @lb.value= $arcadia['buffers.code.in_memory'].keys
554
+ @lb.bind("Double-ButtonPress-1",proc{
555
+ _sel = @lb.get('active')
556
+ Revparsel.new($arcadia['buffers.code.in_memory'][_sel])
557
+ @lb.delete('active')
558
+ $arcadia['buffers.code.in_memory'].delete(_sel)
559
+ destroy
560
+ })
561
+ raise
562
+ end
563
+
564
+ end
565
+
566
+ class ArcadiaLayout
567
+ include Observable
568
+ ArcadiaPanelInfo = Struct.new( "ArcadiaPanelInfo",
569
+ :name,
570
+ :title,
571
+ :frame
572
+ )
573
+
574
+ def initialize(_arcadia, _frame, _autotab=true)
575
+ @arcadia = _arcadia
576
+ @frames = Array.new
577
+ @frames[0] = Array.new
578
+ @frames[0][0] = _frame
579
+ @domains = Array.new
580
+ @domains[0] = Array.new
581
+ @domains[0][0] = '_domain_root_'
582
+ @panels = Hash.new
583
+ @panels['_domain_root_']= Hash.new
584
+ @panels['_domain_root_']['root']= _frame
585
+ @panels['_domain_root_']['sons'] = Hash.new
586
+ @autotab = _autotab
587
+ @headed = false
588
+ ArcadiaContractListener.new(self, MainContract, :do_main_event)
589
+ end
590
+ def root
591
+ @panels['_domain_root_']['root']
592
+ end
593
+ def do_main_event(_event)
594
+ case _event.signature
595
+ when MainContract::RAISE_EXTENSION
596
+ p = @panels[_event.context.domain]
597
+ if p && p['notebook'] != nil && _event.channel == '0'
598
+ p['notebook'].raise(_event.context.extension)
599
+ end
600
+ end
601
+ end
602
+
603
+ def _prepare_rows(_row,_col, _height, _perc=false, _top_name=nil, _bottom_name=nil)
604
+ if (@frames[_row][_col] != nil)
605
+ _h = AGTkOSplittedFrames.new(@frames[_row][_col],_height, _perc)
606
+ if @frames[_row + 1] == nil
607
+ @frames[_row + 1] = Array.new
608
+ @domains[_row + 1] = Array.new
609
+ end
610
+ @frames[_row][_col] = _h.top_frame
611
+ @frames[_row + 1][_col] = _h.bottom_frame
612
+
613
+ _top_name = _row.to_s+'.'+_col.to_s if _top_name == nil
614
+ @panels[_top_name] = Hash.new
615
+ @panels[_top_name]['root'] = @frames[_row][_col]
616
+ @panels[_top_name]['sons'] = Hash.new
617
+ @domains[_row][_col] = _top_name
618
+
619
+ _bottom_name = (_row+1).to_s+'.'+_col.to_s if _bottom_name == nil
620
+ @panels[_bottom_name] = Hash.new
621
+ @panels[_bottom_name]['root'] = @frames[_row + 1][_col]
622
+ @panels[_bottom_name]['sons'] = Hash.new
623
+ @domains[_row + 1][_col] = _bottom_name
624
+ end
625
+ end
626
+ private :_prepare_rows
627
+
628
+ def add_rows(_row,_col, _height, _top_name=nil, _bottom_name=nil)
629
+ _prepare_rows(_row,_col, _height, false, _top_name, _bottom_name)
630
+ end
631
+
632
+ def add_rows_perc(_row,_col, _height, _top_name=nil, _bottom_name=nil)
633
+ _prepare_rows(_row,_col, _height, true, _top_name, _bottom_name)
634
+ end
635
+
636
+
637
+ def add_cols(_row,_col, _width, _left_name=nil, _right_name=nil)
638
+ if (@frames[_row][_col] != nil)
639
+ _w = AGTkVSplittedFrames.new(@frames[_row][_col],_width)
640
+ @frames[_row][_col] = _w.left_frame
641
+ @frames[_row][_col + 1] = _w.right_frame
642
+
643
+ _left_name = _row.to_s+'.'+_col.to_s if _left_name == nil
644
+ @panels[_left_name] = Hash.new
645
+ @panels[_left_name]['root'] = @frames[_row][_col]
646
+ @panels[_left_name]['sons'] = Hash.new
647
+ @domains[_row][_col] = _left_name
648
+
649
+ _right_name = _row.to_s+'.'+(_col+1).to_s if _right_name == nil
650
+ @panels[_right_name] = Hash.new
651
+ @panels[_right_name]['root'] = @frames[_row][_col + 1]
652
+ @panels[_right_name]['sons'] = Hash.new
653
+ @domains[_row][_col + 1] = _right_name
654
+ end
655
+ end
656
+
657
+ def add_headers
658
+ @domains.each{|row|
659
+ row.each{|domain|
660
+ @panels[domain]['root']= TkTitledFrame.new(@panels[domain]['root'], '...').place('x'=>0, 'y'=>0,'relheight'=>1, 'relwidth'=>1) if @panels[domain]
661
+ }
662
+ }
663
+ @headed = true
664
+ end
665
+
666
+ def headed?
667
+ @headed
668
+ end
669
+
670
+ def autotab?
671
+ @autotab
672
+ end
673
+
674
+ def registed?(_domain_name, _name)
675
+ @panels[_domain_name]['sons'][_name] != nil
676
+ end
677
+
678
+ def register_panel(_domain_name, _name, _title)
679
+ p = @panels[_domain_name]
680
+ if p!=nil
681
+ num = p['sons'].length
682
+ if @headed
683
+ p['root'].title(_title)
684
+ root_frame = p['root'].frame
685
+ else
686
+ root_frame = p['root']
687
+ end
688
+ if (num == 0 && @autotab)
689
+ api = ArcadiaPanelInfo.new(_name,_title,nil)
690
+ api.frame = TkFrame.new(root_frame).place('x'=>0, 'y'=>0, 'relwidth'=>1, 'relheight'=>1)
691
+ p['sons'][_name] = api
692
+ return api.frame
693
+ else
694
+ if num == 1 && @autotab && p['notebook'] == nil
695
+ p['notebook'] = Tk::BWidget::NoteBook.new(root_frame){
696
+ tabbevelsize 0
697
+ internalborderwidth 0
698
+ pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
699
+ }
700
+ api = p['sons'].values[0]
701
+ api_tab_frame = p['notebook'].insert('end',
702
+ api.name,
703
+ 'text'=>api.title,
704
+ 'raisecmd'=>proc{
705
+ p['root'].title(api.title)
706
+ p['root'].top_text('')
707
+ changed
708
+ notify_observers('RAISE', api.name)
709
+ }
710
+ )
711
+ api.frame.place('in'=>api_tab_frame, 'x'=>0, 'y'=>0, 'relwidth'=>1, 'relheight'=>1)
712
+ api.frame.raise
713
+ elsif (num==0 && !@autotab)
714
+ p['notebook'] = Tk::BWidget::NoteBook.new(root_frame){
715
+ tabbevelsize 0
716
+ internalborderwidth 0
717
+ pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
718
+ }
719
+ end
720
+ _panel = p['notebook'].insert('end',_name ,
721
+ 'text'=>_title,
722
+ #'background'=>_tab_bg,
723
+ 'raisecmd'=>proc{
724
+ p['root'].title(_title)
725
+ changed
726
+ notify_observers('RAISE', _name)
727
+ }
728
+ )
729
+
730
+ # if _tab_bg
731
+ # _panel = p['notebook'].insert('end',_name , 'text'=>_title, 'background'=>_tab_bg)
732
+ # else
733
+ # _panel = p['notebook'].insert('end',_name , 'text'=>_title)
734
+ # end
735
+ p['sons'][_name] = ArcadiaPanelInfo.new(_name,_title,_panel)
736
+ p['notebook'].raise(_name)
737
+ return _panel
738
+ end
739
+ end
740
+ end
741
+
742
+ def unregister_panel(_domain_name, _name)
743
+ @panels[_domain_name]['sons'].delete(_name)
744
+ @panels[_domain_name]['notebook'].delete(_name)
745
+ new_raise_key = @panels[_domain_name]['sons'].keys[@panels[_domain_name]['sons'].length-1]
746
+ @panels[_domain_name]['notebook'].raise(new_raise_key)
747
+ end
748
+
749
+ def raise_panel(_domain_name, _name)
750
+ @panels[_domain_name]['notebook'].raise(_name) if @panels[_domain_name] && @panels[_domain_name]['notebook']
751
+ end
752
+
753
+ def [](_row, _col)
754
+ @frames[_row][_col]
755
+ end
756
+
757
+ def frame(_domain_name, _name)
758
+ @panels[_domain_name]['sons'][_name].frame
759
+ end
760
+
761
+ def domain(_domain_name)
762
+ @panels[_domain_name]
763
+ end
764
+
765
+ def domain_root_frame(_domain_name)
766
+ @panels[_domain_name]['root'].frame
767
+ end
768
+ end
769
+
770
+ Arcadia.new.run