rbcurse-core 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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