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