rbcurse 1.4.0 → 1.4.1.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/NOTES +68 -0
  2. data/README.markdown +73 -330
  3. data/TODO2.txt +2 -2
  4. data/VERSION +1 -1
  5. data/examples/abasiclist.rb +8 -2
  6. data/examples/alpmenu.rb +1 -1
  7. data/examples/app.rb +1 -24
  8. data/examples/appdirtree.rb +1 -1
  9. data/examples/appemail.rb +8 -14
  10. data/examples/appemaillb.rb +2 -2
  11. data/examples/appgcompose.rb +7 -5
  12. data/examples/common/file.rb +40 -0
  13. data/examples/{rmail.rb → common/rmail.rb} +0 -0
  14. data/examples/data/README.markdown +9 -0
  15. data/examples/data/brew.txt +38 -0
  16. data/examples/data/color.2 +37 -0
  17. data/examples/data/gemlist.txt +60 -0
  18. data/examples/data/lotr.txt +12 -0
  19. data/examples/data/ports.txt +136 -0
  20. data/examples/data/tasks.txt +27 -0
  21. data/examples/{todocsv.csv → data/todocsv.csv} +0 -0
  22. data/examples/data/unix1.txt +21 -0
  23. data/examples/data/unix2.txt +11 -0
  24. data/examples/dbdemo.rb +49 -14
  25. data/examples/{appgmail.rb → deprecated/appgmail.rb} +1 -1
  26. data/examples/{splitp.rb → deprecated/splitp.rb} +0 -0
  27. data/examples/{testscrolllb.rb → deprecated/testscrolllb.rb} +0 -0
  28. data/examples/{testscrollp.rb → deprecated/testscrollp.rb} +0 -0
  29. data/examples/{testscrollta.rb → deprecated/testscrollta.rb} +0 -0
  30. data/examples/{testscrolltable.rb → deprecated/testscrolltable.rb} +0 -0
  31. data/examples/{testsplit.rb → deprecated/testsplit.rb} +0 -0
  32. data/examples/{testsplit2.rb → deprecated/testsplit2.rb} +0 -0
  33. data/examples/{testsplit3.rb → deprecated/testsplit3.rb} +0 -0
  34. data/examples/{testsplit3_1.rb → deprecated/testsplit3_1.rb} +0 -0
  35. data/examples/{testsplit3a.rb → deprecated/testsplit3a.rb} +0 -0
  36. data/examples/{testsplit3b.rb → deprecated/testsplit3b.rb} +0 -0
  37. data/examples/{testsplitta.rb → deprecated/testsplitta.rb} +0 -0
  38. data/examples/{testsplittv.rb → deprecated/testsplittv.rb} +0 -0
  39. data/examples/{testsplittvv.rb → deprecated/testsplittvv.rb} +0 -0
  40. data/examples/{testtpane.rb → deprecated/testtpane.rb} +0 -0
  41. data/examples/{testtpane2.rb → deprecated/testtpane2.rb} +0 -0
  42. data/examples/{testtpanetable.rb → deprecated/testtpanetable.rb} +0 -0
  43. data/examples/dirtree.rb +17 -7
  44. data/examples/experimental/resultsetdemo.rb +280 -0
  45. data/examples/experimental/testmform.rb +35 -0
  46. data/examples/{testscroller.rb → experimental/testscroller.rb} +1 -19
  47. data/examples/experimental/teststackflow.rb +111 -0
  48. data/examples/menu1.rb +1 -0
  49. data/examples/multispl.rb +4 -4
  50. data/examples/newmessagebox.rb +130 -0
  51. data/examples/newtabbedwindow.rb +100 -0
  52. data/examples/newtesttabp.rb +0 -3
  53. data/examples/qdfilechooser.rb +0 -3
  54. data/examples/rfe.rb +134 -18
  55. data/examples/rfe_renderer.rb +48 -2
  56. data/examples/sqlc.rb +2 -1
  57. data/examples/sqlm.rb +0 -2
  58. data/examples/table1.rb +1 -7
  59. data/examples/term2.rb +4 -1
  60. data/examples/test1.rb +0 -5
  61. data/examples/test2.rb +42 -31
  62. data/examples/testapp2.rb +8 -1
  63. data/examples/testchars.rb +0 -4
  64. data/examples/testcombo.rb +5 -9
  65. data/examples/testkeypress.rb +0 -3
  66. data/examples/testmenu.rb +0 -4
  67. data/examples/testmulticomp.rb +3 -5
  68. data/examples/testmulticontainer.rb +94 -0
  69. data/examples/testtable.rb +0 -5
  70. data/examples/testtabp.rb +16 -18
  71. data/examples/testtodo.rb +1 -5
  72. data/examples/testwsshortcuts.rb +64 -0
  73. data/examples/testwsshortcuts2.rb +126 -0
  74. data/examples/viewtodo.rb +1 -4
  75. data/lib/rbcurse.rb +1 -1
  76. data/lib/rbcurse/app.rb +92 -69
  77. data/lib/rbcurse/applicationheader.rb +46 -6
  78. data/lib/rbcurse/celleditor.rb +1 -9
  79. data/lib/rbcurse/comboboxcellrenderer.rb +0 -4
  80. data/lib/rbcurse/common/ansiparser.rb +117 -0
  81. data/{examples → lib/rbcurse/common}/appmethods.rb +25 -0
  82. data/lib/rbcurse/common/basestack.rb +407 -0
  83. data/lib/rbcurse/common/bordertitle.rb +41 -0
  84. data/lib/rbcurse/common/chunk.rb +177 -0
  85. data/lib/rbcurse/common/colorparser.rb +71 -0
  86. data/lib/rbcurse/common/keydefs.rb +30 -0
  87. data/lib/rbcurse/common/widgetshortcuts.rb +302 -0
  88. data/lib/rbcurse/deprecated/README.markdown +12 -0
  89. data/lib/rbcurse/{rscrollpane.rb → deprecated/rscrollpane.rb} +0 -0
  90. data/lib/rbcurse/{rsplitpane.rb → deprecated/rsplitpane.rb} +0 -0
  91. data/lib/rbcurse/{rsplitpane2.rb → deprecated/rsplitpane2.rb} +0 -0
  92. data/lib/rbcurse/{rviewport.rb → deprecated/rviewport.rb} +0 -0
  93. data/lib/rbcurse/experimental/README.markdown +14 -0
  94. data/lib/rbcurse/experimental/resultsettextview.rb +585 -0
  95. data/lib/rbcurse/experimental/stackflow.rb +478 -0
  96. data/lib/rbcurse/extras/bottomline.rb +85 -16
  97. data/lib/rbcurse/extras/box.rb +58 -0
  98. data/lib/rbcurse/extras/directorylist.rb +1 -1
  99. data/lib/rbcurse/extras/horizlist.rb +203 -0
  100. data/lib/rbcurse/extras/listselectable.rb +8 -0
  101. data/lib/rbcurse/extras/multiform.rb +330 -0
  102. data/lib/rbcurse/extras/multilinelabel.rb +142 -0
  103. data/lib/rbcurse/extras/newmessagebox.rb +328 -0
  104. data/lib/rbcurse/extras/newtabbedpane.rb +612 -0
  105. data/lib/rbcurse/extras/newtabbedwindow.rb +68 -0
  106. data/lib/rbcurse/extras/padreader.rb +189 -0
  107. data/lib/rbcurse/extras/rcomboedit.rb +256 -0
  108. data/lib/rbcurse/extras/resultsetbrowser.rb +281 -0
  109. data/lib/rbcurse/extras/statusline.rb +44 -6
  110. data/lib/rbcurse/extras/tabularwidget.rb +141 -104
  111. data/lib/rbcurse/extras/textpad.rb +516 -0
  112. data/lib/rbcurse/extras/viewer.rb +2 -0
  113. data/lib/rbcurse/io.rb +120 -3
  114. data/lib/rbcurse/listcellrenderer.rb +2 -1
  115. data/lib/rbcurse/listkeys.rb +1 -1
  116. data/lib/rbcurse/listscrollable.rb +72 -7
  117. data/lib/rbcurse/rbasiclistbox.rb +64 -12
  118. data/lib/rbcurse/rchangeevent.rb +0 -1
  119. data/lib/rbcurse/rcombo.rb +54 -59
  120. data/lib/rbcurse/rcommandwindow.rb +46 -10
  121. data/lib/rbcurse/rcontainer.rb +415 -0
  122. data/lib/rbcurse/rdialogs.rb +242 -165
  123. data/lib/rbcurse/rinputdataevent.rb +0 -1
  124. data/lib/rbcurse/rlistbox.rb +19 -9
  125. data/lib/rbcurse/rmessagebox.rb +1 -5
  126. data/lib/rbcurse/rmulticontainer.rb +64 -61
  127. data/lib/rbcurse/rmultitextview.rb +0 -2
  128. data/lib/rbcurse/rpopupmenu.rb +0 -2
  129. data/lib/rbcurse/rscrollform.rb +61 -12
  130. data/lib/rbcurse/rtabbedpane.rb +89 -73
  131. data/lib/rbcurse/rtabbedwindow.rb +53 -211
  132. data/lib/rbcurse/rtable.rb +0 -2
  133. data/lib/rbcurse/rtextarea.rb +14 -14
  134. data/lib/rbcurse/rtextview.rb +165 -50
  135. data/lib/rbcurse/rvimsplit.rb +15 -12
  136. data/lib/rbcurse/rwidget.rb +404 -150
  137. data/lib/rbcurse/table/tablecellrenderer.rb +1 -4
  138. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -3
  139. data/lib/ver/ncurses.rb +1 -9
  140. data/lib/ver/rpad.rb +375 -0
  141. data/lib/ver/window.rb +262 -440
  142. metadata +73 -31
@@ -0,0 +1,12 @@
1
+ == Short Story
2
+
3
+ If you are new here, don't touch anything in this directory.
4
+
5
+ == Long Story
6
+
7
+ This directory contains stuff that was once used, but has since been rewritten in a simpler form.
8
+ Thus, I've replaced this with the simpler form. This still exists for anyone who was using it.
9
+
10
+ Some old stuff was either rather ambitiously rewritten or written awfully like MessageBox. I've got a more sensible version up now. Stuff here will *NOT* be maintained by me anylonger.
11
+
12
+ There's also stuff here that will *NOT* work any longer such as SplitPanes and ScrollPanes. Support for them has been removed from the core (Form, widget and window) since it was complicating the core too much.
@@ -0,0 +1,14 @@
1
+ == Short story
2
+
3
+ Minimally tested but interesting stuff
4
+
5
+ == Long story
6
+
7
+ Use stuff here at your own risk. Most of this works, and will work in most situations but may not take care validations, extreme cases, wrong data passed.
8
+
9
+ Its tested for basic use cases. Samples should help you. Don't use in production, or release for others to use. Use for personal use if you have too.
10
+
11
+
12
+ Feel free to fork and further develop stuff in here, or submit patches to me.
13
+
14
+ Some of this stuff may move to extras or core if its really useful and stable.
@@ -0,0 +1,585 @@
1
+ =begin
2
+ * Name: ResultsetTextView
3
+ * Description View text in this widget.
4
+ * Author: rkumar (arunachalesha)
5
+ * file created 2009-01-08 15:23
6
+ * major change: 2010-02-10 19:43 simplifying the buffer stuff.
7
+ * major change: 2011-10-14 reducing repaint, calling only if scrolled
8
+ also, printing row focus and selection outside of repaint so only 2 rows affected.
9
+ --------
10
+ * License:
11
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
12
+
13
+ =end
14
+ require 'rbcurse/rtextview'
15
+
16
+ include RubyCurses
17
+ module RubyCurses
18
+ extend self
19
+
20
+ ##
21
+ # An extension of textview that allows viewing a resultset, one record
22
+ # at a time, paging records.
23
+
24
+ class ResultsetTextView < TextView
25
+
26
+ # The offset of the current record in the resultset, starting 0
27
+ attr_accessor :current_record
28
+
29
+ # not used, and may not be used since i would have to reserve on more column for this
30
+ #dsl_accessor :row_selected_symbol
31
+ # Should the row focussed on show a highlight or not, default is false
32
+ # By default, the cursor will be placed on focussed row.
33
+ dsl_accessor :should_show_focus
34
+ #
35
+ # Attribute of selected row 'reverse' 'bold'
36
+ # By default, it is reverse.
37
+ dsl_accessor :selected_attrib
38
+ # Attribute of focussed row 'reverse' 'bold'
39
+ # By default, it is not set.
40
+ dsl_accessor :focussed_attrib # attribute of focussed row 'bold' 'underline'
41
+ dsl_accessor :editing_allowed # can user edit values and store in database
42
+
43
+ def initialize form = nil, config={}, &block
44
+ @row_offset = @col_offset = 1
45
+ @row = 0
46
+ @col = 0
47
+ @should_show_focus = false # don;t show focus and unfocus by default
48
+ @list = [] # this is only the currently visible record
49
+ @rows = nil # this is the entire resultset
50
+ @old_record = @current_record = 0 # index of currently displayed record from resultset
51
+ @editing_allowed = true
52
+ super
53
+ @win = @graphic
54
+ @datatypes = nil; # to be set when we query data, an array one for each column
55
+
56
+ @widget_scrolled = true
57
+ @record_changed = false
58
+
59
+ @help_text = "C to edit a column, Navigation: M-lhjk,jk gg G, Space. Next Record M-period or period, Previous M-comma or comma. Last Record '>' First Record '<' <Enter> View sortable tabular view"
60
+ bind(:PRESS){ |eve|
61
+ s = eve.source
62
+ r = s.current_record
63
+ col = @columns[@current_index]
64
+ #alert "You clicked on #{r} , #{col} , #{eve.text} "
65
+ #edit_record
66
+ }
67
+ #@selected_attrib = 'standout'
68
+ #@focussed_attrib = 'underline'
69
+ end
70
+ def edit_record
71
+ unless @editing_allowed
72
+ say "You clicked on #{r} , #{col} , #{eve.text}. If editing_allowed was true you could have modified the db "
73
+ return
74
+ end
75
+ col = @columns[@current_index]
76
+ text = @rows[@current_record][@current_index]
77
+ value = ask("Edit #{col}: "){ |q| q.default = text }
78
+ if value && value != "" && value != text
79
+ @rows[@current_record][@current_index] = value
80
+ @widget_scrolled = true # force repaint of data
81
+ begin
82
+ sql_update @tablename, id=@rows[@current_record][0], col, value
83
+ say_with_wait "Update to database successful"
84
+ rescue => err
85
+ alert "UPDATE ERROR:#{err.to_s} "
86
+ end
87
+ else
88
+ say_with_pause "Editing aborted", :color_pair => $errorcolor
89
+ end
90
+ end
91
+ ##
92
+ # update a row from bugs based on id, giving one fieldname and value
93
+ # @param [Fixnum] id unique key
94
+ # @param [String] fieldname
95
+ # @param [String] value to update
96
+ # @example sql_update "bugs", 9, :name, "Roger"
97
+ # I need to know keyfields for 2 reasons , disallow update and use in update XXX
98
+ def sql_update table, id, field, value
99
+ # 2010-09-12 11:42 added to_s to now, due to change in sqlite3 1.3.x
100
+ alert "No database connection" unless @db
101
+ return unless @db
102
+ ret = @db.execute( "update #{table} set #{field} = ? where id = ?", [value, id])
103
+ $log.debug "SQLITE ret value : #{ret}, #{table} #{field} #{id} #{value} "
104
+ end
105
+
106
+ def repaint_all tf
107
+ super
108
+ @widget_scrolled = true
109
+ end
110
+ def next_record num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
111
+ @old_record = @current_record
112
+ @record_changed = true
113
+ num.times {
114
+ @current_record += 1 if @current_record < @rows.count-1;
115
+ }
116
+
117
+ @repaint_required = true
118
+ $multiplier = 0
119
+ end
120
+ def previous_record num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
121
+ @old_record = @current_record
122
+ @record_changed = true
123
+ num.times {
124
+ @current_record -= 1 if @current_record > 0 ;
125
+ }
126
+ @repaint_required = true
127
+ end
128
+ def last_record
129
+ @old_record = @current_record
130
+ @record_changed = true
131
+ @current_record = @rows.count-1; @repaint_required = true
132
+ end
133
+ def first_record
134
+ @old_record = @current_record
135
+ @record_changed = true
136
+ @current_record = 0; @repaint_required = true
137
+ end
138
+ def map_keys
139
+ super
140
+ bind_key([?\C-x, ?6], :scroll_backward)
141
+ bind_key([?\C-x, ?v], :scroll_forward)
142
+ bind_key([?\C-x, ?n], :next_record)
143
+ bind_key([?\C-x, ?p], :previous_record)
144
+ bind_keys([?\M-,,?,], :previous_record )
145
+ bind_keys([?\M-.,?.], :next_record)
146
+ bind_keys([?\M-<,?<], :first_record )
147
+ bind_keys([?\M->,?>], :last_record)
148
+ bind_key('C', :edit_record)
149
+ #bind_key([?\C-x, ?>], :scroll_right)
150
+ #bind_key([?\C-x, ?<], :scroll_left)
151
+ #bind_key([?\C-x, ?\C-s], :saveas)
152
+ #bind_key(?r) { getstr("Enter a word: ") }
153
+ #bind_key(?m, :disp_menu)
154
+ end
155
+ # connect to database, run sql and set data, columns and datatypes
156
+ # Similar can be done with another database
157
+ def sqlite dbname, table, sql
158
+ raise "file not found" unless File.exist? dbname
159
+ require 'sqlite3'
160
+ db = SQLite3::Database.new(dbname)
161
+ columns, *rows = db.execute2(sql)
162
+ @db = db # for update
163
+ @dbname = dbname
164
+ @tablename = table
165
+ $log.debug "XXX sql #{sql}, #{rows.count} "
166
+ content = rows
167
+ return nil if content.nil? or content[0].nil?
168
+ self.datatypes = content[0].types
169
+ set_content rows, columns
170
+ end
171
+ ##
172
+ # send in a dataset (array of arrays) and array of column names
173
+ # e.g. set_content File.open("README.txt","r").readlines
174
+ # set wrap at time of passing :WRAP_NONE :WRAP_WORD
175
+ # XXX if we widen the textview later, as in a vimsplit that data
176
+ # will still be wrapped at this width !!
177
+ def set_content list, columns
178
+ @rows = list
179
+ @columns = columns
180
+ @current_record = 0
181
+ init_vars
182
+ self
183
+ end
184
+ def data=(list)
185
+ @rows = list
186
+ end
187
+ def columns=(list)
188
+ @columns = list
189
+ end
190
+ # set array of datatypes, one per column
191
+ def datatypes=(list)
192
+ @datatypes = list
193
+ end
194
+ def remove_all
195
+ $log.warn "ResultsetTextView remove_all not yet tested XXX"
196
+ @list = []
197
+ @rows = []
198
+ init_vars
199
+ @repaint_required = true
200
+ end
201
+
202
+ def repaint # textview :nodoc:
203
+ #$log.debug "TEXTVIEW repaint r c #{@row}, #{@col} "
204
+ $log.debug "RESULTSETTEXTVIEW repaint r c #{@row}, #{@col}, key: #{$current_key}, reqd #{@repaint_required} "
205
+
206
+ # TRYING OUT dangerous 2011-10-13
207
+ @repaint_required = false
208
+ @repaint_required = true if @widget_scrolled || @pcol != @old_pcol || @record_changed
209
+
210
+
211
+ paint if @repaint_required
212
+
213
+ print_foot if @print_footer && !@suppress_borders && @repaint_footer_required
214
+ end
215
+ def print_foot #:nodoc:
216
+ return unless @rows
217
+ @footer_attrib ||= Ncurses::A_DIM
218
+ gb = get_color($datacolor, 'green','black')
219
+ footer = "%15s" % " [#{@current_record+1}/ #{@rows.length} ]"
220
+ $log.debug " print_foot calling printstring with #{@row} + #{@height} -1, #{@col}+2"
221
+ pos = @col + 2
222
+ right = true
223
+ if right
224
+ pos = @col + @width - footer.length - 1
225
+ end
226
+ @graphic.printstring( @row + @height -1 , pos, footer, gb, @footer_attrib)
227
+ @repaint_footer_required = false # 2010-01-23 22:55
228
+ end
229
+ def getvalue
230
+ @list
231
+ end
232
+ # not sure what to return, returning data value
233
+ def current_value
234
+ return nil if @list.nil? || @rows.nil?
235
+ #@list[@current_record][@current_index]
236
+ @rows[@current_record][@current_index]
237
+ end
238
+ def fire_action_event
239
+ if @current_index == @selected_index
240
+ @old_selected_index = @current_index
241
+ unhighlight_row @current_index
242
+ color_field @current_index
243
+ @selected_index = nil
244
+ return
245
+ end
246
+ unhighlight_row @selected_index
247
+ color_field @selected_index
248
+ @selected_index = @current_index
249
+ highlight_selected_row
250
+ @old_selected_index = @selected_index
251
+ @repaint_required = true
252
+ super
253
+ tabular
254
+ end
255
+ def handle_key ch #:nodoc:
256
+ return :UNHANDLED if @rows.nil?
257
+ super
258
+ end
259
+ def tabular
260
+ require 'rbcurse/extras/tabularwidget'
261
+ w = Ncurses.COLS
262
+ h = Ncurses.LINES-1
263
+ v_window = VER::Window.new(h,w,0,0)
264
+ v_form = RubyCurses::Form.new v_window
265
+ tabula = TabularWidget.new v_form, :width => w, :height => h-1, :print_footer => true
266
+ begin
267
+ tabula.set_content @rows, @columns
268
+ yield tabula if block_given?
269
+ v_form.repaint
270
+ v_window.wrefresh
271
+ Ncurses::Panel.update_panels
272
+ # allow closing using q and Ctrl-q in addition to any key specified
273
+ # user should not need to specify key, since that becomes inconsistent across usages
274
+ while((ch = v_window.getchar()) != ?\C-q.getbyte(0) )
275
+ break if ch == config[:close_key] || ch == ?q.ord
276
+ # if you've asked for RETURN then i also check for 10 and 13
277
+ break if (ch == 10 || ch == 13) && config[:close_key] == KEY_RETURN
278
+ v_form.handle_key ch
279
+ #v_form.repaint
280
+ v_window.wrefresh
281
+ end
282
+ rescue => err
283
+ $log.error " Tabularwidget Resultsetview ERROR #{err} "
284
+ $log.error(err.backtrace.join("\n"))
285
+ alert err.to_s
286
+
287
+ ensure
288
+ v_window.destroy if !v_window.nil?
289
+ end
290
+ end
291
+ # newly added to check curpos when moving up or down
292
+ # set cursor on correct column tview
293
+ def set_form_col col1=@curpos #:nodoc:
294
+ @cols_panned ||= 0
295
+ @pad_offset ||= 0 # added 2010-02-11 21:54 since padded widgets get an offset.
296
+ @curpos = col1
297
+ maxlen = @maxlen || @width-@internal_width
298
+ #@curpos = maxlen if @curpos > maxlen
299
+ if @curpos > maxlen
300
+ @pcol = @curpos - maxlen
301
+ @curpos = maxlen - 1
302
+ @repaint_required = true # this is required so C-e can pan screen
303
+ else
304
+ @pcol = 0
305
+ end
306
+ # the rest only determines cursor placement
307
+ win_col = 0 # 2010-02-07 23:19 new cursor stuff
308
+ col2 = win_col + @col + @col_offset + @curpos + @cols_panned + @pad_offset
309
+ $log.debug "TV SFC #{@name} setting c to #{col2} #{win_col} #{@col} #{@col_offset} #{@curpos} "
310
+ #@form.setrowcol @form.row, col
311
+ setrowcol nil, col2
312
+ @repaint_footer_required = true
313
+ end
314
+ #
315
+ # prepares row data for paint to print
316
+ # Creates a string for each row, which is great for textview operation, all of them
317
+ # work just fine. But does not allow paint to know what part is title and what is
318
+ # data
319
+ #
320
+ def get_content
321
+ return nil unless @rows
322
+ id = @current_record
323
+
324
+ row = @rows[id]
325
+ @lens = []
326
+ a = []
327
+ f = "%14s %-*s"
328
+ #f = "%14s %-20s"
329
+ @columns.each_with_index { |e, i|
330
+ value = row[i]
331
+ len = value.to_s.length
332
+ type = @datatypes[i]
333
+ if type == "TEXT"
334
+ value = value.gsub(/\n/," ") if value
335
+ end
336
+ @lens << len
337
+ a << f % [e, len, value]
338
+ }
339
+ @list = a # this keeps it compatible with textview operations.
340
+ return a
341
+ end
342
+
343
+ ## NOTE: earlier print_border was called only once in constructor, but when
344
+ ##+ a window is resized, and destroyed, then this was never called again, so the
345
+ ##+ border would not be seen in splitpane unless the width coincided exactly with
346
+ ##+ what is calculated in divider_location.
347
+ def paint #:nodoc:
348
+
349
+ $log.debug "XXX TEXTVIEW PAINT HAPPENING #{@current_index} "
350
+ #@left_margin ||= @row_selected_symbol.length
351
+ @left_margin = 0
352
+ @fieldbgcolor ||= get_color($datacolor,@bgcolor, 'cyan')
353
+ my_win = nil
354
+ if @form
355
+ my_win = @form.window
356
+ else
357
+ my_win = @target_window
358
+ end
359
+ @graphic = my_win unless @graphic
360
+ @win_left = my_win.left
361
+ @win_top = my_win.top
362
+
363
+ print_borders if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
364
+ maxlen = @maxlen || @width-@internal_width
365
+ #$log.debug " #{@name} textview repaint width is #{@width}, height is #{@height} , maxlen #{maxlen}/ #{@maxlen}, #{@graphic.name} roff #{@row_offset} coff #{@col_offset}"
366
+ tm = get_content
367
+ return unless tm # no data
368
+ rc = tm.size # row_count
369
+ tr = @toprow
370
+ acolor = get_color $datacolor
371
+ h = scrollatrow()
372
+ r,c = rowcol
373
+ @longest_line = @width-@internal_width #maxlen
374
+ $log.debug "XXX: SELECTED ROW IS #{@selected_index} "
375
+ 0.upto(h) do |hh|
376
+ crow = tr+hh
377
+ if crow < rc
378
+ focussed = @current_index == crow # row focussed ?
379
+ selected = is_row_selected crow
380
+ content = tm[crow]
381
+ content = content.dup
382
+ sanitize content if @sanitization_required
383
+ truncate content
384
+
385
+ @graphic.printstring r+hh, c+@left_margin, "%-*s" % [@width-@internal_width,content], acolor, @attr
386
+
387
+ if selected
388
+ #print_selected_row r+hh, c+@left_margin, content, acolor
389
+ highlight_selected_row r+hh, c
390
+ #@graphic.printstring r+hh, c+@left_margin, "%-*s" % [@width-@internal_width,content], acolor, @focussed_attrib || 'reverse'
391
+ elsif focussed
392
+ # i am keeping this here just since sometimes repaint gets called
393
+ highlight_focussed_row :FOCUSSED, r+hh, c
394
+ end
395
+ #print_focussed_row :FOCUSSED, nil, nil, content, acolor
396
+ #@graphic.printstring r+hh, c+@left_margin, "%-*s" % [@width-@internal_width,content], acolor, @focussed_attrib || 'bold'
397
+
398
+ color_field crow
399
+ =begin
400
+ # paint field portion separately, take care of when panned
401
+ # hl only field length, not whole thing.
402
+ startpoint = [c+14+1-@pcol,c].max # don't let it go < 0
403
+ clen = @lens[crow]
404
+ # take into account when we've scrolled off right
405
+ clen -= @pcol-14-1 if 14+1-@pcol < 0
406
+ hlwidth = [clen,@width-@internal_width-14-1+@pcol, @width-@internal_width].min
407
+ hlwidth = 0 if hlwidth < 0
408
+
409
+ @graphic.mvchgat(y=r+hh, x=startpoint, hlwidth, Ncurses::A_NORMAL, @fieldbgcolor, nil)
410
+ #@graphic.mvchgat(y=r+hh, x=startpoint, hlwidth, Ncurses::A_BOLD, acolor, nil)
411
+ =end
412
+
413
+ # highlighting search results.
414
+ if @search_found_ix == tr+hh
415
+ if !@find_offset.nil?
416
+ # handle exceed bounds, and if scrolling
417
+ if @find_offset1 < maxlen+@pcol and @find_offset > @pcol
418
+ @graphic.mvchgat(y=r+hh, x=c+@find_offset-@pcol, @find_offset1-@find_offset, Ncurses::A_NORMAL, $reversecolor, nil)
419
+ end
420
+ end
421
+ end
422
+ else
423
+ # clear rows
424
+ @graphic.printstring r+hh, c, " " * (@width-@internal_width), acolor,@attr
425
+ end
426
+
427
+ end
428
+ @repaint_required = false
429
+ @repaint_footer_required = true
430
+ @repaint_all = false
431
+ # 2011-10-13
432
+ @widget_scrolled = false
433
+ @record_changed = false
434
+ @old_pcol = @pcol
435
+
436
+ end
437
+ def color_field index
438
+ return unless index
439
+ _r,c = rowcol
440
+ r = _convert_index_to_printable_row index
441
+ return unless r
442
+ # paint field portion separately, take care of when panned
443
+ # hl only field length, not whole thing.
444
+ startpoint = [c+14+1-@pcol,c].max # don't let it go < 0
445
+ clen = @lens[index]
446
+ # take into account when we've scrolled off right
447
+ clen -= @pcol-14-1 if 14+1-@pcol < 0
448
+ hlwidth = [clen,@width-@internal_width-14-1+@pcol, @width-@internal_width].min
449
+ hlwidth = 0 if hlwidth < 0
450
+
451
+ @graphic.mvchgat(y=r, x=startpoint, hlwidth, Ncurses::A_NORMAL, @fieldbgcolor, nil)
452
+ end
453
+ # the idea here is to be able to call externally or from loop
454
+ # However, for that content has to be truncated here, not in loop
455
+ def DELprint_focussed_row type, r=nil, c=nil, content=nil, acolor=nil
456
+ return unless @should_show_focus
457
+ case type
458
+ when :FOCUSSED
459
+ r = _convert_index_to_printable_row() unless r
460
+ attrib = @focussed_attrib || 'bold'
461
+ ix = @current_index
462
+
463
+ when :UNFOCUSSED
464
+ return if @oldrow.nil? || @oldrow == @current_index
465
+ r = _convert_index_to_printable_row(@oldrow) unless r
466
+ return unless r # row is not longer visible
467
+ ix = @oldrow
468
+ attrib = @attr
469
+ end
470
+ unless c
471
+ _r, c = rowcol
472
+ end
473
+ if content.nil?
474
+ content = @list[ix]
475
+ content = content.dup
476
+ sanitize content if @sanitization_required
477
+ truncate content
478
+ end
479
+ acolor ||= get_color $datacolor
480
+ #@graphic.printstring r+hh, c+@left_margin, "%-*s" % [@width-@internal_width,content], acolor, @focussed_attrib || 'bold'
481
+ @graphic.printstring r, c+@left_margin, "%-*s" % [@width-@internal_width, content], acolor, attrib
482
+ end
483
+
484
+ # this only highlights the selcted row, does not print data again
485
+ # so its safer and should be used instead of print_selected_row
486
+ def highlight_selected_row r=nil, c=nil, acolor=nil
487
+ return unless @selected_index # no selection
488
+ r = _convert_index_to_printable_row(@selected_index) unless r
489
+ return unless r # not on screen
490
+ unless c
491
+ _r, c = rowcol
492
+ end
493
+ acolor ||= get_color $datacolor
494
+ att = FFI::NCurses::A_REVERSE
495
+ att = get_attrib(@selected_attrib) if @selected_attrib
496
+ @graphic.mvchgat(y=r, x=c, @width-@internal_width, att , acolor , nil)
497
+ end
498
+ def highlight_focussed_row type, r=nil, c=nil, acolor=nil
499
+ return unless @should_show_focus
500
+ case type
501
+ when :FOCUSSED
502
+ r = _convert_index_to_printable_row() unless r
503
+ attrib = @focussed_attrib || 'bold'
504
+ ix = @current_index
505
+
506
+ when :UNFOCUSSED
507
+ return if @oldrow.nil? || @oldrow == @current_index
508
+ r = _convert_index_to_printable_row(@oldrow) unless r
509
+ return unless r # row is not longer visible
510
+ ix = @oldrow
511
+ attrib = @attr
512
+ end
513
+ unless c
514
+ _r, c = rowcol
515
+ end
516
+ acolor ||= get_color $datacolor
517
+ att = get_attrib(attrib) #if @focussed_attrib
518
+ @graphic.mvchgat(y=r, x=c, @width-@internal_width, att , acolor , nil)
519
+ #@graphic.printstring r, c+@left_margin, "%-*s" % [@width-@internal_width,content], acolor, @focussed_attrib || 'reverse'
520
+ end
521
+ def unhighlight_row index, r=nil, c=nil, acolor=nil
522
+ return unless index # no selection
523
+ r = _convert_index_to_printable_row(index) unless r
524
+ return unless r # not on screen
525
+ unless c
526
+ _r, c = rowcol
527
+ end
528
+ acolor ||= get_color $datacolor
529
+ att = FFI::NCurses::A_NORMAL
530
+ att = get_attrib(@normal_attrib) if @normal_attrib
531
+ @graphic.mvchgat(y=r, x=c, @width-@internal_width, att , acolor , nil)
532
+ end
533
+ def is_row_selected row
534
+ @selected_index == row
535
+ end
536
+ def on_enter_row arow
537
+ if @should_show_focus
538
+ highlight_focussed_row :FOCUSSED
539
+ unless @oldrow == @selected_index
540
+ highlight_focussed_row :UNFOCUSSED
541
+ color_field @oldrow
542
+ end
543
+ end
544
+ super
545
+ end
546
+ # no such method in superclass !!! XXX FIXME no such event too
547
+ def on_leave_row arow
548
+ #print_focussed_row :UNFOCUSSED
549
+ #print_normal_row
550
+ #super
551
+ end
552
+ # this is just a test of the simple "most" menu
553
+ # How can application add to this, or override
554
+ def disp_menu #:nodoc:
555
+ require 'rbcurse/extras/menutree'
556
+ # we need to put this into data-structure so that i can be manipulated by calling apps
557
+ # This should not be at the widget level, too many types of menus. It should be at the app
558
+ # level only if the user wants his app to use this kind of menu.
559
+
560
+ @menu = RubyCurses::MenuTree.new "Main", { s: :goto_start, r: :scroll_right, l: :scroll_left, m: :submenu }
561
+ @menu.submenu :m, "submenu", {s: :noignorecase, t: :goto_last_position, f: :next3 }
562
+ menu = PromptMenu.new self
563
+ menu.menu_tree @menu
564
+
565
+ =begin
566
+ menu = PromptMenu.new self
567
+ menu.add( menu.create_mitem( 's', "Goto start ", "Going to start", Proc.new { goto_start} ))
568
+ menu.add(menu.create_mitem( 'r', "scroll right", "I have scrolled ", :scroll_right ))
569
+ menu.add(menu.create_mitem( 'l', "scroll left", "I have scrolled ", :scroll_left ))
570
+ item = menu.create_mitem( 'm', "submenu", "submenu options" )
571
+ menu1 = PromptMenu.new( self, "Submenu Options")
572
+ menu1.add(menu1.create_mitem( 's', "CASE sensitive", "Ignoring Case in search" ))
573
+ menu1.add(menu1.create_mitem( 't', "goto last position", "moved to previous position", Proc.new { goto_last_position} ))
574
+ item.action = menu1
575
+ menu.add(item)
576
+ # how do i know what's available. the application or window should know where to place
577
+ #menu.display @form.window, 23, 1, $datacolor #, menu
578
+ =end
579
+ menu.display @form.window, $error_message_row, $error_message_col, $datacolor #, menu
580
+ end
581
+
582
+
583
+ end # class textview
584
+
585
+ end # modul