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,30 @@
1
+ require 'rbhex'
2
+ ##
3
+ module RubyCurses
4
+ class Link < Button
5
+ dsl_property :description
6
+
7
+
8
+ def initialize form, config={}, &block
9
+ super
10
+ @text_offset = 0
11
+ # haha we've never done this, pin the cursor up on 0,0
12
+ @col_offset = -1
13
+ # this won't be triggered since the shortcut does not set menmo
14
+ # unless form is there.
15
+ # Sometimes the mnemonic is not in text, such as '?'
16
+ if @mnemonic
17
+ form.bind_key(@mnemonic.downcase, self){ self.fire }
18
+ end
19
+ @display_length = config[:width]
20
+ end
21
+ def fire
22
+ super
23
+ self.focus
24
+ end
25
+ def getvalue_for_paint
26
+ getvalue()
27
+ end
28
+ ##
29
+ end # class
30
+ end # module
@@ -0,0 +1,696 @@
1
+ =begin
2
+ * Name: rlistbox: basic scrollable lists - no editing, see editablelistbox of more
3
+ * Description
4
+ * Author: rkumar (arunachalesha)
5
+ * Date: 2010-09-26 16:00
6
+ * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
7
+ *
8
+ TODO
9
+ [x] removed Popup, ListDataEvent and ListDataModel !
10
+ [x] XXX Can we separate editing out. Make a ReadonlyList, and extend it as EditableList. This way the usual
11
+ use case remains cleaner.
12
+
13
+ CHANGES
14
+ - 2011-11-18 changed name to list
15
+
16
+ =end
17
+ require 'rbhex'
18
+ require 'rbhex/core/include/listcellrenderer'
19
+ require 'rbhex/core/include/bordertitle'
20
+ #require 'rbhex/extras/include/listkeys'
21
+ require 'forwardable'
22
+
23
+
24
+ module RubyCurses
25
+ extend self
26
+ ##
27
+ ##
28
+ # scrollable, selectable list of items
29
+ # - @selected contains indices of selected objects.
30
+ ##
31
+ ##
32
+ # A readonly control for displaying a list of data or values.
33
+ # Although user editing is not allowed, but the list may be repopulated
34
+ # as in a directory listing, or a list dependent on some other control's value.
35
+ # This is not a drop-in replacement for Listbox as it drops many methods that are redundant.
36
+ # Default selection is single, as opposed to Listbox.
37
+ #
38
+ class List < Widget
39
+
40
+ require 'rbhex/core/include/listscrollable'
41
+ require 'rbhex/core/include/listselectable' # added 2011-10-8
42
+ include ListScrollable
43
+ include NewListSelectable # added 2011-10-8
44
+ extend Forwardable
45
+ #dsl_accessor :height # << widget already has this
46
+ #dsl_accessor :title
47
+ #dsl_property :title_attrib # bold, reverse, normal
48
+ # dsl_accessor :list # the array of data to be sent by user
49
+ attr_reader :toprow
50
+ #dsl_accessor :default_values # array of default values
51
+ #dsl_accessor :is_popup # if it is in a popup and single select, selection closes
52
+ attr_accessor :current_index
53
+ # selection mode multiple, single and none (none added 2011-12-26)
54
+ dsl_accessor :selection_mode
55
+ dsl_accessor :selected_color, :selected_bgcolor, :selected_attr
56
+ dsl_accessor :max_visible_items # how many to display 2009-01-11 16:15
57
+ #dsl_accessor :cell_editing_allowed
58
+ dsl_property :show_selector # boolean
59
+ dsl_property :row_selected_symbol # 2009-01-12 12:01 changed from selector to selected
60
+ dsl_property :row_unselected_symbol # added 2009-01-12 12:00
61
+ dsl_property :left_margin
62
+ # please set these in he constructor block. Settin them later will have no effect
63
+ # since i would have bound them to actions
64
+ attr_accessor :one_key_selection # will pressing a single key select or not
65
+ # set to true if data could have newlines, tabs, and other stuff, def true
66
+ dsl_accessor :sanitization_required
67
+ # set to true if cell-renderer data can exceed width of listbox, default true
68
+ # if you are absolutely sure that data is constant width, set to false.
69
+ dsl_accessor :truncation_required
70
+ #dsl_accessor :suppress_borders #to_print_borders
71
+ dsl_accessor :justify # will be picked up by renderer
72
+ # index of selected row
73
+ attr_accessor :selected_index
74
+ # index of selected rows, if multiple selection asked for
75
+ dsl_accessor :selected_indices
76
+
77
+ dsl_accessor :should_show_focus
78
+
79
+ # basic listbox constructor
80
+ #
81
+ def initialize form=nil, config={}, &block
82
+ @focusable = true
83
+ @editable = false
84
+ @sanitization_required = true # cleanup control and non print chars
85
+ @truncation_required = true
86
+ @suppress_borders = false #to_print_borders = 1
87
+ #@row_selected_symbol = '' # thi sprevents default value from being set
88
+ @row = 0
89
+ @col = 0
90
+ # data of listbox this is not an array, its a pointer to the listdatamodel
91
+ @list = nil
92
+ # any special attribs such as status to be printed in col1, or color (selection)
93
+ @list_attribs = {}
94
+ @current_index = 0
95
+ @selected_indices = []
96
+ @selected_index = nil
97
+ @row_offset = @col_offset = 1
98
+ @should_show_focus = true # Here's its on since the cellrenderer will show it on repaint
99
+ @one_key_selection = false # use vim keys
100
+ @selection_mode = :multiple # default is multiple, anything else given becomes single
101
+ super
102
+ @_events.push(*[:ENTER_ROW, :LEAVE_ROW, :LIST_SELECTION_EVENT, :PRESS])
103
+ # I have moved this here so user can override keys.
104
+ map_keys unless @keys_mapped
105
+ @win = @graphic # 2010-01-04 12:36 BUFFERED replace form.window with graphic
106
+ @win_left = 0
107
+ @win_top = 0
108
+
109
+ init_vars
110
+ @internal_width = 2
111
+ #@internal_width = 0 if @suppress_borders # NOTE it is 1 in bordertitle
112
+ bordertitle_init
113
+
114
+ if @list && !@selected_index.nil? # XXX
115
+ set_focus_on @selected_index # the new version
116
+ end
117
+ init_actions
118
+ end
119
+ # this is called several times, from constructor
120
+ # and when list data changed, so only put relevant resets here.
121
+ def init_vars
122
+ @repaint_required = true
123
+ @widget_scrolled = true # 2011-10-15
124
+ @toprow = @pcol = 0
125
+ if @show_selector
126
+ @row_selected_symbol ||= '>'
127
+ @row_unselected_symbol ||= ' '
128
+ @left_margin ||= @row_selected_symbol.length
129
+ end
130
+ @row_selected_symbol ||= ''
131
+ #@left_margin ||= 0
132
+ @one_key_selection = false if @one_key_selection.nil?
133
+ @row_offset = @col_offset = 0 if @suppress_borders
134
+
135
+ end
136
+ def map_keys
137
+ return if @keys_mapped
138
+ require 'rbhex/core/include/listbindings'
139
+ bindings()
140
+ bind_key(?f, 'next row starting with char'){ ask_selection_for_char() }
141
+ bind_key(?\M-v, 'toggle one_key_selection'){ @one_key_selection = !@one_key_selection }
142
+ bind_key(13, 'fire action event'){ fire_action_event }
143
+ list_bindings unless @selection_mode == :none # listselectable
144
+ @keys_mapped = true
145
+
146
+ end
147
+
148
+ ## returns count of row, needed by scrollbar and others.
149
+ def row_count
150
+ return 0 if @list.nil?
151
+ @list.length
152
+ end
153
+ # start scrolling when user reaches this row
154
+ def scrollatrow #:nodoc:
155
+ if @suppress_borders
156
+ return @height - 1
157
+ else
158
+ return @height - 3
159
+ end
160
+ end
161
+ # provide data to List in the form of an Array or Variable or
162
+ # ListDataModel. This will create a default ListSelectionModel.
163
+ #
164
+ # CHANGE as on 2010-09-21 12:53:
165
+ # If explicit nil passed then dummy datamodel and selection model created
166
+ # From now on, constructor will call this, so this can always
167
+ # happen.
168
+ #
169
+ # NOTE: sometimes this can be added much after its painted.
170
+ # Do not expect this to be called from constructor, although that
171
+ # is the usual case. it can be dependent on some other list or tree.
172
+ # @param [Array, Variable, ListDataModel] data to populate list with
173
+ # @return [ListDataModel] just created or assigned
174
+
175
+ def list *val
176
+ return @list if val.empty?
177
+ alist = val[0]
178
+ case alist
179
+ when Array
180
+ @list = alist
181
+ # I possibly should call init_vars in these 3 cases but am doing the minimal 2013-04-10 - 18:27
182
+ # Based no issue: https://github.com/rkumar/rbcurse/issues/15
183
+ @current_index = @toprow = @pcol = 0
184
+ when NilClass
185
+ @list = [] # or nil ?
186
+ @current_index = @toprow = @pcol = 0
187
+ when Variable
188
+ @list = alist.value
189
+ @current_index = @toprow = @pcol = 0
190
+ else
191
+ raise ArgumentError, "Listbox list(): do not know how to handle #{alist.class} "
192
+ end
193
+ clear_selection
194
+
195
+ @repaint_required = true
196
+ @widget_scrolled = true # 2011-10-15
197
+ @list
198
+ end
199
+ def list_data_model; @list; end
200
+ # conv method to insert data, trying to keep names same across along with Tabular, TextView,
201
+ # TextArea and listbox. Don;t use this till i am certain.
202
+ def data=(val)
203
+ list(val)
204
+ end
205
+ # get element at
206
+ # @param [Fixnum] index for element
207
+ # @return [Object] element
208
+ # @since 1.2.0 2010-09-06 14:33 making life easier for others.
209
+ def [](off0)
210
+ @list[off0]
211
+ end
212
+ # return object under cursor
213
+ # Note: this should not be confused with selected row/s. User may not have selected this.
214
+ # This is only useful since in some demos we like to change a status bar as a user scrolls down
215
+ # @since 1.2.0 2010-09-06 14:33 making life easier for others.
216
+ def current_value
217
+ @list[@current_index]
218
+ end
219
+ def remove_all
220
+ return if @list.nil? || @list.empty?
221
+ @list = []
222
+ init_vars
223
+ end
224
+ def_delegators :@list, :include?, :each, :values, :size
225
+ %w[ insert clear delete_at []= << ].each { |e|
226
+ eval %{
227
+ def #{e}(*args)
228
+ @list.send(:#{e}, *args)
229
+ @widget_scrolled = true
230
+ @repaint_required = true
231
+ end
232
+ }
233
+ }
234
+ def append text
235
+ @list.push text
236
+ @widget_scrolled = true
237
+ @repaint_required = true
238
+ end
239
+ # avoid using "row", i'd rather stick with "index" and "value".
240
+ alias :current_row :current_value
241
+ alias :text :current_value # thanks to shoes, not sure how this will impact since widget has text.
242
+
243
+ ### START FOR scrollable ###
244
+ def get_content
245
+ @list
246
+ end
247
+ def get_window #:nodoc:
248
+ @graphic
249
+ end
250
+ ### END FOR scrollable ###
251
+ # override widgets text
252
+ # returns indices of selected rows
253
+ def getvalue
254
+ selected_rows
255
+ end
256
+ # Listbox
257
+ def handle_key(ch) #:nodoc:
258
+ #map_keys unless @keys_mapped
259
+ @current_index ||= 0
260
+ @toprow ||= 0
261
+ #h = scrollatrow()
262
+ #rc = row_count
263
+ #$log.debug " basiclistbox got ch #{ch}"
264
+ #$log.debug " when kps #{@KEY_PREV_SELECTION} "
265
+ case ch
266
+ #when 32
267
+ #return if is_popup and @selection_mode == 'single' # not allowing select this way since there will be a difference
268
+ #toggle_row_selection @current_index #, @current_index
269
+ #@repaint_required = true
270
+ #when 0 # c-space
271
+ #add_to_selection
272
+ #when @KEY_NEXT_SELECTION # ?'
273
+ #$log.debug "insdie next selection"
274
+ #@oldrow = @current_index
275
+ #do_next_selection
276
+ #bounds_check
277
+ #when @KEY_PREV_SELECTION # ?"
278
+ #@oldrow = @current_index
279
+ #$log.debug "insdie prev selection"
280
+ #do_prev_selection
281
+ #bounds_check
282
+ #when @KEY_CLEAR_SELECTION
283
+ #clear_selection
284
+ #@repaint_required = true
285
+ when 27, ?\C-c.getbyte(0)
286
+ $multiplier = 0
287
+ when @KEY_BLOCK_SELECTOR
288
+ mark_block #selection
289
+ #when ?\C-u.getbyte(0)
290
+ # multiplier. Series is 4 16 64
291
+ # TESTING @multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
292
+ # return 0
293
+ #when ?\C-c.getbyte(0)
294
+ #@multiplier = 0
295
+ #return 0
296
+ else
297
+ # this has to be fixed, if compo does not handle key it has to continue into next part FIXME
298
+ ret = :UNHANDLED # changed on 2009-01-27 13:14 not going into unhandled, tab not released
299
+ if ret == :UNHANDLED
300
+ # beware one-key eats up numbers. we'll be wondering why
301
+ if @one_key_selection
302
+ case ch
303
+ #when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0), ?0.getbyte(0)..?9.getbyte(0)
304
+ when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0)
305
+ # simple motion, key press defines motion
306
+ ret = set_selection_for_char ch.chr
307
+ else
308
+ ret = process_key ch, self
309
+ @multiplier = 0
310
+ # if no block associated with :PRESS (KEY_ENTER) lets allow the form to use ENTER
311
+ # This is for default buttons. Added NO_BLOCK 2011-12-2
312
+ # 2011-12-2 11:54 PM this was resulting in no repaint even
313
+ # when symbols were being executed??
314
+ # Its risky since symbol can call something which returns
315
+ # UNHNDLED or NO_BLOCK even tho' it executed.
316
+ return :UNHANDLED if ret == :UNHANDLED #|| ret == :NO_BLOCK
317
+ end
318
+ else
319
+ # no motion on single key, we can freak out like in vim, pref f <char> for set_selection
320
+ case ch
321
+ when ?0.getbyte(0)..?9.getbyte(0)
322
+ $multiplier *= 10 ; $multiplier += (ch-48)
323
+ #$log.debug " setting mult to #{$multiplier} in list "
324
+ return 0
325
+ end
326
+ ret = process_key ch, self
327
+ # if no block associated with :PRESS (KEY_ENTER) lets allow the form to use ENTER
328
+ # This is for default buttons. Added NO_BLOCK 2011-12-2
329
+ return :UNHANDLED if ret == :UNHANDLED #|| ret == :NO_BLOCK1
330
+ end
331
+ end
332
+ end
333
+ $multiplier = 0
334
+ end
335
+ #
336
+ # triggered on hitting ENTER button
337
+ #
338
+ def fire_action_event
339
+ require 'rbhex/core/include/ractionevent'
340
+ fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
341
+ end
342
+ # get a keystroke from user and go to first item starting with that key
343
+ def ask_selection_for_char
344
+ ch = @graphic.getch
345
+ if ch < 0 || ch > 255
346
+ return :UNHANDLED
347
+ end
348
+ ret = set_selection_for_char ch.chr
349
+ end
350
+ def ask_search_forward
351
+ regex = get_string("Enter regex to search")
352
+ ix = @list.find_match regex
353
+ if ix.nil?
354
+ alert("No matching data for: #{regex}")
355
+ else
356
+ set_focus_on(ix)
357
+ end
358
+ end
359
+ # gets string to search and calls data models find prev
360
+ def ask_search_backward
361
+ regex = get_string("Enter regex to search (backward)")
362
+ @last_regex = regex
363
+ ix = @list.find_prev regex, @current_index
364
+ if ix.nil?
365
+ alert("No matching data for: #{regex}")
366
+ else
367
+ set_focus_on(ix)
368
+ end
369
+ end
370
+ # please check for error before proceeding
371
+ # @return [Boolean] false if no data
372
+ def on_enter
373
+ if @list.nil? || @list.size == 0
374
+ Ncurses.beep
375
+ return :UNHANDLED
376
+ end
377
+ super # forgot this 2011-10-9 that's why events not firign
378
+ on_enter_row @current_index
379
+ set_form_row # added 2009-01-11 23:41
380
+ true
381
+ end
382
+ def on_enter_row arow
383
+ # copied from resultsettextview, can this not be in one place like listscrollable ? FIXME
384
+ if @should_show_focus
385
+ highlight_focussed_row :FOCUSSED
386
+ unless @oldrow == @selected_index
387
+ highlight_focussed_row :UNFOCUSSED
388
+ end
389
+ end
390
+ fire_handler :ENTER_ROW, self
391
+ @repaint_required = true
392
+ end
393
+ def on_leave_row arow
394
+ fire_handler :LEAVE_ROW, self
395
+ end
396
+ # getter and setter for cell_renderer
397
+ # NOTE: due to our optimization of not repainting unless data has changed
398
+ # or scrolling has happened, highlighting focus will repaint the row if you've
399
+ # colored it. In that case, set <tt>show_show_focus</tt> to false
400
+ def cell_renderer(*val)
401
+ if val.empty?
402
+ @cell_renderer ||= create_default_cell_renderer
403
+ else
404
+ @cell_renderer = val[0]
405
+ end
406
+ end
407
+ def create_default_cell_renderer
408
+ return ListCellRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => self, "display_length"=> @width-@internal_width-@left_margin}
409
+ #return BasicListCellRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => self, "display_length"=> @width-2-@left_margin}
410
+ end
411
+ ##
412
+ # this method chops the data to length before giving it to the
413
+ # renderer, this can cause problems if the renderer does some
414
+ # processing. also, it pans the data horizontally giving the renderer
415
+ # a section of it.
416
+ def repaint #:nodoc:
417
+ return unless @repaint_required
418
+ #
419
+ # TRYING OUT dangerous 2011-10-15
420
+ @repaint_required = false
421
+ @repaint_required = true if @widget_scrolled || @pcol != @old_pcol || @record_changed || @property_changed
422
+
423
+ unless @repaint_required
424
+ unhighlight_row @old_selected_index
425
+ highlight_selected_row
426
+ end
427
+ return unless @repaint_required
428
+ $log.debug "BASICLIST REPAINT WILL HAPPEN #{current_index} "
429
+ # not sure where to put this, once for all or repeat 2010-02-17 23:07 RFED16
430
+ my_win = @form ? @form.window : @target_window
431
+ @graphic = my_win unless @graphic
432
+ raise " #{@name} neither form, nor target window given LB paint " unless my_win
433
+ raise " #{@name} NO GRAPHIC set as yet LB paint " unless @graphic
434
+ raise "width or height not given w:#{@width} , h:#{@height} " if @width.nil? || @height.nil?
435
+ @win_left = my_win.left
436
+ @win_top = my_win.top
437
+ @left_margin ||= @row_selected_symbol.length
438
+ # we are making sure display len does not exceed width XXX hope this does not wreak havoc elsewhere
439
+ _dl = [@display_length || 100, @width-@internal_width-@left_margin].min # 2011-09-17 RK overwriting when we move grabbar in vimsplit
440
+
441
+ $log.debug "basiclistbox repaint #{@name} graphic #{@graphic}"
442
+ #$log.debug "XXX repaint to_print #{@to_print_borders} "
443
+ print_borders unless @suppress_borders # do this once only, unless everything changes
444
+ #maxlen = @maxlen || @width-2
445
+ tm = list()
446
+ rc = row_count
447
+ @longest_line = @width
448
+ $log.debug " rbasiclistbox #{row_count}, w:#{@width} , maxlen:#{@maxlen} "
449
+ if rc > 0 # just added in case no data passed
450
+ tr = @toprow
451
+ acolor = get_color $datacolor
452
+ h = scrollatrow()
453
+ r,c = rowcol
454
+ 0.upto(h) do |hh|
455
+ crow = tr+hh
456
+ if crow < rc
457
+ _focussed = @current_index == crow ? true : false # row focussed ?
458
+ focus_type = _focussed
459
+ focus_type = :SOFT_FOCUS if _focussed && !@focussed
460
+ selected = is_row_selected crow
461
+ content = tm[crow] # 2009-01-17 18:37 chomp giving error in some cases says frozen
462
+ content = convert_value_to_text content, crow # 2010-09-23 20:12
463
+ # by now it has to be a String
464
+ if content.is_a? String
465
+ content = content.dup
466
+ sanitize content if @sanitization_required
467
+ truncate content if @truncation_required
468
+ end
469
+ ## set the selector symbol if requested
470
+ selection_symbol = ''
471
+ if @show_selector
472
+ if selected
473
+ selection_symbol = @row_selected_symbol
474
+ else
475
+ selection_symbol = @row_unselected_symbol
476
+ end
477
+ @graphic.printstring r+hh, c, selection_symbol, acolor,@attr
478
+ end
479
+ #renderer = get_default_cell_renderer_for_class content.class.to_s
480
+ renderer = cell_renderer()
481
+ renderer.display_length = _dl # 2011-09-17 RK overwriting when we move grabbar in vimsplit
482
+ renderer.repaint @graphic, r+hh, c+@left_margin, crow, content, focus_type, selected
483
+ else
484
+ # clear rows
485
+ @graphic.printstring r+hh, c, " " * (@width-@internal_width), acolor,@attr
486
+ end
487
+ end
488
+ end # rc == 0
489
+ @repaint_required = false
490
+ # 2011-10-13
491
+ @widget_scrolled = false
492
+ @record_changed = false
493
+ @property_changed = false
494
+ @old_pcol = @pcol
495
+ end
496
+ def highlight_selected_row r=nil, c=nil, acolor=nil
497
+ return unless @selected_index # no selection
498
+ r = _convert_index_to_printable_row(@selected_index) unless r
499
+ return unless r # not on screen
500
+ unless c
501
+ _r, c = rowcol
502
+ end
503
+ acolor ||= get_color $promptcolor, @selected_color, @selected_bgcolor
504
+ att = FFI::NCurses::A_REVERSE
505
+ att = get_attrib(@selected_attrib) if @selected_attrib
506
+ @graphic.mvchgat(y=r, x=c, @width-@internal_width-@left_margin, att , acolor , nil)
507
+ end
508
+ def unhighlight_row index, r=nil, c=nil, acolor=nil
509
+ return unless index # no selection
510
+ r = _convert_index_to_printable_row(index) unless r
511
+ return unless r # not on screen
512
+ unless c
513
+ _r, c = rowcol
514
+ end
515
+ acolor ||= get_color $datacolor
516
+ att = FFI::NCurses::A_NORMAL
517
+ att = get_attrib(@normal_attrib) if @normal_attrib
518
+ @graphic.mvchgat(y=r, x=c, @width-@internal_width-@left_margin, att , acolor , nil)
519
+ end
520
+ # the idea here is to allow users who subclass Listbox to easily override parts of the cumbersome repaint
521
+ # method. This assumes your List has some data, but you print a lot more. Now you don't need to
522
+ # change the data in the renderer, or keep formatted data in the list itself.
523
+ # e.g. @list contains file names, or File objects, and this converts to a long listing.
524
+ # If the renderer did that, the truncation would be on wrong data.
525
+ # @since 1.2.0
526
+ def convert_value_to_text value, crow
527
+ case value
528
+ when TrueClass, FalseClass
529
+ value
530
+ else
531
+ value.to_s if value
532
+ end
533
+ end
534
+ # takes a block, this way anyone extending this klass can just pass a block to do his job
535
+ # This modifies the string
536
+ def sanitize content #:nodoc:
537
+ if content.is_a? String
538
+ content.chomp!
539
+ content.gsub!(/\t/, ' ') # don't display tab
540
+ content.gsub!(/[^[:print:]]/, '') # don't display non print characters
541
+ else
542
+ content
543
+ end
544
+ end
545
+ # returns only the visible portion of string taking into account display length
546
+ # and horizontal scrolling. MODIFIES STRING
547
+ def truncate content # :nodoc:
548
+ maxlen = @maxlen || @width-@internal_width
549
+ maxlen = @width-@internal_width if maxlen > @width-@internal_width
550
+ if maxlen == 0 # (otherwise it becoems -1 below)
551
+ content.replace ""
552
+ return
553
+ end
554
+ if !content.nil?
555
+ cl = content.length
556
+ if cl > maxlen # only show maxlen
557
+ @longest_line = cl if cl > @longest_line
558
+ #content = content[@pcol..@pcol+maxlen-1]
559
+ ## taking care of when scrolling is needed but longest_line is misreported
560
+ # So we scroll always and need to check 2013-03-06 - 00:09
561
+ content.replace(content[@pcol..@pcol+maxlen-1] || " ")
562
+ else
563
+ ## taking care of when scrolling is needed but longest_line is misreported
564
+ # So we scroll always and need to check 2013-03-06 - 00:09
565
+ content.replace(content[@pcol..-1]||" ") if @pcol > 0
566
+ end
567
+ end
568
+ content
569
+ end
570
+
571
+ # be informed when data has changed. required here, was being called by listdatamodel earlier
572
+ def list_data_changed
573
+ if row_count == 0 # added on 2009-02-02 17:13 so cursor not hanging on last row which could be empty
574
+ init_vars
575
+ @current_index = 0
576
+ set_form_row
577
+ end
578
+ @widget_scrolled = true # 2011-10-15
579
+ @repaint_required = true
580
+ end
581
+
582
+ # set cursor column position
583
+ # if i set col1 to @curpos, i can move around left right if key mapped
584
+ def set_form_col col1=0 #:nodoc:
585
+ @cols_panned ||= 0
586
+ # editable listboxes will involve changing cursor and the form issue
587
+ win_col = 0
588
+ col2 = win_col + @col + @col_offset + col1 + @cols_panned + @left_margin
589
+ $log.debug " set_form_col in rlistbox #{@col}+ left_margin #{@left_margin} ( #{col2} ) "
590
+ setrowcol nil, col2
591
+ end
592
+
593
+ # @group selection related
594
+
595
+ # change selection of current row on pressing space bar
596
+ # If mode is multiple, then other selections are cleared and this is added
597
+ # NOTE: 2011-10-8 allow multiple select on spacebar. Using C-Space was quite unfriendly
598
+ # although it will still work
599
+ def OLDtoggle_row_selection crow=@current_index
600
+ @repaint_required = true
601
+ row = crow
602
+ case @selection_mode
603
+ when :multiple
604
+ add_to_selection
605
+ #clear_selection
606
+ #@selected_indices[0] = crow #@current_index
607
+ else
608
+ if @selected_index == crow #@current_index
609
+ @selected_index = nil
610
+ lse = ListSelectionEvent.new(crow, crow, self, :DELETE)
611
+ fire_handler :LIST_SELECTION_EVENT, lse
612
+ else
613
+ @selected_index = crow #@current_index
614
+ lse = ListSelectionEvent.new(crow, crow, self, :INSERT)
615
+ fire_handler :LIST_SELECTION_EVENT, lse
616
+ end
617
+ end
618
+ end
619
+ #
620
+ # Only for multiple mode.
621
+ # add an item to selection, if selection mode is multiple
622
+ # if item already selected, it is deselected, else selected
623
+ # typically bound to Ctrl-Space
624
+ def OLDadd_to_selection
625
+ crow = @current_index
626
+ case @selection_mode
627
+ when :multiple
628
+ if @selected_indices.include? @current_index
629
+ @selected_indices.delete @current_index
630
+ lse = ListSelectionEvent.new(crow, crow, self, :DELETE)
631
+ fire_handler :LIST_SELECTION_EVENT, lse
632
+ else
633
+ @selected_indices << @current_index
634
+ lse = ListSelectionEvent.new(crow, crow, self, :INSERT)
635
+ fire_handler :LIST_SELECTION_EVENT, lse
636
+ end
637
+ else
638
+ end
639
+ @repaint_required = true
640
+ end
641
+ # clears selected indices
642
+ def OLDclear_selection
643
+ @selected_indices = []
644
+ @repaint_required = true
645
+ end
646
+ def OLDis_row_selected crow=@current_index
647
+ case @selection_mode
648
+ when :multiple
649
+ @selected_indices.include? crow
650
+ else
651
+ crow == @selected_index
652
+ end
653
+ end
654
+ alias :is_selected? is_row_selected
655
+ def goto_next_selection
656
+ return if selected_rows().length == 0
657
+ row = selected_rows().sort.find { |i| i > @current_index }
658
+ row ||= @current_index
659
+ @current_index = row
660
+ @repaint_required = true # fire list_select XXX
661
+ end
662
+ def goto_prev_selection
663
+ return if selected_rows().length == 0
664
+ row = selected_rows().sort{|a,b| b <=> a}.find { |i| i < @current_index }
665
+ row ||= @current_index
666
+ @current_index = row
667
+ @repaint_required = true # fire list_select XXX
668
+ end
669
+ # Returns selected indices
670
+ # Indices are often required since the renderer may modify the values displayed
671
+ #
672
+ def get_selected_indices; @selected_indices; end
673
+
674
+ # Returns selected values
675
+ #
676
+ def get_selected_values
677
+ selected = []
678
+ @selected_indices.each { |i| selected << @list[i] }
679
+ return selected
680
+ end
681
+ alias :selected_values :get_selected_values
682
+
683
+ # Define actions that can be popped up by PromptMenu or other menubar
684
+ # Currently, only PromptMenu, but we can start contextually appending to Menubar or others
685
+ def init_actions
686
+ am = action_manager()
687
+ am.add_action(Action.new("&Disable selection") { @selection_mode = :none; unbind_key(32); bind_key(32, :scroll_forward); } )
688
+ am.add_action(Action.new("&Edit Toggle") { @edit_toggle = !@edit_toggle; $status_message.value = "Edit toggle is #{@edit_toggle}" })
689
+ end
690
+
691
+
692
+ # ADD HERE
693
+ end # class listb
694
+
695
+
696
+ end # module