rbhex-core 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/CHANGELOG +2000 -0
  4. data/LICENSE +56 -0
  5. data/README.md +44 -0
  6. data/examples/abasiclist.rb +179 -0
  7. data/examples/alpmenu.rb +50 -0
  8. data/examples/app.sample +19 -0
  9. data/examples/atree.rb +100 -0
  10. data/examples/bline.rb +136 -0
  11. data/examples/common/file.rb +45 -0
  12. data/examples/data/README.markdown +9 -0
  13. data/examples/data/brew.txt +38 -0
  14. data/examples/data/color.2 +37 -0
  15. data/examples/data/gemlist.txt +60 -0
  16. data/examples/data/lotr.txt +12 -0
  17. data/examples/data/ports.txt +136 -0
  18. data/examples/data/table.txt +37 -0
  19. data/examples/data/tasks.csv +88 -0
  20. data/examples/data/tasks.txt +27 -0
  21. data/examples/data/todo.txt +10 -0
  22. data/examples/data/todo.txt.bak +10 -0
  23. data/examples/data/todocsv.csv +28 -0
  24. data/examples/data/unix1.txt +21 -0
  25. data/examples/data/unix2.txt +11 -0
  26. data/examples/dbdemo.rb +502 -0
  27. data/examples/dirtree.rb +94 -0
  28. data/examples/newtabbedwindow.rb +100 -0
  29. data/examples/newtesttabp.rb +92 -0
  30. data/examples/tabular.rb +146 -0
  31. data/examples/tasks.rb +178 -0
  32. data/examples/term2.rb +84 -0
  33. data/examples/testbuttons.rb +296 -0
  34. data/examples/testcombo.rb +102 -0
  35. data/examples/testfields.rb +195 -0
  36. data/examples/testkeypress.rb +72 -0
  37. data/examples/testlistbox.rb +170 -0
  38. data/examples/testmessagebox.rb +140 -0
  39. data/examples/testprogress.rb +116 -0
  40. data/examples/testree.rb +106 -0
  41. data/examples/testwsshortcuts.rb +66 -0
  42. data/examples/testwsshortcuts2.rb +128 -0
  43. data/lib/rbhex.rb +6 -0
  44. data/lib/rbhex/core/docs/index.txt +73 -0
  45. data/lib/rbhex/core/include/action.rb +80 -0
  46. data/lib/rbhex/core/include/actionmanager.rb +49 -0
  47. data/lib/rbhex/core/include/appmethods.rb +214 -0
  48. data/lib/rbhex/core/include/bordertitle.rb +48 -0
  49. data/lib/rbhex/core/include/chunk.rb +203 -0
  50. data/lib/rbhex/core/include/io.rb +553 -0
  51. data/lib/rbhex/core/include/listbindings.rb +74 -0
  52. data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
  53. data/lib/rbhex/core/include/listeditable.rb +317 -0
  54. data/lib/rbhex/core/include/listscrollable.rb +663 -0
  55. data/lib/rbhex/core/include/listselectable.rb +271 -0
  56. data/lib/rbhex/core/include/multibuffer.rb +83 -0
  57. data/lib/rbhex/core/include/orderedhash.rb +77 -0
  58. data/lib/rbhex/core/include/ractionevent.rb +73 -0
  59. data/lib/rbhex/core/include/rchangeevent.rb +27 -0
  60. data/lib/rbhex/core/include/rhistory.rb +95 -0
  61. data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
  62. data/lib/rbhex/core/include/vieditable.rb +172 -0
  63. data/lib/rbhex/core/include/widgetmenu.rb +66 -0
  64. data/lib/rbhex/core/system/colormap.rb +165 -0
  65. data/lib/rbhex/core/system/keyboard.rb +150 -0
  66. data/lib/rbhex/core/system/keydefs.rb +30 -0
  67. data/lib/rbhex/core/system/ncurses.rb +236 -0
  68. data/lib/rbhex/core/system/panel.rb +162 -0
  69. data/lib/rbhex/core/system/window.rb +913 -0
  70. data/lib/rbhex/core/util/ansiparser.rb +119 -0
  71. data/lib/rbhex/core/util/app.rb +1228 -0
  72. data/lib/rbhex/core/util/basestack.rb +410 -0
  73. data/lib/rbhex/core/util/bottomline.rb +1859 -0
  74. data/lib/rbhex/core/util/colorparser.rb +77 -0
  75. data/lib/rbhex/core/util/focusmanager.rb +31 -0
  76. data/lib/rbhex/core/util/padreader.rb +192 -0
  77. data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
  78. data/lib/rbhex/core/util/rdialogs.rb +574 -0
  79. data/lib/rbhex/core/util/viewer.rb +149 -0
  80. data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
  81. data/lib/rbhex/core/version.rb +5 -0
  82. data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
  83. data/lib/rbhex/core/widgets/box.rb +58 -0
  84. data/lib/rbhex/core/widgets/divider.rb +310 -0
  85. data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
  86. data/lib/rbhex/core/widgets/rcombo.rb +253 -0
  87. data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
  88. data/lib/rbhex/core/widgets/rlink.rb +30 -0
  89. data/lib/rbhex/core/widgets/rlist.rb +696 -0
  90. data/lib/rbhex/core/widgets/rmenu.rb +958 -0
  91. data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
  92. data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
  93. data/lib/rbhex/core/widgets/rprogress.rb +118 -0
  94. data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
  95. data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
  96. data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
  97. data/lib/rbhex/core/widgets/rtextview.rb +739 -0
  98. data/lib/rbhex/core/widgets/rtree.rb +768 -0
  99. data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
  100. data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
  101. data/lib/rbhex/core/widgets/statusline.rb +113 -0
  102. data/lib/rbhex/core/widgets/tabular.rb +264 -0
  103. data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
  104. data/lib/rbhex/core/widgets/textpad.rb +995 -0
  105. data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
  106. data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
  107. data/rbhex-core.gemspec +32 -0
  108. metadata +172 -0
@@ -0,0 +1,149 @@
1
+ require 'rbhex/core/widgets/rtextview'
2
+ require 'fileutils'
3
+
4
+ # NOTE: experimental, not yet firmed up
5
+ # If you use in application, please copy to some application folder in case i change this.
6
+ # Can be used for print_help_page
7
+ # TODO: add vi_keys here
8
+ # SUGGESTIONS WELCOME.
9
+ # @since 1.2.0
10
+ module RubyCurses
11
+ # a data viewer for viewing some text or filecontents
12
+ # view filename, :close_key => KEY_ENTER
13
+ # send data in an array
14
+ # view Array, :close_key => KEY_ENTER, :layout => [0,0,23,80]
15
+ # when passing layout reserve 4 rows for window and border. So for 2 lines of text
16
+ # give 6 rows.
17
+ class Viewer
18
+ # @param filename as string or content as array
19
+ # @yield textview object for further configuration before display
20
+ # NOTE: i am experimentally yielding textview object so i could supress borders
21
+ # just for kicks, but on can also bind_keys or events if one wanted.
22
+ def self.view what, config={} #:yield: textview
23
+ case what
24
+ when String # we have a path
25
+ content = _get_contents(what)
26
+ when Array
27
+ content = what
28
+ else
29
+ raise ArgumentError, "Viewer: Expecting Filename or Contents (array), but got #{what.class} "
30
+ end
31
+ wt = 0 # top margin
32
+ wl = 0 # left margin
33
+ wh = Ncurses.LINES-wt # height, goes to bottom of screen
34
+ ww = Ncurses.COLS-wl # width, goes to right end
35
+ wt, wl, wh, ww = config[:layout] if config.has_key? :layout
36
+
37
+ fp = config[:title] || ""
38
+ pf = config.fetch(:print_footer, true)
39
+ ta = config.fetch(:title_attrib, 'bold')
40
+ fa = config.fetch(:footer_attrib, 'bold')
41
+ type = config[:content_type]
42
+
43
+ layout = { :height => wh, :width => ww, :top => wt, :left => wl }
44
+ v_window = VER::Window.new(layout)
45
+ v_form = RubyCurses::Form.new v_window
46
+ colors = Ncurses.COLORS
47
+ back = :blue
48
+ back = 235 if colors >= 256
49
+ blue_white = get_color($datacolor, :white, back)
50
+ #blue_white = RubyCurses::Utils.get_color($datacolor, :white, 235)
51
+ textview = TextView.new v_form do
52
+ name "Viewer"
53
+ row 0
54
+ col 0
55
+ width ww
56
+ height wh-0 # earlier 2 but seems to be leaving space.
57
+ title fp
58
+ title_attrib ta
59
+ print_footer pf
60
+ footer_attrib fa
61
+ #border_attrib :reverse
62
+ border_color blue_white
63
+ end
64
+ require 'rbhex/core/include/multibuffer'
65
+ textview.extend(RubyCurses::MultiBuffers)
66
+
67
+ t = textview
68
+ t.bind_key('<', 'move window left'){ f = t.form.window; c = f.left - 1; f.hide; f.mvwin(f.top, c); f.show;
69
+ f.reset_layout([f.height, f.width, f.top, c]);
70
+ }
71
+ t.bind_key('>', 'move window right'){ f = t.form.window; c = f.left + 1; f.hide; f.mvwin(f.top, c);
72
+ f.reset_layout([f.height, f.width, f.top, c]); f.show;
73
+ }
74
+ t.bind_key('^', 'move window up'){ f = t.form.window; c = f.top - 1 ; f.hide; f.mvwin(c, f.left);
75
+ f.reset_layout([f.height, f.width, c, f.left]) ; f.show;
76
+ }
77
+ t.bind_key('V', 'move window down'){ f = t.form.window; c = f.top + 1 ; f.hide; f.mvwin(c, f.left);
78
+ f.reset_layout([f.height, f.width, c, f.left]); f.show;
79
+ }
80
+ # yielding textview so you may further configure or bind keys or events
81
+ begin
82
+ textview.set_content content, :content_type => type
83
+ textview.add_content content, :content_type => type
84
+ # the next can also be used to use formatted_text(text, :ansi)
85
+ yield textview if block_given?
86
+ v_form.repaint
87
+ v_window.wrefresh
88
+ Ncurses::Panel.update_panels
89
+ # allow closing using q and Ctrl-q in addition to any key specified
90
+ # user should not need to specify key, since that becomes inconsistent across usages
91
+ while((ch = v_window.getchar()) != ?\C-q.getbyte(0) )
92
+ break if ch == config[:close_key] || ch == ?q.ord || ch == 2727 # added double esc 2011-12-27
93
+ # if you've asked for ENTER then i also check for 10 and 13
94
+ break if (ch == 10 || ch == 13) && config[:close_key] == KEY_ENTER
95
+ v_form.handle_key ch
96
+ v_form.repaint
97
+ end
98
+ rescue => err
99
+ $log.error " VIEWER ERROR #{err} "
100
+ $log.debug(err.backtrace.join("\n"))
101
+ textdialog ["Error in viewer: #{err} ", *err.backtrace], :title => "Exception"
102
+ ensure
103
+ v_window.destroy if !v_window.nil?
104
+ end
105
+ end
106
+ private
107
+ def self._get_contents fp
108
+ return "File #{fp} not readable" unless File.readable? fp
109
+ return Dir.new(fp).entries if File.directory? fp
110
+ case File.extname(fp)
111
+ when '.tgz','.gz'
112
+ cmd = "tar -ztvf #{fp}"
113
+ content = %x[#{cmd}]
114
+ when '.zip'
115
+ cmd = "unzip -l #{fp}"
116
+ content = %x[#{cmd}]
117
+ when '.jar', '.gem'
118
+ cmd = "tar -tvf #{fp}"
119
+ content = %x[#{cmd}]
120
+ when '.png', '.out','.jpg', '.gif','.pdf'
121
+ content = "File #{fp} not displayable"
122
+ when '.sqlite'
123
+ cmd = "sqlite3 #{fp} 'select name from sqlite_master;'"
124
+ content = %x[#{cmd}]
125
+ else
126
+ content = File.open(fp,"r").readlines
127
+ end
128
+ end
129
+ end # class
130
+
131
+ end # module
132
+ if __FILE__ == $PROGRAM_NAME
133
+ require 'rbhex/core/util/app'
134
+
135
+ App.new do
136
+ header = app_header "rbhex 1.2.0", :text_center => "Viewer Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
137
+ message "Press F1 to exit from here"
138
+
139
+ RubyCurses::Viewer.view(ARGV[0] || $0, :close_key => KEY_ENTER, :title => "Enter to close") do |t|
140
+ # you may configure textview further here.
141
+ #t.suppress_borders true
142
+ #t.color = :black
143
+ #t.bgcolor = :white
144
+ # or
145
+ #t.attr = :reverse
146
+ end
147
+
148
+ end # app
149
+ end
@@ -0,0 +1,506 @@
1
+ # ------------------------------------------------------------ #
2
+ # File: widgetshortcuts.rb
3
+ # Description: A common module for shortcuts to create widgets
4
+ # Also, stacks and flows objects
5
+ # Author: rkumar http://github.com/rkumar/rbcurse/
6
+ # Date: 05.11.11 - 15:13
7
+ # Last update: 2013-03-21 00:55
8
+ #
9
+ # I hope this slowly does not become an unmaintainable maze like vimsplit
10
+ #
11
+ # "Simplicity hinges as much on cutting nonessential features as on adding helpful ones."
12
+ # - Walter Bender
13
+ #
14
+ # == TODO
15
+ # add multirow comps like textview and textarea, list
16
+ # add blocks that make sense like in app
17
+ # - what if user does not want form attached - app uses useform ot
18
+ # to check for this, if current_object don't add form
19
+ #
20
+ # - usage of _position inside means these shortcuts cannot be reused
21
+ # with other positioning systems, we'll be cut-pasting forever
22
+ #
23
+ # == CHANGES
24
+ # ------------------------------------------------------------ #
25
+ #
26
+
27
+ # what is the real purpose of the shortcuts, is it to avoid putting nil
28
+ # for form there if not required.
29
+ # Or is it positioning, such as in a stack. or just a method ?
30
+ require 'rbhex/core/widgets/rlist'
31
+ require 'rbhex/core/widgets/rtextview'
32
+ module RubyCurses
33
+ module WidgetShortcuts
34
+ class Ws
35
+ attr_reader :config
36
+ def initialize config={}
37
+ @config = config
38
+ end
39
+ def [](sym)
40
+ @config[sym]
41
+ end
42
+ def []=(sym, val)
43
+ @config[sym] = val
44
+ end
45
+ end
46
+ class WsStack < Ws; end
47
+ class WsFlow < Ws; end
48
+ def widget_shortcuts_init
49
+ @_ws_app_row = @_ws_app_col = 0
50
+ #@_ws_active = []
51
+ @_ws_active = nil # so we can use shortcuts if no stack used
52
+ @_ws_components = []
53
+ @variables = {}
54
+ end
55
+ def blank
56
+ label :text => ""
57
+ end
58
+ def line config={}
59
+ #horizontal line TODO
60
+ #row = config[:row] || @app_row
61
+ #width = config[:width] || 20
62
+ #_position config
63
+ #col = config[:col] || 1
64
+ #@color_pair = config[:color_pair] || $datacolor
65
+ #@attrib = config[:attrib] || Ncurses::A_NORMAL
66
+ #@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
67
+ #@window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width)
68
+ #@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
69
+ end
70
+ def radio config={}, &block
71
+ a = config[:group]
72
+ # should we not check for a nil
73
+ if @variables.has_key? a
74
+ v = @variables[a]
75
+ else
76
+ v = Variable.new
77
+ @variables[a] = v
78
+ end
79
+ config[:variable] = v
80
+ config.delete(:group)
81
+ w = RadioButton.new nil, config #, &block
82
+ _position w
83
+ if block
84
+ w.bind(:PRESS, &block)
85
+ end
86
+ return w
87
+ end
88
+ # create a shortcut for a class
89
+ # path is path of file to use in require starting with rbhex
90
+ # klass is name of class to instantiate
91
+ def self.def_widget(path, klass, short=nil)
92
+ p=""
93
+ if path
94
+ p="require \"#{path}\""
95
+ end
96
+ short ||= klass.to_s.downcase
97
+ eval %{
98
+ def #{short}(config={}, &block)
99
+ if config.is_a? String
100
+ _s = config
101
+ config = {}
102
+ config[:text] = _s
103
+ end
104
+ #{p}
105
+ w = #{klass}.new nil, config
106
+ _position w
107
+ w.command &block if block_given?
108
+ return w
109
+ end
110
+ }
111
+ end
112
+ def_widget "rbhex/core/widgets/rprogress", "Progress"
113
+ def_widget "rbhex/core/widgets/scrollbar", "Scrollbar"
114
+ def_widget nil, "Label"
115
+ def_widget nil, "Field"
116
+ def_widget nil, :CheckBox, 'check'
117
+ def_widget nil, :Button
118
+ def_widget nil, :ToggleButton, 'toggle'
119
+ def menubar &block
120
+ require 'rbhex/core/widgets/rmenu'
121
+ RubyCurses::MenuBar.new &block
122
+ end
123
+ def app_header title, config={}, &block
124
+ require 'rbhex/core/widgets/applicationheader'
125
+ header = ApplicationHeader.new @form, title, config, &block
126
+ end
127
+ # editable text area
128
+ def textarea config={}, &block
129
+ require 'rbhex/core/widgets/rtextarea'
130
+ # TODO confirm events many more
131
+ events = [ :CHANGE, :LEAVE, :ENTER ]
132
+ block_event = events[0]
133
+ #_process_args args, config, block_event, events
134
+ #config[:width] = config[:display_length] unless config.has_key? :width
135
+ # if no width given, expand to flows width
136
+ #config[:width] ||= @stack.last.width if @stack.last
137
+ useform = nil
138
+ #useform = @form if @current_object.empty?
139
+ w = TextArea.new useform, config
140
+ w.width = :expand unless w.width
141
+ w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
142
+ _position(w)
143
+ w.height ||= 8 # TODO
144
+ # need to expand to stack's width or flows itemwidth if given
145
+ if block
146
+ w.bind(block_event, &block)
147
+ end
148
+ return w
149
+ end
150
+ def textview config={}, &block
151
+ events = [ :LEAVE, :ENTER ]
152
+ block_event = events[0]
153
+ #_process_args args, config, block_event, events
154
+ #config[:width] = config[:display_length] unless config.has_key? :width
155
+ # if no width given, expand to flows width
156
+ #config[:width] ||= @stack.last.width if @stack.last
157
+ useform = nil
158
+ #useform = @form if @current_object.empty?
159
+ w = TextView.new useform, config
160
+ w.width = :expand unless w.width
161
+ w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
162
+ _position(w)
163
+ # need to expand to stack's width or flows itemwidth if given
164
+ if block
165
+ w.bind(block_event, &block)
166
+ end
167
+ return w
168
+ end
169
+ def listbox config={}, &block
170
+ events = [ :PRESS, :ENTER_ROW, :LEAVE, :ENTER ]
171
+ block_event = events[0]
172
+ #_process_args args, config, block_event, events
173
+ #config[:width] = config[:display_length] unless config.has_key? :width
174
+ # if no width given, expand to flows width
175
+ #config[:width] ||= @stack.last.width if @stack.last
176
+ useform = nil
177
+ #useform = @form if @current_object.empty?
178
+ w = List.new useform, config
179
+ w.width = :expand unless w.width
180
+ w.height ||= :expand # TODO We may need to push this before _position so it can be accounted for in stack
181
+ _position(w)
182
+ # need to expand to stack's width or flows itemwidth if given
183
+ if block
184
+ w.bind(block_event, &block)
185
+ end
186
+ return w
187
+ end
188
+ # prints pine-like key labels
189
+ def dock labels, config={}, &block
190
+ require 'rbhex/core/widgets/keylabelprinter'
191
+ klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block
192
+ end
193
+
194
+ def link config={}, &block
195
+ if config.is_a? String
196
+ _s = config
197
+ config = {}
198
+ config[:text] = _s
199
+ end
200
+ require 'rbhex/core/widgets/rlink'
201
+ events = [ :PRESS, :LEAVE, :ENTER ]
202
+ block_event = :PRESS
203
+ config[:highlight_foreground] = "yellow"
204
+ config[:highlight_background] = "red"
205
+ toggle = Link.new nil, config
206
+ _position(toggle)
207
+ if block
208
+ toggle.bind(block_event, toggle, &block)
209
+ end
210
+ return toggle
211
+ end
212
+ def menulink config={}, &block
213
+ if config.is_a? String
214
+ _s = config
215
+ config = {}
216
+ config[:text] = _s
217
+ end
218
+ require 'rbhex/core/widgets/rmenulink'
219
+ events = [ :PRESS, :LEAVE, :ENTER ]
220
+ block_event = :PRESS
221
+ config[:highlight_foreground] = "yellow"
222
+ config[:highlight_background] = "red"
223
+ #config[:hotkey] = true
224
+ w = MenuLink.new nil, config
225
+ _position(w)
226
+ if block
227
+ w.bind(block_event, w, &block)
228
+ end
229
+ return w
230
+ end
231
+ def tree config={}, &block
232
+ require 'rbhex/core/widgets/rtree'
233
+ events = [:TREE_WILL_EXPAND_EVENT, :TREE_EXPANDED_EVENT, :TREE_SELECTION_EVENT, :PROPERTY_CHANGE, :LEAVE, :ENTER ]
234
+ block_event = nil
235
+ #config[:height] ||= 10
236
+ # if no width given, expand to flows width
237
+ useform = nil
238
+ #useform = @form if @current_object.empty?
239
+ w = Tree.new useform, config, &block
240
+ w.width ||= :expand
241
+ w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
242
+ _position w
243
+ return w
244
+ end
245
+ # creates a simple readonly table, that allows users to click on rows
246
+ # and also on the header. Header clicking is for column-sorting.
247
+ def tabular_widget config={}, &block
248
+ require 'rbhex/core/widgets/tabularwidget'
249
+ events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :CHANGE, :ENTER_ROW, :PRESS ]
250
+ block_event = nil
251
+ # if no width given, expand to stack width
252
+ #config.delete :title
253
+ useform = nil
254
+
255
+ w = TabularWidget.new useform, config # NO BLOCK GIVEN
256
+ w.width ||= :expand
257
+ w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
258
+ _position(w)
259
+ if block_given?
260
+ #@current_object << w
261
+ yield_or_eval &block
262
+ #@current_object.pop
263
+ end
264
+ return w
265
+ end
266
+ alias :table :tabular_widget
267
+ # NOTE UNTESTED
268
+ def vimsplit config={}, &block
269
+ require 'rbhex/extras/widgets/rvimsplit'
270
+ #TODO check these
271
+ events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ]
272
+ block_event = nil
273
+ config[:height] ||= 10
274
+ # if no width given, expand to flows width
275
+ #config.delete :title
276
+ useform = nil
277
+
278
+ w = VimSplit.new useform, config # NO BLOCK GIVEN
279
+ _position(w)
280
+ if block_given?
281
+ #@current_object << w
282
+ #instance_eval &block if block_given?
283
+ yield w
284
+ #@current_object.pop
285
+ end
286
+ return w
287
+ end
288
+ def _position w
289
+ if @_ws_active.nil? || @_ws_active.empty?
290
+ # no stack or flow, this is independent usage, or else we are outside stacks and flows
291
+ #
292
+ # this is outside any stack or flow, so we do the minimal
293
+ # user should specify row and col
294
+ w.row ||= 0
295
+ w.col ||= 0
296
+ #$log.debug "XXX: LABEL #{w.row} , #{w.col} "
297
+ w.set_form @form if @form # temporary,, only set if not inside an object FIXME
298
+ if w.width == :expand # calculate from current col, not 0 FIXME
299
+ w.width = FFI::NCurses.COLS-w.col # or take windows width since this could be in a message box
300
+ end
301
+ if w.height == :expand
302
+ # take from current row, and not zero FIXME
303
+ w.height = FFI::NCurses.LINES-w.row # or take windows width since this could be in a message box
304
+ end
305
+ return
306
+
307
+ end
308
+ # -------------------------- there is a stack or flow -------------------- #
309
+ #
310
+ cur = @_ws_active.last
311
+ unless cur
312
+ raise "This should have been handled previously.Somethings wrong, check/untested"
313
+ end
314
+ r = cur[:row] || 0
315
+ c = cur[:col] || 0
316
+ w.row = r
317
+ w.col = c
318
+ # if flow then take flows height, else use dummy value
319
+ if w.height_pc
320
+ w.height = ( (cur[:height] * w.height_pc.to_i)/100).floor
321
+ end
322
+ if w.height == :expand
323
+ if cur.is_a? WsFlow
324
+ w.height = cur[:height] || 8 #or raise "height not known for flow"
325
+ else
326
+ w.height = cur[:item_height] || 8 #or raise "height not known for flow"
327
+ end
328
+ #alert "setting ht to #{w.height}, #{cur[:height]} , for #{cur} "
329
+ end
330
+ if w.width == :expand
331
+ if cur.is_a? WsFlow
332
+ if cur[:item_width]
333
+ w.width = cur[:item_width] #or raise "item_Width not known for flow #{cur.class}, #{cur[:item_width]}, #{cur[:width]} , #{w.width_pc} "
334
+ elsif w.width_pc
335
+ #w.width = w.width_pc * cur[:width]
336
+ w.width = (cur[:width] * (w.width_pc.to_i * 0.01)).floor
337
+ else
338
+ w.width = cur[:width]
339
+ end
340
+ raise "width could not be calculated. i need flow width and item width_pc" if w.width == :expand
341
+ else
342
+ w.width = cur[:width] or raise "Width not known for stack #{cur.class}, #{cur[:width]} "
343
+ end
344
+ end
345
+ if cur.is_a? WsStack
346
+ r += w.height || 1 # NOTE, we need to have height for this purpose defined BEFORE calling for list/text
347
+ cur[:row] = r
348
+ else
349
+ wid = cur[:item_width] || w.width || 10
350
+ c += wid + 1
351
+ cur[:col] = c
352
+ end
353
+ #alert "set width to #{w.width} ,cur: #{cur[:width]} ,iw: #{cur[:item_width]} "
354
+ if cur.is_a? WsFlow
355
+ unless w.height
356
+ w.height = cur[:height] #or raise "Height not known for flow"
357
+ end
358
+ end
359
+ w.color ||= cur[:color]
360
+ w.bgcolor ||= cur[:bgcolor]
361
+ w.set_form @form if @form # temporary
362
+ @_ws_components << w
363
+ cur[:components] << w
364
+ end
365
+ # make it as simple as possible, don't try to be intelligent or
366
+ # clever, put as much on the user
367
+ def stack config={}, &block
368
+ s = WsStack.new config
369
+ @_ws_active ||= []
370
+ _configure s
371
+ @_ws_active << s
372
+ yield_or_eval &block if block_given?
373
+ @_ws_active.pop
374
+
375
+ # ---- stack is finished now
376
+ last = @_ws_active.last
377
+ if last
378
+ case last
379
+ when WsStack
380
+ when WsFlow
381
+ last[:col] += last[:item_width] || 0
382
+ # this tries to set height of outer flow based on highest row
383
+ # printed, however that does not account for height of object,
384
+ # so user should give a height to the flow.
385
+ last[:height] = s[:row] if s[:row] > (last[:height]||0)
386
+ $log.debug "XXX: STACK setting col to #{s[:col]} "
387
+ end
388
+ end
389
+
390
+ end
391
+ #
392
+ # item_width - width to use per item
393
+ # but the item width may apply to stacks inside not to items
394
+ def flow config={}, &block
395
+ s = WsFlow.new config
396
+ @_ws_active ||= []
397
+ _configure s
398
+ @_ws_active << s
399
+ yield_or_eval &block if block_given?
400
+ @_ws_active.pop
401
+ last = @_ws_active.last
402
+ if last
403
+ case last
404
+ when WsStack
405
+ if s[:height]
406
+ last[:row] += s[:height]
407
+ else
408
+ #last[:row] += last[:highest_row]
409
+ last[:row] += 1
410
+ end
411
+ when WsFlow
412
+ last[:col] += last[:item_width] || 0
413
+ end
414
+ end
415
+ end
416
+ # flow and stack could have a border option
417
+ # NOTE: box takes one row below too, so :expand overwrites that line
418
+ def box config={}, &block
419
+ require 'rbhex/core/widgets/box'
420
+ # take current stacks row and col
421
+ # advance row by one and col by one
422
+ # at end note row and advance by one
423
+ # draw a box around using these coordinates. width should be
424
+ # provided unless we have item width or something.
425
+ @_ws_active ||= []
426
+ last = @_ws_active.last
427
+ if last
428
+ r = last[:row]
429
+ c = last[:col]
430
+ config[:row] = r
431
+ config[:col] = c
432
+ last[:row] += config[:margin_top] || 1
433
+ last[:col] += config[:margin_left] || 1
434
+ _box = Box.new @form, config # needs to be created first or will overwrite area after others painted
435
+ yield_or_eval &block if block_given?
436
+ # FIXME last[height] needs to account for row
437
+ h = config[:height] || last[:height] || (last[:row] - r)
438
+ h = 2 if h < 2
439
+ w = config[:width] || last[:width] || 15 # tmp
440
+ case last
441
+ when WsFlow
442
+ w = last[:col]
443
+ when WsStack
444
+ #h += 1
445
+ end
446
+ config[:row] = r
447
+ config[:col] = c
448
+ config[:height] = h
449
+ config[:width] = w
450
+ _box.row r
451
+ _box.col c
452
+ _box.height h
453
+ _box.width w
454
+ last[:row] += 1
455
+ last[:col] += 1 # ??? XXX if flow we need to increment properly or not ?
456
+ end
457
+ end
458
+
459
+ # This configures a stack or flow not the objects inside
460
+ def _configure s
461
+ s[:row] ||= 0
462
+ s[:col] ||= 0
463
+ s[:row] += (s[:margin_top] || 0)
464
+ s[:col] += (s[:margin_left] || 0)
465
+ s[:width] = FFI::NCurses.COLS-s[:col] if s[:width] == :expand
466
+ s[:height] = FFI::NCurses.LINES-s[:row] if s[:height] == :expand # 2011-11-30
467
+ last = @_ws_active.last
468
+ if last
469
+ if s[:width_pc]
470
+ if last.is_a? WsStack
471
+ s[:width] = (last[:width] * (s[:width_pc].to_i * 0.01)).floor
472
+ else
473
+ # i think this width is picked up by next stack in this flow
474
+ last[:item_width] = (last[:width] * (s[:width_pc].to_i* 0.01)).floor
475
+ end
476
+ end
477
+ if s[:height_pc]
478
+ if last.is_a? WsFlow
479
+ s[:height] = ( (last[:height] * s[:height_pc].to_i)/100).floor
480
+ else
481
+ # this works only for flows within stacks not for an object unless
482
+ # you put a single object in a flow
483
+ s[:item_height] = ( (last[:height] * s[:height_pc].to_i)/100).floor
484
+ end
485
+ #alert "item height set as #{s[:height]} for #{s} "
486
+ end
487
+ if last.is_a? WsStack
488
+ s[:row] += (last[:row] || 0)
489
+ s[:col] += (last[:col] || 0)
490
+ else
491
+ s[:row] += (last[:row] || 0)
492
+ s[:col] += (last[:col] || 0) # we are updating with item_width as each st finishes
493
+ s[:width] ||= last[:item_width] #
494
+ end
495
+ else
496
+ # this should be outer most flow or stack, if nothing mentioned
497
+ # trying this out
498
+ s[:width] ||= :expand
499
+ s[:height] ||= :expand
500
+ s[:width] = FFI::NCurses.COLS-s[:col] if s[:width] == :expand
501
+ s[:height] = FFI::NCurses.LINES-s[:row] if s[:height] == :expand # 2011-11-30
502
+ end
503
+ s[:components] = []
504
+ end
505
+ end
506
+ end