rbhex-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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