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,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