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,68 @@
1
+ =begin
2
+ * Name: newtabbedwindow.rb
3
+ * Description : This is a window that contains a tabbedpane (NewTabbedPane). This for situation
4
+ when you want to pop up a setup/configuration type of tabbed pane.
5
+ See examples/newtabbedwindow.rb for an example of usage, and test2.rb
6
+ which calls it from the menu (Options2 item).
7
+ In a short while, I will deprecate the existing complex TabbedPane and use this
8
+ in the lib/rbcurse dir.
9
+ * Author: rkumar (http://github.com/rkumar/rbcurse/)
10
+ * Date: 22.10.11 - 20:35
11
+ * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
12
+ * Last update: Sat Oct 22 20:35:46 IST 2011
13
+
14
+ == CHANGES
15
+ == TODO
16
+ =end
17
+ require 'rbcurse'
18
+ require 'rbcurse/extras/newtabbedpane'
19
+ require 'rbcurse/rcontainer'
20
+
21
+ include RubyCurses
22
+ class NewTabbedWindow
23
+ attr_reader :tabbed_pane
24
+ # The given block is passed to the TabbedPane
25
+ # The given dimensions are used to create the window.
26
+ # The TabbedPane is placed at 0,0 and fills the window.
27
+ def initialize config={}, &block
28
+
29
+ h = config.fetch(:height, 0)
30
+ w = config.fetch(:width, 0)
31
+ t = config.fetch(:row, 0)
32
+ l = config.fetch(:col, 0)
33
+ @window = VER::Window.new :height => h, :width => w, :top => t, :left => l
34
+ @form = Form.new @window
35
+ config[:row] = config[:col] = 0
36
+ @tabbed_pane = NewTabbedPane.new @form, config , &block
37
+ end
38
+ # returns button index
39
+ # Call this after instantiating the window
40
+ def run
41
+ @form.repaint
42
+ @window.wrefresh
43
+ return handle_keys
44
+ end
45
+ # returns button index
46
+ private
47
+ def handle_keys
48
+ buttonindex = catch(:close) do
49
+ while((ch = @window.getchar()) != FFI::NCurses::KEY_F10 )
50
+ break if ch == ?\C-q.getbyte(0)
51
+ begin
52
+ @form.handle_key(ch)
53
+ @window.wrefresh
54
+ rescue => err
55
+ $log.debug( err) if err
56
+ $log.debug(err.backtrace.join("\n")) if err
57
+ alert "Got an exception in NewTabbedWindow: #{err}. Check log"
58
+ $error_message.value = ""
59
+ ensure
60
+ end
61
+
62
+ end # while loop
63
+ end # close
64
+ $log.debug "XXX: CALLER GOT #{buttonindex} "
65
+ @window.destroy
66
+ return buttonindex
67
+ end
68
+ end
@@ -0,0 +1,189 @@
1
+ =begin
2
+ * Name: PadReader.rb
3
+ * Description : This is an independent file viewer that uses a Pad and traps keys
4
+ * Author: rkumar (http://github.com/rkumar/rbcurse/)
5
+ * Date: 22.10.11 - 20:35
6
+ * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
7
+ * Last update: 2011-11-14 - 20:57
8
+
9
+ == CHANGES
10
+ == TODO
11
+ make the window configurable so we can move to a textview that is pad based, later even list ?
12
+ Note that cursor does not move, in real life applicatino cursor must move to bottom row
13
+ and only then scrolling should start.
14
+ NOTE: I have continued this in textpad which is a widget that uses pads to scroll.
15
+ This is very rough, i may work on this more later.
16
+ =end
17
+ require 'rbcurse'
18
+
19
+ include RubyCurses
20
+ class PadReader
21
+
22
+ # You may pass height, width, row and col for creating a window otherwise a fullscreen window
23
+ # will be created. If you pass a window from caller then that window will be used.
24
+ # Some keys are trapped, jkhl space, pgup, pgdown, end, home, t b
25
+ # This is currently very minimal and was created to get me started to integrating
26
+ # pads into other classes such as textview.
27
+ def initialize config={}, &block
28
+
29
+ @config = config
30
+ @rows = FFI::NCurses.LINES-1
31
+ @cols = FFI::NCurses.COLS-1
32
+ @prow = @pcol = 0
33
+ @startrow = 0
34
+ @startcol = 0
35
+
36
+ h = config.fetch(:height, 0)
37
+ w = config.fetch(:width, 0)
38
+ t = config.fetch(:row, 0)
39
+ l = config.fetch(:col, 0)
40
+ @rows = h unless h == 0
41
+ @cols = w unless w == 0
42
+ @startrow = t unless t == 0
43
+ @startcol = l unless l == 0
44
+ @suppress_border = config[:suppress_border]
45
+ unless @suppress_border
46
+ @startrow += 1
47
+ @startcol += 1
48
+ @rows -=3 # 3 is since print_border_only reduces one from width, to check whether this is correct
49
+ @cols -=3
50
+ end
51
+ @top = t
52
+ @left = l
53
+ view_file config[:filename]
54
+ @window = config[:window] || VER::Window.new(:height => h, :width => w, :top => t, :left => l)
55
+ # print border reduces on from width for some historical reason
56
+ @window.print_border_only @top, @left, h-1, w, $datacolor
57
+ @ph = @content_rows
58
+ @pw = @content_cols # get max col
59
+ @pad = FFI::NCurses.newpad(@ph, @pw)
60
+
61
+ Ncurses::Panel.update_panels
62
+ @content.each_index { |ix|
63
+
64
+ FFI::NCurses.mvwaddstr(@pad,ix, 0, @content[ix])
65
+ }
66
+ @window.wrefresh
67
+ padrefresh
68
+ #FFI::NCurses.prefresh(@pad, 0,0, @startrow ,@startcol, @rows,@cols);
69
+
70
+ @window.bkgd(Ncurses.COLOR_PAIR(5));
71
+ FFI::NCurses.keypad(@pad, true);
72
+ #@form = Form.new @window
73
+ config[:row] = config[:col] = 0 # ??? XXX
74
+ end
75
+
76
+ private
77
+ def view_file(filename)
78
+ @file = filename
79
+ @content = File.open(filename,"r").readlines
80
+ @content_rows = @content.count
81
+ @content_cols = content_cols()
82
+ #run()
83
+ end
84
+ # write pad onto window
85
+ private
86
+ def padrefresh
87
+ FFI::NCurses.prefresh(@pad,@prow,@pcol, @startrow,@startcol, @rows + @startrow,@cols+@startcol);
88
+ end
89
+ # returns button index
90
+ # Call this after instantiating the window
91
+ public
92
+ def run
93
+ #@form.repaint
94
+ #@window.wrefresh
95
+ return handle_keys
96
+ end
97
+
98
+ # convenience method
99
+ private
100
+ def key x
101
+ x.getbyte(0)
102
+ end
103
+ def content_cols
104
+ longest = @content.max_by(&:length)
105
+ longest.length
106
+ end
107
+
108
+ # returns button index
109
+ private
110
+ def handle_keys
111
+ ht = @window.height.ifzero FFI::NCurses.LINES-1
112
+ buttonindex = catch(:close) do
113
+ @maxrow = @content_rows - @rows
114
+ @maxcol = @content_cols - @cols
115
+ while((ch = @window.getchar()) != FFI::NCurses::KEY_F10 )
116
+ #while((ch = FFI::NCurses.wgetch(@pad)) != FFI::NCurses::KEY_F10 )
117
+ break if ch == ?\C-q.getbyte(0)
118
+ begin
119
+ case ch
120
+ when key(?g), 279 # home as per iterm2
121
+ @prow = 0
122
+ when key(?b), key(?G), 277 # end as per iterm2
123
+ @prow = @maxrow-1
124
+ when key(?j)
125
+ @prow += 1
126
+ when key(?k)
127
+ @prow -= 1
128
+ when 32, 338 # Page Down abd Page Up as per iTerm2
129
+ @prow += 10
130
+ when key(?\C-d)
131
+ @prow += ht
132
+ when key(?\C-b)
133
+ @prow -= ht
134
+ when 339
135
+ @prow -= 10
136
+ when key(?l)
137
+ @pcol += 1
138
+ when key(?$)
139
+ @pcol = @maxcol - 1
140
+ when key(?h)
141
+ @pcol -= 1
142
+ when key(?0)
143
+ @pcol = 0
144
+ when key(?q)
145
+ throw :close
146
+ else
147
+ alert " #{ch} not mapped "
148
+ end
149
+ @prow = 0 if @prow < 0
150
+ @pcol = 0 if @pcol < 0
151
+ if @prow > @maxrow-1
152
+ @prow = @maxrow-1
153
+ end
154
+ if @pcol > @maxcol-1
155
+ @pcol = @maxcol-1
156
+ end
157
+ #@window.wclear
158
+ #FFI::NCurses.prefresh(@pad,@prow,@pcol, @startrow,0, @rows,@cols);
159
+ padrefresh
160
+ Ncurses::Panel.update_panels
161
+ #@form.handle_key(ch)
162
+ #@window.wrefresh
163
+ rescue => err
164
+ $log.debug( err) if err
165
+ $log.debug(err.backtrace.join("\n")) if err
166
+ alert "Got an exception in PadReader: #{err}. Check log"
167
+ $error_message.value = ""
168
+ ensure
169
+ end
170
+
171
+ end # while loop
172
+ end # close
173
+ $log.debug "XXX: CALLER GOT #{buttonindex} "
174
+ @window.destroy unless @config[:window]
175
+ FFI::NCurses.delwin(@pad)
176
+ return buttonindex
177
+ end
178
+ end
179
+ if __FILE__ == $PROGRAM_NAME
180
+ require 'rbcurse/app'
181
+ App.new do
182
+ #status_line :row => FFI::NCurses.LINES-1
183
+ @form.repaint
184
+ #p = PadReader.new :filename => "padreader.rb", :height => 20, :width => 60, :row => 4, :col => 4, :window => @window, :suppress_border => true
185
+ p = PadReader.new :filename => "padreader.rb", :height => FFI::NCurses.LINES-1, :width => 0, :row => 0, :col => 0, :window => @window, :suppress_border => true
186
+ p.run
187
+ throw :close
188
+ end
189
+ end
@@ -0,0 +1,256 @@
1
+ =begin
2
+ * Name: combo box
3
+ * Description:
4
+ * Author: rkumar
5
+
6
+ --------
7
+ * Date: 2008-12-16 22:03
8
+ * License:
9
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
+
11
+ TODO:
12
+ Simplify completely. we don't need to use popup list, use something simpler do
13
+ we can control keys.
14
+ Keys: ignore down arrow in field. Use space to popup and space to select from popup.
15
+ Or keep that as default.
16
+ That v character does not position correctly if label used.
17
+ =end
18
+ require 'rbcurse'
19
+ require 'rbcurse/rlistbox'
20
+
21
+ include RubyCurses
22
+ module RubyCurses
23
+ extend self
24
+
25
+ # TODO :
26
+ # i no longer use values, i now use "list" or better "list_data_model"
27
+ # try to make it so values gets converted to list.
28
+ # NOTE: 2010-10-01 13:25 spacebar and enter will popup in addition to Alt-Down
29
+ class ComboBoxEdit < Field
30
+ include RubyCurses::EventHandler
31
+ dsl_accessor :list_config
32
+ dsl_accessor :insert_policy # NO_INSERT, INSERT_AT_TOP, INSERT_AT_BOTTOM, INSERT_AT_CURRENT
33
+ # INSERT_AFTER_CURRENT, INSERT_BEFORE_CURRENT,INSERT_ALPHABETICALLY
34
+
35
+ attr_accessor :current_index
36
+ # the symbol you want to use for combos
37
+ attr_accessor :COMBO_SYMBOL
38
+ attr_accessor :show_symbol # show that funny symbol after a combo to signify its a combo
39
+ dsl_accessor :arrow_key_policy # :IGNORE :NEXT_ROW :POPUP
40
+
41
+ def initialize form, config={}, &block
42
+ @arrow_key_policy = :ignore
43
+ @show_symbol = true
44
+ @COMBO_SYMBOL = "v".ord # trying this out
45
+ super
46
+ @current_index ||= 0
47
+ # added if check since it was overriding set_buffer in creation. 2009-01-18 00:03
48
+ set_buffer @list[@current_index].dup if @buffer.nil? or @buffer.empty?
49
+ init_vars
50
+ @_events.push(*[:CHANGE, :ENTER_ROW, :LEAVE_ROW])
51
+ end
52
+ def init_vars
53
+ super
54
+ #@show_symbol = false if @label # commented out 2011-11-13 maybe it doesn't place properly if label
55
+ @COMBO_SYMBOL ||= FFI::NCurses::ACS_DARROW #GEQUAL # now this won't work since i've set it above
56
+ bind_key(KEY_UP) { previous_row }
57
+ bind_key(KEY_DOWN) { next_row }
58
+ end
59
+ def selected_item
60
+ @list[@current_index]
61
+ end
62
+ def selected_index
63
+ @current_index
64
+ end
65
+
66
+ ##
67
+ # convert given list to datamodel
68
+ def list alist=nil
69
+ return @list if alist.nil?
70
+ @list = RubyCurses::ListDataModel.new(alist)
71
+ end
72
+ ##
73
+ # set given datamodel
74
+ def list_data_model ldm
75
+ raise "Expecting list_data_model" unless ldm.is_a? RubyCurses::ListDataModel
76
+ @list = ldm
77
+ end
78
+ ##
79
+ # combo edit box key handling
80
+ # removed UP and DOWN and bound it, so it can be unbound
81
+ def handle_key(ch)
82
+ @current_index ||= 0
83
+ # added 2009-01-18 22:44 no point moving horiz or passing up to Field if not edit
84
+ if !@editable
85
+ if ch == KEY_LEFT or ch == KEY_RIGHT
86
+ return :UNHANDLED
87
+ end
88
+ end
89
+ case @arrow_key_policy
90
+ when :ignore
91
+ if ch == KEY_DOWN or ch == KEY_UP
92
+ return :UNHANDLED
93
+ end
94
+ when :popup
95
+ if ch == KEY_DOWN or ch == KEY_UP
96
+ popup
97
+ end
98
+ end
99
+ case ch
100
+ #when KEY_UP # show previous value
101
+ # previous_row
102
+ #when KEY_DOWN # show previous value
103
+ # next_row
104
+ # adding spacebar to popup combo, as in microemacs 2010-10-01 13:21
105
+ when 32, KEY_DOWN+ META_KEY # alt down
106
+ popup # pop up the popup
107
+ else
108
+ super
109
+ end
110
+ end
111
+ def previous_row
112
+ @current_index -= 1 if @current_index > 0
113
+ set_buffer @list[@current_index].dup
114
+ set_modified(true) ## ??? not required
115
+ fire_handler :ENTER_ROW, self
116
+ @list.on_enter_row self
117
+ end
118
+ def next_row
119
+ @current_index += 1 if @current_index < @list.length()-1
120
+ set_buffer @list[@current_index].dup
121
+ set_modified(true) ## ??? not required
122
+ fire_handler :ENTER_ROW, self
123
+ @list.on_enter_row self
124
+ end
125
+ ##
126
+ # calls a popup list
127
+ # TODO: should not be positioned so that it goes off edge
128
+ # user's customizations of list should be passed in
129
+ # The dup of listconfig is due to a tricky feature/bug.
130
+ # I try to keep the config hash and instance variables in synch. So
131
+ # this config hash is sent to popuplist which updates its row col and
132
+ # next time we pop up the popup row and col are zero.
133
+ #
134
+ #
135
+ # added dup in PRESS since editing edit field mods this
136
+ # on pressing ENTER, value set back and current_index updated
137
+ def popup
138
+ listconfig = (@list_config && @list_config.dup) || {}
139
+ dm = @list
140
+ # current item in edit box will be focussed when list pops up
141
+ #$log.debug "XXX POPUP: #{dm.selected_index} = #{@current_index}, value #{@buffer}"
142
+ # we are having some problms when using this in a list. it retains earlier value
143
+ _index = dm.index @buffer
144
+ dm.selected_index = _index # @current_index
145
+ poprow = @row+0 # one row below the edit box
146
+ popcol = @col
147
+ dlength = @display_length
148
+ f = self
149
+ @popup = RubyCurses::PopupList.new do
150
+ row poprow
151
+ col popcol
152
+ width dlength
153
+ list_data_model dm
154
+ list_selection_mode 'single'
155
+ relative_to f
156
+ list_config listconfig
157
+ bind(:PRESS) do |index|
158
+ f.set_buffer dm[index].dup
159
+ f.set_modified(true) if f.current_index != index
160
+ f.current_index = index
161
+ end
162
+ end
163
+ end
164
+
165
+ # Field putc advances cursor when it gives a char so we override this
166
+ def putc c
167
+ if c >= 0 and c <= 127
168
+ ret = putch c.chr
169
+ if ret == 0
170
+ addcol 1 if @editable
171
+ set_modified
172
+ end
173
+ end
174
+ return -1 # always ??? XXX
175
+ end
176
+ ##
177
+ # field does not give char to non-editable fields so we override
178
+ def putch char
179
+ @current_index ||= 0
180
+ if @editable
181
+ super
182
+ return 0
183
+ else
184
+ match = next_match(char)
185
+ set_buffer match unless match.nil?
186
+ fire_handler :ENTER_ROW, self
187
+ end
188
+ @modified = true
189
+ fire_handler :CHANGE, self # 2008-12-09 14:51 ???
190
+ 0
191
+ end
192
+ ##
193
+ # the sets the next match in the edit field
194
+ def next_match char
195
+ start = @current_index
196
+ start.upto(@list.length-1) do |ix|
197
+ if @list[ix][0,1].casecmp(char) == 0
198
+ return @list[ix] unless @list[ix] == @buffer
199
+ end
200
+ @current_index += 1
201
+ end
202
+ ## could not find, start from zero
203
+ @current_index = 0
204
+ start = [@list.length()-1, start].min
205
+ 0.upto(start) do |ix|
206
+ if @list[ix][0,1].casecmp(char) == 0
207
+ return @list[ix] unless @list[ix] == @buffer
208
+ end
209
+ @current_index += 1
210
+ end
211
+ @current_index = [@list.length()-1, @current_index].min
212
+ return nil
213
+ end
214
+ ##
215
+ # on leaving the listbox, update the combo/datamodel.
216
+ # we are using methods of the datamodel. Updating our list will have
217
+ # no effect on the list, and wont trigger events.
218
+ # Do not override.
219
+ def on_leave
220
+ if !@list.include? @buffer and !@buffer.strip.empty?
221
+ _insert_policy = @insert_policy || :INSERT_AT_BOTTOM
222
+ case _insert_policy
223
+ when :INSERT_AT_BOTTOM, :INSERT_AT_END
224
+ @list.append @buffer
225
+ when :INSERT_AT_TOP
226
+ @list.insert(0, @buffer)
227
+ when :INSERT_AFTER_CURRENT
228
+ @current_index += 1
229
+ @list.insert(@current_index, @buffer)
230
+
231
+ when :INSERT_BEFORE_CURRENT
232
+ #_index = @current_index-1 if @current_index>0
233
+ _index = @current_index
234
+ @list.insert(_index, @buffer)
235
+ when :INSERT_AT_CURRENT
236
+ @list[@current_index]=@buffer
237
+ when :NO_INSERT
238
+ ; # take a break
239
+ end
240
+ end
241
+ fire_handler :LEAVE, self
242
+ end
243
+
244
+ def repaint
245
+ super
246
+ c = @col + @display_length
247
+ if @show_symbol # 2009-01-11 18:47
248
+ # i have changed c +1 to c, since we have no right to print beyond display_length
249
+ @form.window.mvwaddch @row, c, @COMBO_SYMBOL # Ncurses::ACS_GEQUAL
250
+ @form.window.mvchgat(y=@row, x=c, max=1, Ncurses::A_REVERSE|Ncurses::A_UNDERLINE, $datacolor, nil)
251
+ end
252
+ end
253
+
254
+ end # class ComboBox
255
+
256
+ end # module