arcadia 0.1.0

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