canis 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES +52 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +24 -0
  7. data/Rakefile +2 -0
  8. data/canis.gemspec +25 -0
  9. data/examples/alpmenu.rb +46 -0
  10. data/examples/app.sample +19 -0
  11. data/examples/appemail.rb +191 -0
  12. data/examples/atree.rb +105 -0
  13. data/examples/bline.rb +181 -0
  14. data/examples/common/devel.rb +319 -0
  15. data/examples/common/file.rb +93 -0
  16. data/examples/data/README.markdown +9 -0
  17. data/examples/data/brew.txt +38 -0
  18. data/examples/data/color.2 +37 -0
  19. data/examples/data/gemlist.txt +59 -0
  20. data/examples/data/lotr.txt +12 -0
  21. data/examples/data/ports.txt +136 -0
  22. data/examples/data/table.txt +37 -0
  23. data/examples/data/tasks.csv +88 -0
  24. data/examples/data/tasks.txt +27 -0
  25. data/examples/data/todo.txt +16 -0
  26. data/examples/data/todocsv.csv +28 -0
  27. data/examples/data/unix1.txt +21 -0
  28. data/examples/data/unix2.txt +11 -0
  29. data/examples/dbdemo.rb +506 -0
  30. data/examples/dirtree.rb +177 -0
  31. data/examples/newtabbedwindow.rb +100 -0
  32. data/examples/newtesttabp.rb +92 -0
  33. data/examples/tabular.rb +212 -0
  34. data/examples/tasks.rb +179 -0
  35. data/examples/term2.rb +88 -0
  36. data/examples/testbuttons.rb +307 -0
  37. data/examples/testcombo.rb +102 -0
  38. data/examples/testdb.rb +182 -0
  39. data/examples/testfields.rb +208 -0
  40. data/examples/testflowlayout.rb +43 -0
  41. data/examples/testkeypress.rb +98 -0
  42. data/examples/testlistbox.rb +187 -0
  43. data/examples/testlistbox1.rb +199 -0
  44. data/examples/testmessagebox.rb +144 -0
  45. data/examples/testprogress.rb +116 -0
  46. data/examples/testree.rb +107 -0
  47. data/examples/testsplitlayout.rb +53 -0
  48. data/examples/testsplitlayout1.rb +49 -0
  49. data/examples/teststacklayout.rb +48 -0
  50. data/examples/testwsshortcuts.rb +68 -0
  51. data/examples/testwsshortcuts2.rb +129 -0
  52. data/lib/canis.rb +16 -0
  53. data/lib/canis/core/docs/index.txt +104 -0
  54. data/lib/canis/core/docs/list.txt +16 -0
  55. data/lib/canis/core/docs/style_help.yml +34 -0
  56. data/lib/canis/core/docs/tabbedpane.txt +15 -0
  57. data/lib/canis/core/docs/table.txt +31 -0
  58. data/lib/canis/core/docs/textpad.txt +48 -0
  59. data/lib/canis/core/docs/tree.txt +23 -0
  60. data/lib/canis/core/include/.DS_Store +0 -0
  61. data/lib/canis/core/include/action.rb +83 -0
  62. data/lib/canis/core/include/actionmanager.rb +49 -0
  63. data/lib/canis/core/include/appmethods.rb +179 -0
  64. data/lib/canis/core/include/bordertitle.rb +49 -0
  65. data/lib/canis/core/include/canisparser.rb +100 -0
  66. data/lib/canis/core/include/colorparser.rb +437 -0
  67. data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
  68. data/lib/canis/core/include/io.rb +320 -0
  69. data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
  70. data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
  71. data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
  72. data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
  73. data/lib/canis/core/include/listbindings.rb +89 -0
  74. data/lib/canis/core/include/listeditable.rb +319 -0
  75. data/lib/canis/core/include/listoperations.rb +61 -0
  76. data/lib/canis/core/include/listselectionmodel.rb +388 -0
  77. data/lib/canis/core/include/multibuffer.rb +173 -0
  78. data/lib/canis/core/include/ractionevent.rb +73 -0
  79. data/lib/canis/core/include/rchangeevent.rb +27 -0
  80. data/lib/canis/core/include/rhistory.rb +95 -0
  81. data/lib/canis/core/include/rinputdataevent.rb +47 -0
  82. data/lib/canis/core/include/textdocument.rb +111 -0
  83. data/lib/canis/core/include/vieditable.rb +175 -0
  84. data/lib/canis/core/include/widgetmenu.rb +66 -0
  85. data/lib/canis/core/system/colormap.rb +165 -0
  86. data/lib/canis/core/system/keydefs.rb +32 -0
  87. data/lib/canis/core/system/ncurses.rb +237 -0
  88. data/lib/canis/core/system/panel.rb +129 -0
  89. data/lib/canis/core/system/window.rb +1081 -0
  90. data/lib/canis/core/util/ansiparser.rb +119 -0
  91. data/lib/canis/core/util/app.rb +696 -0
  92. data/lib/canis/core/util/basestack.rb +412 -0
  93. data/lib/canis/core/util/defaultcolorparser.rb +84 -0
  94. data/lib/canis/core/util/extras/README +5 -0
  95. data/lib/canis/core/util/extras/bottomline.rb +1815 -0
  96. data/lib/canis/core/util/extras/padreader.rb +192 -0
  97. data/lib/canis/core/util/focusmanager.rb +31 -0
  98. data/lib/canis/core/util/helpmanager.rb +160 -0
  99. data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
  100. data/lib/canis/core/util/promptmenu.rb +235 -0
  101. data/lib/canis/core/util/rcommandwindow.rb +933 -0
  102. data/lib/canis/core/util/rdialogs.rb +520 -0
  103. data/lib/canis/core/util/textutils.rb +74 -0
  104. data/lib/canis/core/util/viewer.rb +238 -0
  105. data/lib/canis/core/util/widgetshortcuts.rb +508 -0
  106. data/lib/canis/core/widgets/applicationheader.rb +103 -0
  107. data/lib/canis/core/widgets/box.rb +58 -0
  108. data/lib/canis/core/widgets/divider.rb +310 -0
  109. data/lib/canis/core/widgets/extras/README.md +12 -0
  110. data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
  111. data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
  112. data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
  113. data/lib/canis/core/widgets/listbox.rb +326 -0
  114. data/lib/canis/core/widgets/listfooter.rb +86 -0
  115. data/lib/canis/core/widgets/rcombo.rb +210 -0
  116. data/lib/canis/core/widgets/rcontainer.rb +415 -0
  117. data/lib/canis/core/widgets/rlink.rb +30 -0
  118. data/lib/canis/core/widgets/rmenu.rb +970 -0
  119. data/lib/canis/core/widgets/rmenulink.rb +30 -0
  120. data/lib/canis/core/widgets/rmessagebox.rb +400 -0
  121. data/lib/canis/core/widgets/rprogress.rb +118 -0
  122. data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
  123. data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
  124. data/lib/canis/core/widgets/rwidget.rb +3634 -0
  125. data/lib/canis/core/widgets/scrollbar.rb +147 -0
  126. data/lib/canis/core/widgets/statusline.rb +113 -0
  127. data/lib/canis/core/widgets/table.rb +1072 -0
  128. data/lib/canis/core/widgets/tabular.rb +264 -0
  129. data/lib/canis/core/widgets/textpad.rb +1674 -0
  130. data/lib/canis/core/widgets/tree.rb +690 -0
  131. data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
  132. data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
  133. data/lib/canis/version.rb +3 -0
  134. metadata +229 -0
@@ -0,0 +1,320 @@
1
+ #*******************************************************
2
+ # Some common io routines for getting data or putting
3
+ # at some point
4
+ # Current are:
5
+ # * rb_gets - get a string at bottom of screen
6
+ # * get_file
7
+ # * rb_getchar - get a char
8
+ #
9
+ # * Promptmenu creation
10
+ # requires rcommandwindow
11
+ #
12
+ # *
13
+ # * rb_getstr (and those it calls) (old and for backward compat)
14
+ # - rb_getstr is used by vieditable for edit_line and insert_line
15
+ # * display_cmenu and create_mitem
16
+ # Changes:
17
+ # 2011-12-6 : removed many old, outdated methods.
18
+ # 2014-04-25 - 12:36 moved Promptmenu to util/promptmenu.rb
19
+ #*******************************************************#
20
+ require 'pathname'
21
+ module Canis
22
+ module Io
23
+
24
+ # create a 2 line window at bottom to accept user input
25
+ #
26
+ def __create_footer_window h = 2 , w = Ncurses.COLS, t = Ncurses.LINES-2, l = 0
27
+ ewin = Canis::Window.new(h, w , t, l)
28
+ end
29
+ # 2011-11-27 I have replaced the getting of chars with a field
30
+
31
+ # get a string at the bottom of the screen
32
+ #
33
+ # @param [String] prompt - label to show
34
+ # @param [Hash] config - :default, :width of Field, :help_text, :tab_completion
35
+ # help_text is displayed on F1
36
+ # tab_completion is a proc which helps to complete user input
37
+ # @yield [Field] for overriding or customization
38
+ # @return [String, nil] String if entered, nil if canceled
39
+ def rb_gets(prompt, config={}) # yield field
40
+ if config.is_a? Hash
41
+ # okay
42
+ #
43
+ elsif config.is_a? Array
44
+ # an array is supplied, and tabbing helps complete from that
45
+ # array.
46
+ options = config
47
+ completion_proc = Proc.new{|str|
48
+ options.dup.grep Regexp.new("^#{str}");
49
+ }
50
+ config = {}
51
+ config[:tab_completion] = completion_proc
52
+ elsif config == Pathname
53
+ # we need to return a pathname TODO and prepend dirname
54
+ # allow user to specify startdir else take current
55
+ completion_proc = Proc.new {|str| Dir.glob(str +"*").collect { |f| File.directory?(f) ? f+"/" : f } }
56
+ help_text = "Enter start of filename and tab to get completion"
57
+ config = {}
58
+ config[:tab_completion] = completion_proc
59
+ config[:help_text] = help_text
60
+ elsif config == Integer
61
+ config = {}
62
+ config[:datatype] = 1.class
63
+ config[:type] = :integer
64
+ elsif config == Float
65
+ config = {}
66
+ v = 0.11
67
+ config[:datatype] = v.class
68
+ config[:type] = :float
69
+ elsif config == :phone
70
+
71
+ config = {}
72
+ end
73
+ begin
74
+ win = __create_footer_window
75
+ form = Form.new win
76
+ r = 0; c = 1;
77
+ default = config[:default] || ""
78
+ prompt = "#{prompt} [#{default}]:" if default.size > 0
79
+ _max = FFI::NCurses.COLS-1-prompt.size-4
80
+ displen = config[:width] || [config[:maxlen] || 999, _max].min
81
+ maxlen = config[:maxlen] || _max
82
+ field = LabeledField.new form, :row => r, :col => c, :maxlen => maxlen, :default => default, :label => prompt,
83
+ :width => displen
84
+ field.datatype(config[:datatype]) if config[:datatype]
85
+ field.type(config[:type]) if config[:type]
86
+ bg = Ncurses.COLORS >= 236 ? 233 : :blue
87
+ field.bgcolor = bg
88
+ field.cursor_end if default.size > 0
89
+ def field.default=(x); default(x);end
90
+
91
+ # if user wishes to use the yield and say "field.history = [x,y,z] then
92
+ # we should alredy have extended this, so lets make it permanent
93
+ require 'canis/core/include/rhistory'
94
+ field.extend(FieldHistory)
95
+ field.history = config[:history]
96
+
97
+ yield field if block_given?
98
+ form.repaint
99
+ win.wrefresh
100
+ prevchar = 0
101
+ entries = nil
102
+ oldstr = nil # for tab completion, origal word entered by user
103
+ while ((ch = win.getchar()) != 999)
104
+ if ch == 10 || ch == 13 || ch == KEY_ENTER
105
+ begin
106
+ # validate in case ranges or other validation given
107
+ field.on_leave
108
+ break
109
+ rescue FieldValidationException => err # added 2011-10-2 v1.3.1 so we can rollback
110
+ #alert err.to_s
111
+ # unable to use alert now, since closing alert repaints root window and clears the
112
+ # window this was on (command window in numbered menu).
113
+ print_this(win, err.to_s, $errorcolor, 1, 0)
114
+ form.setpos
115
+ rescue => err
116
+ Ncurses.beep
117
+ break
118
+ end
119
+ end
120
+ #return -1, nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
121
+ return nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
122
+ #if ch == ?\M-h.getbyte(0) # HELP KEY
123
+ #help_text = config[:help_text] || "No help provided"
124
+ #color = $datacolor
125
+ #print_help(win, r, c, color, help_text)
126
+ ## this will come over our text
127
+ #end
128
+ # tab completion and help_text print on F1
129
+ # that field objects can extend, same for tab completion and gmail completion
130
+ if ch == KEY_TAB
131
+ if config
132
+ str = field.text
133
+ # tab_completion
134
+ # if previous char was not tab, execute tab_completion_proc and push first entry
135
+ # else push the next entry
136
+ if prevchar == KEY_TAB
137
+ if !entries.nil? && !entries.empty?
138
+ str = entries.delete_at(0)
139
+ else
140
+ str = oldstr if oldstr
141
+ prevchar = ch = nil # so it can start again completing
142
+ end
143
+ else
144
+ tabc = config[:tab_completion] unless tabc
145
+ next unless tabc
146
+ oldstr = str.dup
147
+ entries = tabc.call(str).dup
148
+ $log.debug " tab got #{entries} for str=#{str}"
149
+ str = entries.delete_at(0) unless entries.nil? || entries.empty?
150
+ str = str.to_s.dup
151
+ end
152
+ if str
153
+ field.text = str
154
+ field.cursor_end
155
+ field.set_form_col # shit why are we doign this, text sets curpos to 0
156
+ end
157
+ form.repaint
158
+ win.wrefresh
159
+ end
160
+
161
+ elsif ch == KEY_F1
162
+ help_text = config[:help_text] || "No help provided. C-c/C-g aborts. <TAB> completion. Alt-h history. C-a/e"
163
+ print_status_message help_text, :wait => 7
164
+ else
165
+ form.handle_key ch
166
+ end
167
+ prevchar = ch
168
+ win.wrefresh
169
+ end
170
+ rescue => err
171
+ Ncurses.beep
172
+ textdialog [err.to_s, *err.backtrace], :title => "Exception"
173
+ $log.error "EXC in rb_getstr #{err} "
174
+ $log.error(err.backtrace.join("\n"))
175
+ ensure
176
+ win.destroy if win
177
+ end
178
+ config[:history] << field.text if config[:history] && field.text
179
+ return field.text
180
+ end
181
+
182
+ # get a character.
183
+ # unlike rb_gets allows user to enter control or alt or function character too.
184
+ # @param [String] prompt or label to show.
185
+ # @param [Hash] configuration such as default or regexp for validation
186
+ # @return [Fixnum] nil if canceled, or ret value of getchar which is numeric
187
+ # If default provided, then ENTER returns the default
188
+ def rb_getchar(prompt, config={}) # yield field
189
+ begin
190
+ win = __create_footer_window
191
+ #form = Form.new win
192
+ r = 0; c = 1;
193
+ default = config[:default]
194
+ prompt = "#{prompt} [#{default}] " if default
195
+ win.mvprintw(r, c, "%s: " % prompt);
196
+ bg = Ncurses.COLORS >= 236 ? 236 : :blue
197
+ color_pair = get_color($reversecolor, :white, bg)
198
+ win.printstring r, c + prompt.size + 2, " ", color_pair
199
+
200
+ win.wrefresh
201
+ prevchar = 0
202
+ entries = nil
203
+ while ((ch = win.getchar()) != 999)
204
+ return default.ord if default && (ch == 13 || ch == KEY_ENTER)
205
+ return nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
206
+ if ch == KEY_F1
207
+ help_text = config[:help_text] || "No help provided. C-c/C-g aborts."
208
+ print_status_message help_text, :wait => 7
209
+ win.wrefresh # nevr had to do this with ncurses, but have to with ffi-ncurses ??
210
+ next
211
+ end
212
+ if config[:regexp]
213
+ reg = config[:regexp]
214
+ if ch > 0 && ch < 256
215
+ chs = ch.chr
216
+ return ch if chs =~ reg
217
+ alert "Wrong character. #{reg} "
218
+ else
219
+ alert "Wrong character. #{reg} "
220
+ end
221
+ else
222
+ return ch
223
+ end
224
+ #form.handle_key ch
225
+ win.wrefresh
226
+ end
227
+ rescue => err
228
+ Ncurses.beep
229
+ $log.error "EXC in rb_getstr #{err} "
230
+ $log.error(err.backtrace.join("\n"))
231
+ ensure
232
+ win.destroy if win
233
+ end
234
+ return nil
235
+ end
236
+
237
+ # This is just experimental, trying out tab_completion
238
+ # Prompt user for a file name, allowing him to tab to complete filenames
239
+ # @see #choose_file from rcommandwindow.rb
240
+ # @param [String] label to print before field
241
+ # @param [Fixnum] max length of field
242
+ # @return [String] filename or blank if user cancelled
243
+ def get_file prompt, config={} #:nodoc:
244
+ maxlen = 70
245
+ tabc = Proc.new {|str| Dir.glob(str +"*") }
246
+ config[:tab_completion] ||= tabc
247
+ config[:maxlen] ||= maxlen
248
+ #config[:default] = "test"
249
+ #ret, str = rb_getstr(nil,0,0, prompt, maxlen, config)
250
+ # 2014-04-25 - 12:42 removed call to deprecated method
251
+ str = rb_gets(prompt, config)
252
+ #$log.debug " get_file returned #{ret} , #{str} "
253
+ str ||= ""
254
+ return str
255
+ end
256
+ def clear_this win, r, c, color, len
257
+ print_this(win, "%-*s" % [len," "], color, r, c)
258
+ end
259
+
260
+
261
+
262
+ ##
263
+ # prints given text to window, in color at x and y coordinates
264
+ # @param [Window] window to write to
265
+ # @param [String] text to print
266
+ # @param [int] color pair such as $datacolor or $promptcolor
267
+ # @param [int] x row
268
+ # @param [int] y col
269
+ # @see Window#printstring
270
+ def print_this(win, text, color, x, y)
271
+ raise "win nil in print_this" unless win
272
+ color=Ncurses.COLOR_PAIR(color);
273
+ win.attron(color);
274
+ #win.mvprintw(x, y, "%-40s" % text);
275
+ win.mvprintw(x, y, "%s" % text);
276
+ win.attroff(color);
277
+ win.refresh
278
+ end
279
+
280
+
281
+ #
282
+ # warn user: currently flashes and places error in log file
283
+ # experimental, may change interface later
284
+ # it does not say anything on screen
285
+ # @param [String] text of error/warning to put in log
286
+ # @since 1.1.5
287
+ def warn string
288
+ $log.warn string
289
+ Ncurses.beep
290
+ end
291
+
292
+
293
+ # routine to get a string at bottom of window.
294
+ # The first 3 params are no longer required since we create a window
295
+ # of our own.
296
+ # @param [String] prompt - label to show
297
+ # @param [Fixnum] maxlen - max length of input
298
+ # @param [Hash] config - :default, :width of Field, :help_text, :tab_completion
299
+ # help_text is displayed on F1
300
+ # tab_completion is a proc which helps to complete user input
301
+ # NOTE : This method is now only for **backward compatibility**
302
+ # rb_getstr had various return codes based on whether user asked for help
303
+ # possibly mimicking alpine, or because i could do nothing about it.
304
+ # Now, rb_getstr handles that and only returns if the user cancels or enters
305
+ # a string, so rb_getstr does not need to return other codes.
306
+ # @deprecated
307
+ def rb_getstr(nolongerused, r, c, prompt, maxlen, config={})
308
+ config[:maxlen] = maxlen
309
+ str = rb_gets(prompt, config)
310
+ if str
311
+ return 0, str
312
+ else
313
+ return -1, nil
314
+ end
315
+ end
316
+
317
+
318
+
319
+ end # module
320
+ end # module
@@ -0,0 +1,161 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: SplitLayout.rb
3
+ # Description:
4
+ # Author: j kepler http://github.com/mare-imbrium/canis/
5
+ # Date: 2014-05-10 - 13:48
6
+ # License: MIT
7
+ # Last update: 2014-05-10 20:19
8
+ # ----------------------------------------------------------------------------- #
9
+ # SplitLayout.rb Copyright (C) 2012-2014 j kepler
10
+ # ----
11
+ # This layout allows for complex arrangements of stacks and flows. One can divide the layout
12
+ # into splits (vertical or horizontal) and keep dividing a split, or placing a component in it.
13
+ # However, to keep it simple and reduce the testing, I am insisting that a weightage be specified
14
+ # with a split.
15
+ #
16
+ # layout = SplitLayout.new :height => -1, :top_margin => 1, :bottom_margin => 1, :left_margin => 1
17
+ # x, y = layout.vsplit( 0.30, 0.70)
18
+ # x.component = mylist
19
+ # y1, y2 = y.split( 0.40, 0.60 )
20
+ # y2.component = mytable
21
+ # y11,y12,y13 = y1.vsplit( 0.3, 0.3, 0.4)
22
+ # y11 = list1
23
+ # y12 = list2
24
+ # y13 = list3
25
+ #
26
+ # Or hopefully:
27
+ #
28
+ # layout.split(0.3, 0.7) do |x,y|
29
+ # x.component = mylist
30
+ # y.split(0.4, 0.6) do |a,b|
31
+ # b.component = mytable
32
+ # a.vsplit( 0.3, 0.3, 0.4) do | p,q,r |
33
+ # p.component = list1
34
+ # end
35
+ # end
36
+ # end
37
+ #
38
+ #
39
+ class Split
40
+
41
+ attr_reader :component
42
+ attr_accessor :name
43
+ attr_reader :splits
44
+ attr_accessor :height, :width, :top, :left
45
+ # link to parent
46
+ # own weight
47
+ attr_accessor :parent, :weight
48
+ # weights of child splits, given in cons
49
+ attr_accessor :split_wts
50
+ attr_reader :type
51
+
52
+ def initialize type, weight, parent
53
+ @type = type
54
+ @weight = weight
55
+ @parent = parent
56
+ end
57
+ def _split type, args, &block
58
+ @split_wts = args
59
+ @splits = []
60
+ args.each do |e|
61
+ @splits << Split.new(type, e, self)
62
+ end
63
+ if block_given?
64
+ yield @splits.flatten
65
+ else
66
+ return @splits.flatten
67
+ end
68
+ end
69
+ def split *args, &block
70
+ _split :h, args, &block
71
+ end
72
+ def vsplit *args, &block
73
+ _split :v, args, &block
74
+ end
75
+
76
+ # Set a component into a split.
77
+ # set name of component as name of split, more for debugging
78
+ def component=(c)
79
+ @component = c
80
+ @name = c.name || c.class.to_s
81
+ end
82
+
83
+ # shorthand to place a component in a split.
84
+ alias :<< :component=
85
+ end
86
+
87
+
88
+
89
+ require 'canis/core/include/layouts/abstractlayout'
90
+ class SplitLayout < AbstractLayout
91
+
92
+ # @param [Form] optional give a form
93
+ # @param [Hash] optional give settings/attributes which will be set into variables
94
+ def initialize arg, config={}, &block
95
+ super
96
+ @splits = nil
97
+ end
98
+ def _split type, args, &block
99
+ @splits = []
100
+ @split_wts = args
101
+ args.each do |e|
102
+ @splits << Split.new(type, e, self)
103
+ end
104
+ if block_given?
105
+ yield @splits.flatten
106
+ else
107
+ return @splits.flatten
108
+ end
109
+ end
110
+
111
+ def split *args, &block
112
+ raise "already split " if @splits
113
+ _split :h, args, &block
114
+ end
115
+ def vsplit *args, &block
116
+ raise "already split " if @splits
117
+ $log.debug " SPLIT GOT #{args} "
118
+ _split :v, args, &block
119
+ end
120
+ alias :top :top_margin
121
+ alias :left :left_margin
122
+
123
+
124
+ # This program lays out the widgets deciding their row and columm and height and weight.
125
+ # This program is called once at start of application, and again whenever a RESIZE event happens.
126
+ def do_layout
127
+ _init_layout
128
+ recalc @splits, @top_margin, @left_margin if @splits
129
+ #
130
+ $log.debug " layout finished "
131
+ end
132
+ def recalc splits, r, c
133
+ splits.each_with_index do |s,i|
134
+ $log.debug " recalc #{i}, #{s} "
135
+ p = s.parent
136
+ s.top = r
137
+ s.left = c
138
+ case s.type
139
+ when :v
140
+ s.width = (s.weight * p.width ).floor
141
+ s.height = p.height
142
+ c += s.width
143
+ when :h
144
+ s.height = (s.weight * p.height ).floor
145
+ s.width = p.width
146
+ r += s.height
147
+ end
148
+ if s.component
149
+ s.component.height = s.height
150
+ s.component.row = s.top
151
+ s.component.col = s.left
152
+ s.component.width = s.width
153
+ elsif s.splits
154
+ recalc s.splits, s.top, s.left if s.splits
155
+ else
156
+ raise "Neither splits nor a component placed in #{s} #{s.type}, #{s.weight} #{s.name}"
157
+ end
158
+ end
159
+
160
+ end
161
+ end