rbcurse 1.4.1 → 1.5.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/CHANGELOG +31 -0
  2. data/README.markdown +69 -11
  3. data/VERSION +1 -1
  4. data/lib/rbcurse.rb +5 -5
  5. metadata +10 -198
  6. data/Makefile +0 -21
  7. data/Manifest.txt +0 -91
  8. data/TODO +0 -372
  9. data/TODO2.txt +0 -118
  10. data/examples/README.txt +0 -67
  11. data/examples/abasiclist.rb +0 -33
  12. data/examples/alpmenu.rb +0 -42
  13. data/examples/app.rb +0 -859
  14. data/examples/app.sample +0 -10
  15. data/examples/appdirtree.rb +0 -75
  16. data/examples/appemail.rb +0 -191
  17. data/examples/appemaillb.rb +0 -308
  18. data/examples/appgcompose.rb +0 -315
  19. data/examples/atree.rb +0 -64
  20. data/examples/common/file.rb +0 -40
  21. data/examples/common/rmail.rb +0 -257
  22. data/examples/data.txt +0 -683
  23. data/examples/data/README.markdown +0 -9
  24. data/examples/data/brew.txt +0 -38
  25. data/examples/data/color.2 +0 -37
  26. data/examples/data/gemlist.txt +0 -60
  27. data/examples/data/lotr.txt +0 -12
  28. data/examples/data/ports.txt +0 -136
  29. data/examples/data/tasks.txt +0 -27
  30. data/examples/data/todocsv.csv +0 -28
  31. data/examples/data/unix1.txt +0 -21
  32. data/examples/data/unix2.txt +0 -11
  33. data/examples/dbdemo.rb +0 -495
  34. data/examples/deprecated/appgmail.rb +0 -952
  35. data/examples/deprecated/splitp.rb +0 -56
  36. data/examples/deprecated/testscrolllb.rb +0 -86
  37. data/examples/deprecated/testscrollp.rb +0 -88
  38. data/examples/deprecated/testscrollta.rb +0 -80
  39. data/examples/deprecated/testscrolltable.rb +0 -165
  40. data/examples/deprecated/testsplit.rb +0 -87
  41. data/examples/deprecated/testsplit2.rb +0 -123
  42. data/examples/deprecated/testsplit3.rb +0 -215
  43. data/examples/deprecated/testsplit3_1.rb +0 -244
  44. data/examples/deprecated/testsplit3a.rb +0 -215
  45. data/examples/deprecated/testsplit3b.rb +0 -237
  46. data/examples/deprecated/testsplitta.rb +0 -148
  47. data/examples/deprecated/testsplittv.rb +0 -142
  48. data/examples/deprecated/testsplittvv.rb +0 -144
  49. data/examples/deprecated/testtpane.rb +0 -215
  50. data/examples/deprecated/testtpane2.rb +0 -145
  51. data/examples/deprecated/testtpanetable.rb +0 -203
  52. data/examples/dirtree.rb +0 -88
  53. data/examples/experimental/resultsetdemo.rb +0 -280
  54. data/examples/experimental/testmform.rb +0 -35
  55. data/examples/experimental/testscroller.rb +0 -117
  56. data/examples/experimental/teststackflow.rb +0 -111
  57. data/examples/menu1.rb +0 -112
  58. data/examples/multispl.rb +0 -86
  59. data/examples/newmessagebox.rb +0 -130
  60. data/examples/newtabbedwindow.rb +0 -100
  61. data/examples/newtesttabp.rb +0 -121
  62. data/examples/qdfilechooser.rb +0 -68
  63. data/examples/rfe.rb +0 -1195
  64. data/examples/rfe_renderer.rb +0 -121
  65. data/examples/sqlc.rb +0 -454
  66. data/examples/sqlm.rb +0 -437
  67. data/examples/sqlt.rb +0 -408
  68. data/examples/status.txt +0 -68
  69. data/examples/table1.rb +0 -24
  70. data/examples/term2.rb +0 -84
  71. data/examples/test1.rb +0 -239
  72. data/examples/test2.rb +0 -674
  73. data/examples/testapp.rb +0 -44
  74. data/examples/testapp2.rb +0 -58
  75. data/examples/testchars.rb +0 -137
  76. data/examples/testcombo.rb +0 -91
  77. data/examples/testkeypress.rb +0 -66
  78. data/examples/testlistbox.rb +0 -113
  79. data/examples/testmenu.rb +0 -101
  80. data/examples/testmulticomp.rb +0 -70
  81. data/examples/testmulticontainer.rb +0 -94
  82. data/examples/testmultispl.rb +0 -199
  83. data/examples/testree.rb +0 -106
  84. data/examples/testtable.rb +0 -263
  85. data/examples/testtabp.rb +0 -107
  86. data/examples/testtodo.rb +0 -584
  87. data/examples/testvimsplit.rb +0 -112
  88. data/examples/testwsshortcuts.rb +0 -64
  89. data/examples/testwsshortcuts2.rb +0 -126
  90. data/examples/todo.db +0 -0
  91. data/examples/todo.yml +0 -191
  92. data/examples/viewtodo.rb +0 -574
  93. data/lib/rbcurse/action.rb +0 -40
  94. data/lib/rbcurse/app.rb +0 -1374
  95. data/lib/rbcurse/applicationheader.rb +0 -102
  96. data/lib/rbcurse/celleditor.rb +0 -112
  97. data/lib/rbcurse/checkboxcellrenderer.rb +0 -57
  98. data/lib/rbcurse/colormap.rb +0 -159
  99. data/lib/rbcurse/comboboxcellrenderer.rb +0 -30
  100. data/lib/rbcurse/common/ansiparser.rb +0 -117
  101. data/lib/rbcurse/common/appmethods.rb +0 -112
  102. data/lib/rbcurse/common/basestack.rb +0 -407
  103. data/lib/rbcurse/common/bordertitle.rb +0 -41
  104. data/lib/rbcurse/common/chunk.rb +0 -177
  105. data/lib/rbcurse/common/colorparser.rb +0 -71
  106. data/lib/rbcurse/common/keydefs.rb +0 -30
  107. data/lib/rbcurse/common/widgetshortcuts.rb +0 -302
  108. data/lib/rbcurse/defaultlistselectionmodel.rb +0 -79
  109. data/lib/rbcurse/deprecated/README.markdown +0 -12
  110. data/lib/rbcurse/deprecated/rscrollpane.rb +0 -512
  111. data/lib/rbcurse/deprecated/rsplitpane.rb +0 -894
  112. data/lib/rbcurse/deprecated/rsplitpane2.rb +0 -1009
  113. data/lib/rbcurse/deprecated/rviewport.rb +0 -204
  114. data/lib/rbcurse/experimental/README.markdown +0 -14
  115. data/lib/rbcurse/experimental/resultsettextview.rb +0 -585
  116. data/lib/rbcurse/experimental/stackflow.rb +0 -478
  117. data/lib/rbcurse/extras/bottomline.rb +0 -1850
  118. data/lib/rbcurse/extras/box.rb +0 -58
  119. data/lib/rbcurse/extras/directorylist.rb +0 -467
  120. data/lib/rbcurse/extras/directorytree.rb +0 -69
  121. data/lib/rbcurse/extras/divider.rb +0 -310
  122. data/lib/rbcurse/extras/focusmanager.rb +0 -31
  123. data/lib/rbcurse/extras/horizlist.rb +0 -203
  124. data/lib/rbcurse/extras/listselectable.rb +0 -264
  125. data/lib/rbcurse/extras/masterdetail.rb +0 -166
  126. data/lib/rbcurse/extras/menutree.rb +0 -63
  127. data/lib/rbcurse/extras/multiform.rb +0 -330
  128. data/lib/rbcurse/extras/multilinelabel.rb +0 -142
  129. data/lib/rbcurse/extras/newmessagebox.rb +0 -328
  130. data/lib/rbcurse/extras/newtabbedpane.rb +0 -612
  131. data/lib/rbcurse/extras/newtabbedwindow.rb +0 -68
  132. data/lib/rbcurse/extras/padreader.rb +0 -189
  133. data/lib/rbcurse/extras/rcomboedit.rb +0 -256
  134. data/lib/rbcurse/extras/resultsetbrowser.rb +0 -281
  135. data/lib/rbcurse/extras/rlink.rb +0 -27
  136. data/lib/rbcurse/extras/rmenulink.rb +0 -21
  137. data/lib/rbcurse/extras/scrollbar.rb +0 -143
  138. data/lib/rbcurse/extras/statusline.rb +0 -94
  139. data/lib/rbcurse/extras/stdscrwindow.rb +0 -309
  140. data/lib/rbcurse/extras/tableextended.rb +0 -40
  141. data/lib/rbcurse/extras/tabular.rb +0 -264
  142. data/lib/rbcurse/extras/tabularwidget.rb +0 -1150
  143. data/lib/rbcurse/extras/textpad.rb +0 -516
  144. data/lib/rbcurse/extras/viewer.rb +0 -136
  145. data/lib/rbcurse/io.rb +0 -850
  146. data/lib/rbcurse/keylabelprinter.rb +0 -178
  147. data/lib/rbcurse/listcellrenderer.rb +0 -140
  148. data/lib/rbcurse/listeditable.rb +0 -310
  149. data/lib/rbcurse/listkeys.rb +0 -37
  150. data/lib/rbcurse/listscrollable.rb +0 -564
  151. data/lib/rbcurse/listselectable.rb +0 -142
  152. data/lib/rbcurse/mapper.rb +0 -130
  153. data/lib/rbcurse/orderedhash.rb +0 -77
  154. data/lib/rbcurse/ractionevent.rb +0 -67
  155. data/lib/rbcurse/rbasiclistbox.rb +0 -768
  156. data/lib/rbcurse/rchangeevent.rb +0 -27
  157. data/lib/rbcurse/rcombo.rb +0 -238
  158. data/lib/rbcurse/rcommandwindow.rb +0 -587
  159. data/lib/rbcurse/rcontainer.rb +0 -415
  160. data/lib/rbcurse/rdialogs.rb +0 -451
  161. data/lib/rbcurse/rinputdataevent.rb +0 -47
  162. data/lib/rbcurse/rlistbox.rb +0 -1196
  163. data/lib/rbcurse/rmenu.rb +0 -939
  164. data/lib/rbcurse/rmessagebox.rb +0 -348
  165. data/lib/rbcurse/rmulticontainer.rb +0 -304
  166. data/lib/rbcurse/rmultisplit.rb +0 -722
  167. data/lib/rbcurse/rmultitextview.rb +0 -306
  168. data/lib/rbcurse/rpopupmenu.rb +0 -755
  169. data/lib/rbcurse/rprogress.rb +0 -118
  170. data/lib/rbcurse/rscrollform.rb +0 -418
  171. data/lib/rbcurse/rtabbedpane.rb +0 -1158
  172. data/lib/rbcurse/rtabbedwindow.rb +0 -167
  173. data/lib/rbcurse/rtable.rb +0 -1718
  174. data/lib/rbcurse/rtextarea.rb +0 -920
  175. data/lib/rbcurse/rtextview.rb +0 -761
  176. data/lib/rbcurse/rtree.rb +0 -780
  177. data/lib/rbcurse/rvimsplit.rb +0 -763
  178. data/lib/rbcurse/rwidget.rb +0 -2915
  179. data/lib/rbcurse/scrollable.rb +0 -301
  180. data/lib/rbcurse/table/tablecellrenderer.rb +0 -86
  181. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -98
  182. data/lib/rbcurse/tree/treecellrenderer.rb +0 -150
  183. data/lib/rbcurse/tree/treemodel.rb +0 -428
  184. data/lib/rbcurse/undomanager.rb +0 -188
  185. data/lib/rbcurse/vieditable.rb +0 -144
  186. data/lib/ver/keyboard.rb +0 -150
  187. data/lib/ver/keyboard2.rb +0 -170
  188. data/lib/ver/ncurses.rb +0 -218
  189. data/lib/ver/panel.rb +0 -162
  190. data/lib/ver/rpad.rb +0 -375
  191. data/lib/ver/window.rb +0 -882
  192. data/test/test_rbcurse.rb +0 -0
@@ -1,47 +0,0 @@
1
- =begin
2
- * Name: InputDataEvent
3
- * Description: Event created when data modified in Field or TextEdit
4
- * Author: rkumar (arunachalesha)
5
-
6
- --------
7
- * Date: 2008-12-24 17:27
8
- * License:
9
- Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
-
11
- NOTE: this is how we used to write code in the Java days. Anyone reading this source,
12
- this is NOT how to code in rubyland. Please see this link, for how to code such as class:
13
- http://blog.grayproductions.net/articles/all_about_struct
14
-
15
- =end
16
-
17
- # Event created when data modified in Field or TextEdit
18
- # 2008-12-24 17:54
19
- module RubyCurses
20
- class InputDataEvent
21
- attr_accessor :index0, :index1, :source, :type, :row, :text
22
- def initialize index0, index1, source, type, row, text
23
- @index0 = index0
24
- @index1 = index1
25
- @source = source
26
- @type = type
27
- @row = row
28
- @text = text
29
- end
30
- # until now to_s was returning inspect, but to make it easy for users let us return the value
31
- # they most expect which is the text that was changed
32
- def to_s
33
- inspect
34
- end
35
- def inspect
36
- ## now that textarea.to_s prints content we shouldn pass it here.
37
- #"#{@type.to_s}, #{@source}, ind0:#{@index0}, ind1:#{@index1}, row:#{@row}, text:#{@text}"
38
- "#{@type.to_s}, ind0:#{@index0}, ind1:#{@index1}, row:#{@row}, text:#{@text}"
39
- end
40
- # this is so that earlier applications were getting source in the block, not an event. they
41
- # were doing a fld.getvalue, so we must keep those apps running
42
- # @since 1.2.0 added 2010-09-11 12:25
43
- def getvalue
44
- @source.getvalue
45
- end
46
- end
47
- end
@@ -1,1196 +0,0 @@
1
- =begin
2
- * Name: rlistbox: editable scrollable lists
3
- * Description
4
- * Author: rkumar (arunachalesha)
5
- * Date: 2008-11-19 12:49
6
- * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
7
- * This file started on 2009-01-13 22:18 (broken off rwidgets.rb)
8
- NOTE: listbox now traps RETURN/ENTER/13 so if you are trapping it, please use bind :PRESS
9
- TODO
10
- Perhaps keep printed data created by convert_value_to_text cached, and used for searching
11
- cursor movement and other functions.
12
- =end
13
- require 'rbcurse'
14
- require 'rbcurse/listcellrenderer'
15
- require 'rbcurse/listkeys'
16
- require 'forwardable'
17
-
18
-
19
- #include Ncurses # FFI 2011-09-8
20
- module RubyCurses
21
- extend self
22
- ##
23
- # When an event is fired by Listbox, contents are changed, then this object will be passed
24
- # to trigger
25
- # shamelessly plugged from a legacy language best unnamed
26
- # type is CONTENTS_CHANGED, INTERVAL_ADDED, INTERVAL_REMOVED
27
- class ListDataEvent
28
- attr_accessor :index0, :index1, :source, :type
29
- def initialize index0, index1, source, type
30
- @index0 = index0
31
- @index1 = index1
32
- @source = source
33
- @type = type
34
- end
35
- def to_s
36
- "#{@type.to_s}, #{@source}, #{@index0}, #{@index1}"
37
- end
38
- def inspect
39
- "#{@type.to_s}, #{@source}, #{@index0}, #{@index1}"
40
- end
41
- end
42
- # http://www.java2s.com/Code/JavaAPI/javax.swing.event/ListDataEventCONTENTSCHANGED.htm
43
- # should we extend array of will that open us to misuse
44
- class ListDataModel
45
- include Enumerable
46
- include RubyCurses::EventHandler
47
- attr_accessor :selected_index
48
- attr_reader :last_regex # should i really keep here as public or maintain in listbox
49
-
50
- def initialize anarray=[]
51
- @list = anarray.dup
52
- @_events = [:LIST_DATA_EVENT, :ENTER_ROW]
53
- end
54
- # changd on 2009-01-14 12:28 based on ..
55
- # http://www.ruby-forum.com/topic/175637#769030
56
- def each(&blk)
57
- @list.each(&blk)
58
- end
59
- # not sure how to do this XXX removed on 2009-01-14 12:28
60
- #def <=>(other)
61
- # @list <=> other
62
- #end
63
- def index obj
64
- @list.index(obj)
65
- end
66
- def length ; @list.length; end
67
- alias :size :length
68
-
69
- def insert off0, *data
70
- @list.insert off0, *data
71
- lde = ListDataEvent.new(off0, off0+data.length-1, self, :INTERVAL_ADDED)
72
- fire_handler :LIST_DATA_EVENT, lde
73
- end
74
- def append data
75
- @list << data
76
- lde = ListDataEvent.new(@list.length-1, @list.length-1, self, :INTERVAL_ADDED)
77
- fire_handler :LIST_DATA_EVENT, lde
78
- end
79
- def update off0, data
80
- @list[off0] = data
81
- lde = ListDataEvent.new(off0, off0, self, :CONTENTS_CHANGED)
82
- fire_handler :LIST_DATA_EVENT, lde
83
- end
84
- def []=(off0, data)
85
- update off0, data
86
- end
87
- def [](off0)
88
- @list[off0]
89
- end
90
- def delete_at off0
91
- ret=@list.delete_at off0
92
- lde = ListDataEvent.new(off0, off0, self, :INTERVAL_REMOVED)
93
- fire_handler :LIST_DATA_EVENT, lde
94
- return ret
95
- end
96
- def remove_all
97
- return if @list.nil? || @list.empty? # 2010-09-21 13:25
98
- lde = ListDataEvent.new(0, @list.size, self, :INTERVAL_REMOVED)
99
- @list = []
100
- @current_index = 0
101
- fire_handler :LIST_DATA_EVENT, lde
102
- end
103
- def delete obj
104
- off0 = @list.index obj
105
- return nil if off0.nil?
106
- ret=@list.delete_at off0
107
- lde = ListDataEvent.new(off0, off0, self, :INTERVAL_REMOVED)
108
- fire_handler :LIST_DATA_EVENT, lde
109
- return ret
110
- end
111
- def include?(obj)
112
- return @list.include?(obj)
113
- end
114
- # returns a `dup()` of the list
115
- def values
116
- @list.dup
117
- end
118
- # why do we have this here in data, we should remove this
119
- # @deprecated this was just eye candy for some demo
120
- def on_enter_row object
121
- $log.debug " XXX on_enter_row of list_data"
122
- fire_handler :ENTER_ROW, object
123
- end
124
- # ##
125
- # added 2009-01-14 01:00
126
- # searches between given range of rows (def 0 and end)
127
- # returns row index of first match of given regex (or nil if not found)
128
- def find_match regex, ix0=0, ix1=length()
129
- $log.debug " find_match got #{regex} #{ix0} #{ix1}"
130
- @last_regex = regex
131
- @search_start_ix = ix0
132
- @search_end_ix = ix1
133
- #@search_found_ix = nil
134
- @list.each_with_index do |row, ix|
135
- next if ix < ix0
136
- break if ix > ix1
137
- if !row.match(regex).nil?
138
- @search_found_ix = ix
139
- return ix
140
- end
141
- end
142
- return nil
143
- end
144
- ##
145
- # continues previous search
146
- def find_next
147
- raise "No previous search" if @last_regex.nil?
148
- start = @search_found_ix && @search_found_ix+1 || 0
149
- return find_match @last_regex, start, @search_end_ix
150
- end
151
- ##
152
- # find backwards, list_data_model
153
- # Using this to start a search or continue search
154
- def find_prev regex=@last_regex, start = @search_found_ix
155
- raise "No previous search" if regex.nil? # @last_regex.nil?
156
- $log.debug " find_prev #{@search_found_ix} : #{@current_index}"
157
- start -= 1 unless start == 0
158
- @last_regex = regex
159
- @search_start_ix = start
160
- start.downto(0) do |ix|
161
- row = @list[ix]
162
- if !row.match(regex).nil?
163
- @search_found_ix = ix
164
- return ix
165
- end
166
- end
167
- return nil
168
- #return find_match @last_regex, start, @search_end_ix
169
- end
170
- ##
171
- # added 2010-05-23 12:10 for listeditable
172
- def slice!(line, howmany)
173
- ret = @list.slice!(line, howmany)
174
- lde = ListDataEvent.new(line, line+howmany-1, self, :INTERVAL_REMOVED)
175
- fire_handler :LIST_DATA_EVENT, lde
176
- return ret
177
- end
178
-
179
- alias :to_array :values
180
- end # class ListDataModel
181
- ##
182
- # scrollable, selectable list of items
183
- # TODO Add events for item add/remove and selection change
184
- # added event LIST_COMBO_SELECT fired whenever a select/deselect is done.
185
- # - I do not know how this works in Tk so only the name is copied..
186
- # - @selected contains indices of selected objects.
187
- # - currently the first argument of event is row (the row selected/deselected). Should it
188
- # be the object.
189
- # - this event could change when range selection is allowed.
190
- #
191
-
192
- ##
193
- # TODO CAN WE MOVE THIS OUT TO ANOTHER FILE as confusing me
194
- # pops up a list of values for selection
195
- # 2008-12-10
196
- class PopupList
197
- include RubyCurses::EventHandler
198
- dsl_accessor :title
199
- dsl_accessor :row, :col, :height, :width
200
- dsl_accessor :layout
201
- attr_reader :config
202
- attr_reader :selected_index # button index selected by user
203
- attr_reader :window # required for keyboard
204
- dsl_accessor :list_selection_mode # true or false allow multiple selection
205
- dsl_accessor :relative_to # a widget, if given row and col are relative to widgets windows
206
- # layout
207
- dsl_accessor :max_visible_items # how many to display
208
- dsl_accessor :list_config # hash with values for the list to use
209
- dsl_accessor :valign
210
- attr_reader :listbox
211
-
212
- def initialize aconfig={}, &block
213
- @config = aconfig
214
- @selected_index = -1
215
- @list_config ||= {}
216
- @config.each_pair { |k,v| instance_variable_set("@#{k}",v) }
217
- instance_eval &block if block_given?
218
- @list_config.each_pair { |k,v| instance_variable_set("@#{k}",v) }
219
- @height ||= [@max_visible_items || 10, @list.length].min
220
- $log.debug " POPUP XXX #{@max_visible_items} ll:#{@list.length} h:#{@height}"
221
- # get widgets absolute coords
222
- if @relative_to
223
- layout = @relative_to.form.window.layout
224
- @row = @row + layout[:top]
225
- @col = @col + layout[:left]
226
- end
227
- if !@valign.nil?
228
- case @valign.to_sym
229
- when :BELOW
230
- @row += 1
231
- when :ABOVE
232
- @row -= @height+1
233
- @row = 0 if @row < 0
234
- when :CENTER
235
- @row -= @height/2
236
- @row = 0 if @row < 0
237
- else
238
- end
239
- end
240
-
241
- layout(1+height, @width+4, @row, @col) # changed 2 to 1, 2008-12-17 13:48
242
- @window = VER::Window.new(@layout)
243
- @form = RubyCurses::Form.new @window
244
- @window.bkgd(Ncurses.COLOR_PAIR($reversecolor));
245
- @window.wrefresh
246
- #@panel = @window.panel # useless line ?
247
- Ncurses::Panel.update_panels
248
- print_input # creates the listbox
249
- @form.repaint
250
- @window.wrefresh
251
- handle_keys
252
- end
253
- # class popup
254
- def list alist=nil
255
- return @list if alist.nil?
256
- @list = ListDataModel.new(alist)
257
- @repaint_required = true
258
- # will we need this ? listbox made each time so data should be fresh
259
- #@list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
260
- end
261
- # class popup
262
- def list_data_model ldm
263
- raise "Expecting list_data_model" unless ldm.is_a? RubyCurses::ListDataModel
264
- @list = ldm
265
- # will we need this ? listbox made each time so data should be fresh
266
- #@list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
267
- end
268
- ##
269
- def input_value
270
- #return @listbox.getvalue if !@listbox.nil?
271
- return @listbox.focussed_index if !@listbox.nil?
272
- end
273
- ## popuplist
274
- def stopping?
275
- @stop
276
- end
277
- ## popuplist
278
- def handle_keys
279
- begin
280
- while((ch = @window.getchar()) != 999 )
281
- case ch
282
- when -1
283
- next
284
- else
285
- press ch
286
- break if @stop
287
- end
288
- end
289
- ensure
290
- destroy
291
- end
292
- return 0 #@selected_index
293
- end
294
- ##
295
- # TODO get next match for key
296
- def press ch
297
- $log.debug "popup handle_keys : #{ch}" if ch != -1
298
- case ch
299
- when -1
300
- return
301
- when KEY_F1, 27, ?\C-q # 27/ESC does not come here since gobbled by keyboard.rb
302
- @stop = true
303
- return
304
- when KEY_ENTER, 10, 13
305
- # if you press ENTER without selecting, it won't come here
306
- # it will fire button OK's fire, if that's the default button
307
-
308
- # returns an array of indices if multiple selection
309
- if @listbox.selection_mode == :multiple
310
- fire_handler :PRESS, @listbox
311
- else
312
- fire_handler :PRESS, @listbox.focussed_index
313
- end
314
- # since Listbox is handling enter, COMBO_SELECT will not be fired
315
- # $log.debug "popup ENTER : #{field.name}" if !field.nil?
316
- @stop = true
317
- return
318
- when KEY_TAB
319
- @form.select_next_field
320
- else
321
- # fields must return unhandled else we will miss hotkeys.
322
- # On messageboxes, often if no edit field, then O and C are hot.
323
- field = @form.get_current_field
324
- handled = field.handle_key ch
325
-
326
- if handled == :UNHANDLED
327
- @stop = true
328
- return
329
- end
330
- end
331
- @form.repaint
332
- Ncurses::Panel.update_panels();
333
- Ncurses.doupdate();
334
- @window.wrefresh
335
- end
336
- def print_input
337
- r = c = 0
338
- width = @layout[:width]
339
- #$log.debug " print_input POPUP ht:#{@height} lh:#{@layout[:height]} "
340
- height = @layout[:height]
341
- #height = @height # 2010-01-06 12:52 why was this overriding previous line. its one less than layout
342
- # i am now using layout height since it gives a closer size to whats asked for.
343
- parent = @relative_to
344
- defaultvalue = @default_value || ""
345
- list = @list
346
- selection_mode = @list_selection_mode
347
- default_values = @default_values
348
- @list_config['color'] ||= 'black'
349
- @list_config['bgcolor'] ||= 'yellow'
350
- @listbox = RubyCurses::Listbox.new @form, @list_config do
351
- name "input"
352
- row r
353
- col c
354
- # attr 'reverse'
355
- width width
356
- height height
357
- list_data_model list
358
- # ?? XXX display_length 30
359
- # set_buffer defaultvalue
360
- selection_mode selection_mode
361
- default_values default_values
362
- is_popup true
363
- #add_observer parent
364
- end
365
- end
366
- # may need to be upgraded to new one XXX FIXME
367
- def configure(*val , &block)
368
- case val.size
369
- when 1
370
- return @config[val[0]]
371
- when 2
372
- @config[val[0]] = val[1]
373
- instance_variable_set("@#{val[0]}", val[1])
374
- end
375
- instance_eval &block if block_given?
376
- end
377
- def cget param
378
- @config[param]
379
- end
380
-
381
- def layout(height=0, width=0, top=0, left=0)
382
- @layout = { :height => height, :width => width, :top => top, :left => left }
383
- end
384
- def destroy
385
- @window.destroy if !@window.nil?
386
- end
387
- end # class PopupList
388
- ##
389
- # A control for displaying a list of data or values.
390
- # The list will be editable if @cell_editing_allowed
391
- # is set to true when creating. By default, multiple selection is allowed, but may be set to :single.
392
- # TODO: were we not going to force creation of datamodel and listener on startup by putting a blank
393
- # :list in config, if no list or list_variable or model is there ?
394
- # Or at end of constructor check, if no listdatamodel then create default.
395
- # TODO : perhaps when datamodel created, attach listener to it, so we can fire to callers when
396
- # they want to be informed of changes. As we did with selection listeners.
397
- #
398
- class Listbox < Widget
399
-
400
- require 'rbcurse/listscrollable'
401
- require 'rbcurse/listselectable'
402
- require 'rbcurse/defaultlistselectionmodel'
403
- require 'rbcurse/celleditor'
404
- include ListScrollable
405
- include ListSelectable
406
- include RubyCurses::ListKeys
407
- extend Forwardable
408
- dsl_accessor :height
409
- dsl_accessor :title
410
- dsl_property :title_attrib # bold, reverse, normal
411
- # dsl_accessor :list # the array of data to be sent by user
412
- attr_reader :toprow
413
- # attr_reader :prow
414
- # attr_reader :winrow
415
- # dsl_accessor :selection_mode # allow multiple select or not
416
- # dsl_accessor :list_variable # a variable values are shown from this
417
- dsl_accessor :default_values # array of default values
418
- dsl_accessor :is_popup # if it is in a popup and single select, selection closes
419
- attr_accessor :current_index
420
- #dsl_accessor :cell_renderer
421
- dsl_accessor :selected_color, :selected_bgcolor, :selected_attr
422
- dsl_accessor :max_visible_items # how many to display 2009-01-11 16:15
423
- dsl_accessor :cell_editing_allowed
424
- dsl_property :show_selector
425
- dsl_property :row_selected_symbol # 2009-01-12 12:01 changed from selector to selected
426
- dsl_property :row_unselected_symbol # added 2009-01-12 12:00
427
- dsl_property :left_margin
428
- # please set these in he constructor block. Settin them later will have no effect
429
- # since i would have bound them to actions
430
- dsl_accessor :KEY_ROW_SELECTOR # editable lists may want to use 0 or some other key
431
- dsl_accessor :KEY_GOTO_TOP # this is going to go
432
- dsl_accessor :KEY_GOTO_BOTTOM # this is going to go
433
- dsl_accessor :KEY_CLEAR_SELECTION # this is going to go
434
- dsl_accessor :KEY_NEXT_SELECTION # this is going to go
435
- dsl_accessor :KEY_PREV_SELECTION # this is going to go
436
- dsl_accessor :valign # 2009-01-17 18:32 vertical alignment used in combos
437
- dsl_accessor :justify # 2010-09-27 12:41 used by renderer
438
- attr_accessor :one_key_selection # will pressing a single key select or not
439
- dsl_accessor :border_attrib, :border_color #
440
- dsl_accessor :sanitization_required
441
- dsl_accessor :suppress_borders #to_print_borders
442
-
443
-
444
- def initialize form, config={}, &block
445
- @focusable = true
446
- @editable = false
447
- @sanitization_required = true
448
- @row = 0
449
- @col = 0
450
- # data of listbox this is not an array, its a pointer to the listdatamodel
451
- @list = nil
452
- # any special attribs such as status to be printed in col1, or color (selection)
453
- @list_attribs = {}
454
- @suppress_borders = false
455
- @row_offset = @col_offset = 1 # for borders
456
- super
457
- @_events.push(*[:ENTER_ROW, :LEAVE_ROW, :LIST_SELECTION_EVENT, :PRESS])
458
- @current_index ||= 0
459
- @selection_mode ||= :multiple # default is multiple, anything else given becomes single
460
- @win = @graphic # 2010-01-04 12:36 BUFFERED replace form.window with graphic
461
- # moving down to repaint so that scrollpane can set should_buffered
462
- # added 2010-02-17 23:05 RFED16 so we don't need a form.
463
- @win_left = 0
464
- @win_top = 0
465
-
466
- # next 2 lines carry a redundancy
467
- select_default_values
468
- # when the combo box has a certain row in focus, the popup should have the same row in focus
469
-
470
- install_keys
471
- init_vars
472
- install_list_keys
473
- # OMG What about people whove installed custom renders such as rfe.rb 2011-10-15
474
- #bind(:PROPERTY_CHANGE){|e| @cell_renderer = nil } # will be recreated if anything changes 2011-09-28 V1.3.1
475
- bind(:PROPERTY_CHANGE){|e|
476
- # I can't delete the cell renderer, but this may not have full effect if one color is passed.
477
- if @cell_renderer.respond_to? e.property_name
478
- @cell_renderer.send(e.property_name.to_sym, e.newvalue)
479
- end
480
- } # will be recreated if anything changes 2011-09-28 V1.3.1
481
-
482
- if @list && !@list.selected_index.nil?
483
- set_focus_on @list.selected_index # the new version
484
- end
485
- end
486
- # this is called several times, from constructor
487
- # and when list data changed, so only put relevant resets here.
488
- # why can't current_index be set to 0 here
489
- def init_vars
490
- @repaint_required = true
491
- @toprow = @pcol = 0
492
-
493
- @row_offset = @col_offset = 0 if @suppress_borders
494
- if @show_selector
495
- @row_selected_symbol ||= '>'
496
- @row_unselected_symbol ||= ' '
497
- @left_margin ||= @row_selected_symbol.length
498
- end
499
- @left_margin ||= 0
500
- @one_key_selection = true if @one_key_selection.nil?
501
- # we reduce internal_width from width while printing
502
- @internal_width = 2 # taking into account borders accounting for 2 cols
503
- @internal_width = 0 if @suppress_borders # should it be 0 ???
504
-
505
- end
506
- def map_keys
507
- return if @keys_mapped
508
- bind_key(?f){ ask_selection_for_char() }
509
- bind_key(?\M-v){ @one_key_selection = false }
510
- bind_key(?j){ next_row() }
511
- bind_key(?k){ previous_row() }
512
- bind_key(?G){ goto_bottom() }
513
- bind_key([?g,?g]){ goto_top() }
514
- bind_key(?/){ ask_search() }
515
- bind_key(?n){ find_more() }
516
- #bind_key(32){ toggle_row_selection() } # some guys may want another selector
517
- if @cell_editing_allowed && @KEY_ROW_SELECTOR == 32
518
- @KEY_ROW_SELECTOR = 0 # Ctrl-Space
519
- end
520
- bind_key(@KEY_ROW_SELECTOR){ toggle_row_selection() }
521
- bind_key(10){ fire_action_event }
522
- bind_key(13){ fire_action_event }
523
- @keys_mapped = true
524
- end
525
-
526
- ##
527
- # getter and setter for selection_mode
528
- # Must be called after creating model, so no duplicate. Since one may set in model directly.
529
- def selection_mode(*val)
530
- #raise "ListSelectionModel not yet created!" if @list_selection_model.nil?
531
-
532
- if val.empty?
533
- if @list_selection_model
534
- return @list_selection_model.selection_mode
535
- else
536
- return @tmp_selection_mode
537
- end
538
- else
539
- if @list_selection_model.nil?
540
- @tmp_selection_mode = val[0]
541
- else
542
- @list_selection_model.selection_mode = val[0].to_sym
543
- end
544
- end
545
- end
546
- def row_count
547
- return 0 if @list.nil?
548
- @list.length
549
- end
550
- # added 2009-01-07 13:05 so new scrollable can use
551
- def scrollatrow
552
- if @suppress_borders
553
- return @height - 1
554
- else
555
- return @height - 3
556
- end
557
- end
558
- # provide data to List in the form of an Array or Variable or
559
- # ListDataModel. This will create a default ListSelectionModel.
560
- #
561
- # CHANGE as on 2010-09-21 12:53:
562
- # If explicit nil passed then dummy datamodel and selection model created
563
- # From now on, constructor will call this, so this can always
564
- # happen.
565
- #
566
- # NOTE: sometimes this can be added much after its painted.
567
- # Do not expect this to be called from constructor, although that
568
- # is the usual case. it can be dependent on some other list or tree.
569
- # @param [Array, Variable, ListDataModel] data to populate list with
570
- # @return [ListDataModel] just created or assigned
571
-
572
- def list *val
573
- return @list if val.empty?
574
- clear_selection if @list # clear previous selections if any
575
- @default_values = nil if @list # clear previous selections if any
576
- alist = val[0]
577
- case alist
578
- when Array
579
- if @list
580
- @list.remove_all
581
- @list.insert 0, *alist
582
- @current_index = 0
583
- else
584
- @list = RubyCurses::ListDataModel.new(alist)
585
- end
586
- when NilClass
587
- if @list
588
- @list.remove_all
589
- else
590
- @list = RubyCurses::ListDataModel.new(alist)
591
- end
592
- when Variable
593
- @list = RubyCurses::ListDataModel.new(alist.value)
594
- when RubyCurses::ListDataModel
595
- @list = alist
596
- else
597
- raise ArgumentError, "Listbox list(): do not know how to handle #{alist.class} "
598
- end
599
- # added on 2009-01-13 23:19 since updates are not automatic now
600
- @list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
601
- create_default_list_selection_model
602
- @list_selection_model.selection_mode = @tmp_selection_mode if @tmp_selection_mode
603
- @repaint_required = true
604
- @list
605
- end
606
- # populate using a Variable which should contain a list
607
- # NOTE: This explicilty overwrites any existing datamodel such as the
608
- # default one. You may lose any events you have bound to the listbox
609
- # prior to this call.
610
- def list_variable alist=nil
611
- return @list if alist.nil?
612
- @list = RubyCurses::ListDataModel.new(alist.value)
613
- # added on 2009-01-13 23:19 since updates are not automatic now
614
- @list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
615
- create_default_list_selection_model
616
- end
617
- # populate using a custom data model
618
- # NOTE: This explicilty overwrites any existing datamodel such as the
619
- # default one. You may lose any events you have bound to the listbox
620
- # prior to this call.
621
-
622
- def list_data_model ldm=nil
623
- return @list if ldm.nil?
624
- raise "Expecting list_data_model" unless ldm.is_a? RubyCurses::ListDataModel
625
- @list = ldm
626
- # added on 2009-01-13 23:19 since updates are not automatic now
627
- @list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
628
- create_default_list_selection_model
629
- end
630
- # create a default list selection model and set it
631
- # NOTE: I am now checking if one is not already created, since
632
- # a second creation would wipe out any listeners on it.
633
- # @see ListSelectable
634
- # @see DefaultListSelectionModel
635
- def create_default_list_selection_model
636
- if @list_selection_model.nil?
637
- list_selection_model DefaultListSelectionModel.new(self)
638
- end
639
- end
640
- # added 2010-09-15 00:11 to make life easier
641
- def_delegators :@list, :insert, :remove_all, :delete_at, :include?, :each, :values, :size
642
- # get element at
643
- # @param [Fixnum] index for element
644
- # @return [Object] element
645
- # @since 1.2.0 2010-09-06 14:33 making life easier for others.
646
- def [](off0)
647
- @list[off0]
648
- end
649
- # return object under cursor
650
- # Note: this should not be confused with selected row/s. User may not have selected this.
651
- # This is only useful since in some demos we like to change a status bar as a user scrolls down
652
- # @since 1.2.0 2010-09-06 14:33 making life easier for others.
653
- def current_value
654
- @list[@current_index]
655
- end
656
- # avoid using "row", i'd rather stick with "index" and "value".
657
- alias :current_row :current_value
658
- alias :text :current_value # thanks to shoes, not sure how this will impact since widget has text.
659
-
660
- # XXX can this not be done at repaint
661
- def select_default_values
662
- return if @default_values.nil?
663
- @default_values.each do |val|
664
- row = @list.index val
665
- add_row_selection_interval row, row unless row.nil?
666
- end
667
- end
668
- def print_borders
669
- width = @width
670
- height = @height-1 # 2010-01-04 15:30 BUFFERED HEIGHT
671
- window = @graphic # 2010-01-04 12:37 BUFFERED
672
- startcol = @col
673
- startrow = @row
674
- @color_pair = get_color($datacolor)
675
- # bordercolor = @border_color || $datacolor # changed 2011 dts
676
- bordercolor = @border_color || @color_pair
677
- borderatt = @border_attrib || Ncurses::A_NORMAL
678
-
679
- #$log.debug "rlistb #{name}: window.print_border #{startrow}, #{startcol} , h:#{height}, w:#{width} , @color_pair, @attr "
680
- window.print_border startrow, startcol, height, width, bordercolor, borderatt
681
- print_title
682
- end
683
- def print_title
684
- @color_pair ||= get_color($datacolor)
685
- # check title.length and truncate if exceeds width
686
- return unless @title
687
- _title = @title
688
- if @title.length > @width - 2
689
- _title = @title[0..@width-2]
690
- end
691
- @graphic.printstring( @row, @col+(@width-_title.length)/2, _title, @color_pair, @title_attrib) unless @title.nil?
692
- end
693
- ### START FOR scrollable ###
694
- def get_content
695
- #@list 2008-12-01 23:13
696
- # NOTE: we never stored the listvariable, so its redundant, we used its value to set list
697
- @list_variable && @list_variable.value || @list
698
- end
699
- def get_window
700
- @graphic # 2010-01-04 12:37 BUFFERED
701
- end
702
- ### END FOR scrollable ###
703
- # override widgets text
704
- # returns indices of selected rows
705
- def getvalue
706
- selected_rows
707
- end
708
- # Listbox
709
- def handle_key(ch)
710
- map_keys unless @keys_mapped
711
- @current_index ||= 0
712
- @toprow ||= 0
713
- h = scrollatrow()
714
- rc = row_count
715
- $log.debug " listbox got ch #{ch}"
716
- #$log.debug " when kps #{@KEY_PREV_SELECTION} "
717
- case ch
718
- when 10,13, KEY_ENTER
719
- # this means you cannot just bind_key 10 or 13 like we once did
720
- fire_action_event # trying out REMOVE 2011-09-16 FFI
721
- $log.debug " 333 listbox catching 10,13 fire_action_event "
722
- return 0
723
- when KEY_UP # show previous value
724
- return previous_row
725
- when KEY_DOWN # show previous value
726
- return next_row
727
- when @KEY_ROW_SELECTOR # 32
728
- return if is_popup && @selection_mode != :multiple # not allowing select this way since there will be a difference
729
- toggle_row_selection @current_index #, @current_index
730
- @repaint_required = true
731
- when @KEY_SCROLL_FORWARD # ?\C-n
732
- scroll_forward
733
- when @KEY_SCROLL_BACKWARD # ?\C-p
734
- scroll_backward
735
- when @KEY_GOTO_TOP # 48, ?\C-[
736
- # please note that C-[ gives 27, same as esc so will respond after ages
737
- goto_top
738
- when @KEY_GOTO_BOTTOM # ?\C-]
739
- goto_bottom
740
- when @KEY_NEXT_SELECTION # ?'
741
- $log.debug "insdie next selection"
742
- @oldrow = @current_index
743
- do_next_selection
744
- bounds_check
745
- when @KEY_PREV_SELECTION # ?"
746
- @oldrow = @current_index
747
- $log.debug "insdie prev selection"
748
- do_prev_selection
749
- bounds_check
750
- when @KEY_CLEAR_SELECTION
751
- clear_selection
752
- @repaint_required = true
753
- when 27, ?\C-c.getbyte(0), ?\C-g.getbyte(0)
754
- editing_canceled @current_index if @cell_editing_allowed
755
- cancel_block # block
756
- $multiplier = 0
757
- when @KEY_ASK_FIND_FORWARD
758
- # ask_search_forward
759
- when @KEY_ASK_FIND_BACKWARD
760
- # ask_search_backward
761
- when @KEY_FIND_NEXT
762
- # find_next
763
- when @KEY_FIND_PREV
764
- # find_prev
765
- when @KEY_ASK_FIND
766
- ask_search
767
- when @KEY_FIND_MORE
768
- find_more
769
- when @KEY_BLOCK_SELECTOR
770
- mark_block #selection
771
- #when ?\C-u.getbyte(0)
772
- # multiplier. Series is 4 16 64
773
- # TESTING @multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
774
- # return 0
775
- when ?\C-c.getbyte(0)
776
- @multiplier = 0
777
- return 0
778
- else
779
- # this has to be fixed, if compo does not handle key it has to continue into next part FIXME
780
- ret = :UNHANDLED # changed on 2009-01-27 13:14 not going into unhandled, tab not released
781
- if @cell_editing_allowed
782
- @repaint_required = true
783
- # hack - on_enter_row should fire when this widget gets focus. first row that is DONE
784
- begin
785
- ret = @cell_editor.component.handle_key(ch)
786
- rescue
787
- on_enter_row @current_index
788
- ret = @cell_editor.component.handle_key(ch)
789
- end
790
- end
791
- if ret == :UNHANDLED
792
- # beware one-key eats up numbers. we'll be wondering why
793
- if @one_key_selection
794
- case ch
795
- #when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0), ?0.getbyte(0)..?9.getbyte(0)
796
- when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0)
797
- # simple motion, key press defines motion
798
- ret = set_selection_for_char ch.chr
799
- else
800
- ret = process_key ch, self
801
- $log.debug "111 listbox #{@current_index} "
802
- @multiplier = 0
803
- return :UNHANDLED if ret == :UNHANDLED
804
- end
805
- else
806
- # no motion on single key, we can freak out like in vim, pref f <char> for set_selection
807
- case ch
808
- when ?0.getbyte(0)..?9.getbyte(0)
809
- $multiplier *= 10 ; $multiplier += (ch-48)
810
- #$log.debug " setting mult to #{$multiplier} in list "
811
- return 0
812
- end
813
- ret = process_key ch, self
814
- return :UNHANDLED if ret == :UNHANDLED
815
- end
816
- end
817
- end
818
- $multiplier = 0
819
- end
820
- # fire handler when user presses ENTER/RETURN
821
- # @since 1.2.0
822
- # listbox now traps ENTER key and fires action event
823
- # to trap please bind :PRESS
824
- #
825
- def fire_action_event
826
- # this does not select the row ???? FIXME ??
827
- require 'rbcurse/ractionevent'
828
- # should have been callled :ACTION_EVENT !!!
829
- fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
830
- end
831
- # get a keystroke from user and go to first item starting with that key
832
- def ask_selection_for_char
833
- ch = @graphic.getch
834
- if ch < 0 || ch > 255
835
- return :UNHANDLED
836
- end
837
- ret = set_selection_for_char ch.chr
838
- end
839
- def ask_search_forward
840
- regex = get_string("Enter regex to search")
841
- ix = @list.find_match regex
842
- if ix.nil?
843
- alert("No matching data for: #{regex}")
844
- else
845
- set_focus_on(ix)
846
- end
847
- end
848
- # gets string to search and calls data models find prev
849
- def ask_search_backward
850
- regex = get_string("Enter regex to search (backward)")
851
- @last_regex = regex
852
- ix = @list.find_prev regex, @current_index
853
- if ix.nil?
854
- alert("No matching data for: #{regex}")
855
- else
856
- set_focus_on(ix)
857
- end
858
- end
859
- # please check for error before proceeding
860
- # @return [Boolean] false if no data
861
- def on_enter
862
- if @list.nil? || @list.size == 0
863
- #Ncurses.beep
864
- get_window.ungetch($current_key) # 2011-10-4 push key back so form can go next
865
- return :UNHANDLED
866
- end
867
- on_enter_row @current_index
868
- set_form_row # added 2009-01-11 23:41
869
- #$log.debug " ONE ENTER LIST #{@current_index}, #{@form.row}"
870
- @repaint_required = true
871
- super
872
- #fire_handler :ENTER, self
873
- true
874
- end
875
- def on_enter_row arow
876
- #$log.debug " Listbox #{self} ENTER_ROW with curr #{@current_index}. row: #{arow} H: #{@handler.keys}"
877
- #fire_handler :ENTER_ROW, arow
878
- fire_handler :ENTER_ROW, self
879
- @list.on_enter_row self ## XXX WHY THIS ???
880
- edit_row_at arow
881
- @repaint_required = true
882
- end
883
- def edit_row_at arow
884
- if @cell_editing_allowed
885
- #$log.debug " cell editor on enter #{arow} val of list[row]: #{@list[arow]}"
886
- editor = cell_editor
887
- prepare_editor editor, arow
888
- end
889
- end
890
- ##
891
- # private
892
- def prepare_editor editor, row
893
- r,c = rowcol
894
- value = @list[row] # .chomp
895
- value = value.dup rescue value # so we can cancel
896
- row = r + (row - @toprow) # @form.row
897
- col = c+@left_margin # @form.col
898
- # unfortunately 2009-01-11 19:47 combo boxes editable allows changing value
899
- editor.prepare_editor self, row, col, value
900
- editor.component.curpos = 0 # reset it after search, if user scrols down
901
- #editor.component.graphic = @graphic # 2010-01-05 00:36 TRYING OUT BUFFERED
902
- ## override is required if the listbox uses a buffer
903
- #if @should_create_buffer # removed on 2011-09-29
904
- #$log.debug " overriding editors comp with GRAPHIC #{@graphic} "
905
- #editor.component.override_graphic(@graphic) # 2010-01-05 00:36 TRYING OUT BUFFERED
906
- #end
907
- set_form_col 0 #@left_margin
908
-
909
- # set original value so we can cancel
910
- # set row and col,
911
- # set value and other things, color and bgcolor
912
- end
913
- def on_leave_row arow
914
- #$log.debug " Listbox #{self} leave with (cr: #{@current_index}) #{arow}: list[row]:#{@list[arow]}"
915
- #$log.debug " Listbox #{self} leave with (cr: #{@current_index}) #{arow}: "
916
- #fire_handler :LEAVE_ROW, arow
917
- fire_handler :LEAVE_ROW, self
918
- editing_completed arow
919
- end
920
- def editing_completed arow
921
- if @cell_editing_allowed
922
- if !@cell_editor.nil?
923
- # $log.debug " cell editor (leave) setting value row: #{arow} val: #{@cell_editor.getvalue}"
924
- $log.debug " cell editor #{@cell_editor.component.form.window} (leave) setting value row: #{arow} val: #{@cell_editor.getvalue}"
925
- @list[arow] = @cell_editor.getvalue #.dup 2009-01-10 21:42 boolean can't duplicate
926
- else
927
- $log.debug "CELL EDITOR WAS NIL, #{arow} "
928
- end
929
- end
930
- @repaint_required = true
931
- end
932
- def editing_canceled arow=@current_index
933
- return unless @cell_editing_allowed
934
- prepare_editor @cell_editor, arow
935
- @repaint_required = true
936
- end
937
-
938
- ##
939
- # getter and setter for cell_editor
940
- def cell_editor(*val)
941
- if val.empty?
942
- @cell_editor ||= create_default_cell_editor
943
- else
944
- @cell_editor = val[0]
945
- end
946
- end
947
- def create_default_cell_editor
948
- return RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> @width-@internal_width-@left_margin}
949
- end
950
- ##
951
- # getter and setter for cell_renderer
952
- def cell_renderer(*val)
953
- if val.empty?
954
- @cell_renderer ||= create_default_cell_renderer
955
- else
956
- @cell_renderer = val[0]
957
- end
958
- end
959
- def create_default_cell_renderer
960
- return RubyCurses::ListCellRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => self, "display_length"=> @width-@internal_width-@left_margin}
961
- end
962
- ##
963
- # this method chops the data to length before giving it to the
964
- # renderer, this can cause problems if the renderer does some
965
- # processing. also, it pans the data horizontally giving the renderer
966
- # a section of it.
967
- def repaint
968
- return unless @repaint_required
969
- # not sure where to put this, once for all or repeat 2010-02-17 23:07 RFED16
970
- my_win = @form ? @form.window : @target_window
971
- @graphic = my_win unless @graphic
972
- raise " #{@name} neither form, nor target window given LB paint " unless my_win
973
- raise " #{@name} NO GRAPHIC set as yet LB paint " unless @graphic
974
- @win_left = my_win.left
975
- @win_top = my_win.top
976
-
977
- #$log.debug "rlistbox repaint #{@name} r,c, #{@row} #{@col} , width: #{@width} "
978
- print_borders unless @suppress_borders # do this once only, unless everything changes
979
- #maxlen = @maxlen || @width-@internal_width
980
- renderer = cell_renderer()
981
- renderer.display_length(@width-@internal_width-@left_margin) # just in case resizing of listbox
982
- tm = list()
983
- rc = row_count
984
- @longest_line = @width
985
- $log.debug " rlistbox repaint #{row_count} #{name} "
986
- if rc > 0 # just added in case no data passed
987
- tr = @toprow
988
- acolor = get_color $datacolor # should be set once, if color or bgcolor changs TODO FIXME
989
- h = scrollatrow()
990
- r,c = rowcol
991
- 0.upto(h) do |hh|
992
- crow = tr+hh
993
- if crow < rc
994
- _focussed = @current_index == crow ? true : false # row focussed ?
995
- focus_type = _focussed
996
- # added 2010-09-02 14:39 so inactive fields don't show a bright focussed line
997
- #focussed = false if focussed && !@focussed
998
- focus_type = :SOFT_FOCUS if _focussed && !@focussed
999
- selected = is_row_selected crow
1000
- content = tm[crow] # 2009-01-17 18:37 chomp giving error in some cases says frozen
1001
- content = convert_value_to_text content, crow # 2010-09-23 20:12
1002
- # by now it has to be a String
1003
- if content.is_a? String
1004
- content = content.dup
1005
- sanitize content if @sanitization_required
1006
- truncate content
1007
- end
1008
- ## set the selector symbol if requested
1009
- selection_symbol = ''
1010
- if @show_selector
1011
- if selected
1012
- selection_symbol = @row_selected_symbol
1013
- else
1014
- selection_symbol = @row_unselected_symbol
1015
- end
1016
- @graphic.printstring r+hh, c, selection_symbol, acolor,@attr
1017
- end
1018
- #renderer = get_default_cell_renderer_for_class content.class.to_s
1019
- renderer.repaint @graphic, r+hh, c+@left_margin, crow, content, focus_type, selected
1020
- else
1021
- # clear rows
1022
- @graphic.printstring r+hh, c, " " * (@width-@internal_width), acolor,@attr
1023
- end
1024
- end
1025
- if @cell_editing_allowed
1026
- @cell_editor.component.repaint unless @cell_editor.nil? or @cell_editor.component.form.nil?
1027
- end
1028
- end # rc == 0
1029
- #@table_changed = false
1030
- @repaint_required = false
1031
- end
1032
- # the idea here is to allow users who subclass Listbox to easily override parts of the cumbersome repaint
1033
- # method. This assumes your List has some data, but you print a lot more. Now you don't need to
1034
- # change the data in the renderer, or keep formatted data in the list itself.
1035
- # e.g. @list contains file names, or File objects, and this converts to a long listing.
1036
- # If the renderer did that, the truncation would be on wrong data.
1037
- # @since 1.2.0
1038
- def convert_value_to_text value, crow
1039
- case value
1040
- when TrueClass, FalseClass
1041
- value
1042
- else
1043
- value.to_s if value
1044
- end
1045
- end
1046
- # takes a block, this way anyone extending this class can just pass a block to do his job
1047
- # This modifies the string
1048
- def sanitize content
1049
- if content.is_a? String
1050
- content.chomp!
1051
- content.gsub!(/\t/, ' ') # don't display tab
1052
- content.gsub!(/[^[:print:]]/, '') # don't display non print characters
1053
- else
1054
- content
1055
- end
1056
- end
1057
- # returns only the visible portion of string taking into account display length
1058
- # and horizontal scrolling. MODIFIES STRING
1059
- # if you;ve truncated the data, it could stay truncated even if lb is increased. be careful
1060
- # FIXME if _maxlen becomes 0 then maxlen -1 will print whole string again
1061
- def truncate content
1062
- _maxlen = @maxlen || @width-@internal_width
1063
- _maxlen = @width-@internal_width if _maxlen > @width-@internal_width
1064
- #$log.debug "TRUNCATE: listbox maxlen #{@maxlen}, #{_maxlen} width #{@width}: #{content} "
1065
- if !content.nil?
1066
- if content.length > _maxlen # only show maxlen
1067
- @longest_line = content.length if content.length > @longest_line
1068
- #content = content[@pcol..@pcol+maxlen-1]
1069
- content.replace content[@pcol..@pcol+_maxlen-1]
1070
- else
1071
- # can this be avoided if pcol is 0 XXX
1072
- content.replace content[@pcol..-1] if @pcol > 0
1073
- end
1074
- end
1075
- #$log.debug " content: #{content}"
1076
- content
1077
- end
1078
-
1079
- def list_data_changed
1080
- if row_count == 0 # added on 2009-02-02 17:13 so cursor not hanging on last row which could be empty
1081
- init_vars
1082
- @current_index = 0
1083
- # I had placed this at some time to get cursor correct. But if this listbox is updated
1084
- # during entry in another field, then this steals the row. e.g. test1.rb 5
1085
- #set_form_row
1086
- end
1087
- @repaint_required = true
1088
- end
1089
- # set cursor column position
1090
- # if i set col1 to @curpos, i can move around left right if key mapped
1091
- def set_form_col col1=0
1092
- # TODO BUFFERED use setrowcol @form.row, col
1093
- # TODO BUFFERED use cols_panned
1094
- #col1 ||= 0
1095
- @cols_panned ||= 0 # RFED16 2010-02-17 23:40
1096
- # editable listboxes will involve changing cursor and the form issue
1097
- ## added win_col on 2010-01-04 23:28 for embedded forms BUFFERED TRYING OUT
1098
- #win_col=@form.window.left
1099
- win_col = 0 # 2010-02-17 23:19 RFED16
1100
- #col = win_col + @orig_col + @col_offset + @curpos + @form.cols_panned
1101
- col2 = win_col + @col + @col_offset + col1 + @cols_panned + @left_margin
1102
- $log.debug " set_form_col in rlistbox #{@col}+ left_margin #{@left_margin} ( #{col2} ) "
1103
- #super col+@left_margin
1104
- #@form.setrowcol @form.row, col2 # added 2009-12-29 18:50 BUFFERED
1105
- setrowcol nil, col2 # 2010-02-17 23:19 RFED16
1106
- end
1107
- #def rowcol
1108
- ## $log.debug "rlistbox rowcol : #{@row+@row_offset+@winrow}, #{@col+@col_offset}"
1109
- #win_col=@form.window.left
1110
- #col2 = win_col + @col + @col_offset + @form.cols_panned + @left_margin
1111
- #return @row+@row_offset, col2
1112
- #end
1113
- # experimental selection of multiple rows via block
1114
- # specify a block start and then a block end
1115
- # usage: bind mark_selection to a key. It works as a toggle.
1116
- # C-c will cancel any selection that has begun.
1117
- # added on 2009-02-19 22:37
1118
- def mark_block #selection
1119
- if @inside_block
1120
- @inside_block = false
1121
- end_block #selection
1122
- else
1123
- @inside_block = true
1124
- start_block #selection
1125
- end
1126
- end
1127
- # added on 2009-02-19 22:37
1128
- def cancel_block
1129
- @first_index = @last_index = nil
1130
- @inside_block = false
1131
- end
1132
- # sets marker for start of block
1133
- # added on 2009-02-19 22:37
1134
- def start_block #selection
1135
- @first_index = @current_index
1136
- @last_index = nil
1137
- end
1138
- # sets marker for end of block
1139
- # added on 2009-02-19 22:37
1140
- def end_block #selection
1141
- @last_index = current_index
1142
- lower = [@first_index, @last_index].min
1143
- higher = [@first_index, @last_index].max
1144
- #lower.upto(higher) do |i| @list.toggle_row_selection i; end
1145
- add_row_selection_interval(lower, higher)
1146
- @repaint_required = true
1147
- end
1148
- # 2010-02-18 11:40
1149
- # TRYING OUT - canceling editing if resized otherwise drawing errors can occur
1150
- # the earlier painted edited comp in yellow keeps showing until a key is pressed
1151
-
1152
- def set_buffering params
1153
- $log.warn "CALLED set_buffering in LISTBOX listbox " if $log.debug?
1154
- super # removed from widget 2011-09-29
1155
- ## Ensuring that changes to top get reflect in editing comp
1156
- #+ otherwise it raises an exception. Still the earlier cell_edit is being
1157
- #+ printed where it was , until a key is moved
1158
- # FIXME - do same for col
1159
- if @cell_editor
1160
- r,c = rowcol
1161
- if @cell_editor.component.row < @row_offset + @buffer_params[:screen_top]
1162
- @cell_editor.component.row = @row_offset + @buffer_params[:screen_top]
1163
- end
1164
- # TODO next block to be tested by placing a listbox in right split of vertical
1165
- if @cell_editor.component.col < @col_offset + @buffer_params[:screen_left]
1166
- @cell_editor.component.col = @col_offset + @buffer_params[:screen_left]
1167
- end
1168
- #editing_canceled @current_index if @cell_editing_allowed and @cell_editor
1169
- end
1170
- #set_form_row
1171
- @repaint_required = true
1172
- end
1173
-
1174
- # trying to simplify usage. The Java way has made listboxes very difficult to use
1175
- # Returns selected indices
1176
- # Indices are often required since the renderer may modify the values displayed
1177
- #
1178
- def get_selected_indices
1179
- @list_selection_model.get_selected_indices
1180
- end
1181
-
1182
- # Returns selected values
1183
- #
1184
- def get_selected_values
1185
- selected = []
1186
- @list_selection_model.get_selected_indices.each { |i| selected << list_data_model[i] }
1187
- return selected
1188
- end
1189
- alias :selected_values :get_selected_values
1190
- alias :selected_indices :get_selected_indices
1191
-
1192
- # ADD HERE
1193
- end # class listb
1194
-
1195
-
1196
- end # module