rbcurse 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/CHANGELOG +33 -0
  2. data/README.markdown +7 -1
  3. data/TODO2.txt +21 -15
  4. data/VERSION +1 -1
  5. data/examples/abasiclist.rb +2 -2
  6. data/examples/alpmenu.rb +1 -1
  7. data/examples/app.rb +0 -1
  8. data/examples/appdirtree.rb +4 -2
  9. data/examples/appemail.rb +7 -3
  10. data/examples/appemaillb.rb +1 -1
  11. data/examples/appgcompose.rb +2 -2
  12. data/examples/appgmail.rb +1 -1
  13. data/examples/appmethods.rb +20 -2
  14. data/examples/atree.rb +9 -1
  15. data/examples/dbdemo.rb +460 -0
  16. data/examples/dirtree.rb +1 -1
  17. data/examples/menu1.rb +37 -5
  18. data/examples/multispl.rb +1 -1
  19. data/examples/rfe.rb +9 -2
  20. data/examples/splitp.rb +1 -1
  21. data/examples/sqlc.rb +6 -10
  22. data/examples/sqlm.rb +2 -20
  23. data/examples/sqlt.rb +408 -0
  24. data/examples/term2.rb +1 -1
  25. data/examples/test2.rb +169 -97
  26. data/examples/testapp.rb +1 -1
  27. data/examples/testapp2.rb +1 -1
  28. data/examples/testkeypress.rb +4 -2
  29. data/examples/testtable.rb +6 -0
  30. data/examples/testtpane.rb +35 -23
  31. data/examples/testvimsplit.rb +3 -2
  32. data/lib/rbcurse.rb +1 -1
  33. data/lib/rbcurse/action.rb +8 -0
  34. data/lib/rbcurse/app.rb +39 -23
  35. data/lib/rbcurse/extras/bottomline.rb +101 -13
  36. data/lib/rbcurse/extras/directorylist.rb +14 -5
  37. data/lib/rbcurse/extras/divider.rb +1 -1
  38. data/lib/rbcurse/extras/listselectable.rb +42 -8
  39. data/lib/rbcurse/extras/masterdetail.rb +2 -2
  40. data/lib/rbcurse/extras/scrollbar.rb +11 -2
  41. data/lib/rbcurse/extras/statusline.rb +56 -0
  42. data/lib/rbcurse/extras/stdscrwindow.rb +11 -0
  43. data/lib/rbcurse/extras/tabular.rb +2 -1
  44. data/lib/rbcurse/extras/tabularwidget.rb +60 -17
  45. data/lib/rbcurse/extras/viewer.rb +16 -4
  46. data/lib/rbcurse/keylabelprinter.rb +34 -4
  47. data/lib/rbcurse/listeditable.rb +5 -1
  48. data/lib/rbcurse/listkeys.rb +1 -1
  49. data/lib/rbcurse/listscrollable.rb +15 -8
  50. data/lib/rbcurse/rbasiclistbox.rb +44 -23
  51. data/lib/rbcurse/rcommandwindow.rb +8 -14
  52. data/lib/rbcurse/rdialogs.rb +187 -2
  53. data/lib/rbcurse/rlistbox.rb +38 -19
  54. data/lib/rbcurse/rmenu.rb +313 -93
  55. data/lib/rbcurse/rmessagebox.rb +3 -2
  56. data/lib/rbcurse/rmulticontainer.rb +5 -3
  57. data/lib/rbcurse/rmultisplit.rb +2 -11
  58. data/lib/rbcurse/rmultitextview.rb +4 -5
  59. data/lib/rbcurse/rtabbedpane.rb +223 -69
  60. data/lib/rbcurse/rtable.rb +6 -10
  61. data/lib/rbcurse/rtextarea.rb +57 -36
  62. data/lib/rbcurse/rtextview.rb +12 -15
  63. data/lib/rbcurse/rtree.rb +79 -22
  64. data/lib/rbcurse/rvimsplit.rb +16 -25
  65. data/lib/rbcurse/rwidget.rb +376 -523
  66. data/lib/rbcurse/tree/treecellrenderer.rb +24 -11
  67. data/lib/rbcurse/tree/treemodel.rb +1 -1
  68. data/lib/ver/window.rb +130 -66
  69. metadata +5 -3
  70. data/examples/term.rb +0 -48
data/examples/testapp.rb CHANGED
@@ -24,7 +24,7 @@ class Testy
24
24
  app = App.new
25
25
  $log.debug " APP : value #{value}" if $log.debug?
26
26
  header = app.app_header "rbcurse #{Rbcurse::VERSION} " , :text_center => " #{@value} Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
27
- app.message "Press F1 to exit from here #{@value} "
27
+ app.message "Press F10 to exit from here #{@value} "
28
28
 
29
29
  app.stack :margin_top => 2, :margin => 5, :width => 30 do |s|
30
30
  app.label "Hello: ", :attr => :reverse
data/examples/testapp2.rb CHANGED
@@ -30,7 +30,7 @@ class Testy
30
30
  App.new do |app|
31
31
  $log.debug " APP : value #{value}" if $log.debug?
32
32
  header = app.app_header "rbcurse #{Rbcurse::VERSION} ", :text_center => " #{@value} Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
33
- app.message "Press F1 to exit from here #{@value} "
33
+ app.message "Press F10 to exit from here #{@value} "
34
34
 
35
35
  app.stack :margin_top => 2, :margin => 5, :width => 30 do |s|
36
36
  app.label "Hello: ", :attr => :reverse
@@ -36,8 +36,10 @@ if $0 == __FILE__
36
36
  auto_scroll true
37
37
  title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
38
38
  end
39
- @help = "q to quit. Use any key of key combination to see what's caught.: #{$0} Check logger too"
40
- RubyCurses::Label.new @form, {'text' => @help, "row" => 21, "col" => 2, "color" => "yellow"}
39
+ help = "q to quit. Check keys. F1..10, C-a..z, Alt a-zA-Z0-9, C-left,rt, Sh-F5..10 .: #{$0}"
40
+ help1 = "Press in quick succession: 1) M-[, w and (2) M-[, M-w. (3) M-Sh-O, w."
41
+ RubyCurses::Label.new @form, {'text' => help, "row" => 21, "col" => 2, "color" => "yellow"}
42
+ RubyCurses::Label.new @form, {'text' => help1, "row" => 22, "col" => 2, "color" => "green"}
41
43
 
42
44
  @form.repaint
43
45
  @window.wrefresh
@@ -232,6 +232,7 @@ if $0 == __FILE__
232
232
  @window.wrefresh
233
233
  Ncurses::Panel.update_panels
234
234
  while((ch = @window.getchar()) != ?\C-q.getbyte(0) )
235
+ begin
235
236
  colcount = tcm.column_count-1
236
237
  s = keycode_tos ch
237
238
  keylabel.text = "Pressed #{ch} , #{s}"
@@ -248,6 +249,11 @@ if $0 == __FILE__
248
249
 
249
250
  @form.repaint
250
251
  @window.wrefresh
252
+ rescue => ex
253
+ $log.debug( ex) if ex
254
+ $log.debug(ex.backtrace.join("\n")) if ex
255
+ alert ex.to_s
256
+ end
251
257
  end
252
258
  end
253
259
  rescue => ex
@@ -15,9 +15,6 @@
15
15
  # M-l in button form will scroll. M-h to scroll left.
16
16
  # dd to kill a tab, u to undo kill, or p/P to paste deleted tab
17
17
  #
18
- #$LOAD_PATH << "/Users/rahul/work/projects/rbcurse/"
19
- require 'rubygems'
20
- #require 'ncurses' # FFI
21
18
  require 'logger'
22
19
  require 'rbcurse'
23
20
  require 'rbcurse/rtabbedpane'
@@ -45,13 +42,16 @@ class TestTabbedPane
45
42
  col 8
46
43
  #button_type :ok
47
44
  end
45
+ @tab1 = @tp.add_tab "&TextView" #, textview
46
+ f1 = @tp.form(@tab1)
48
47
 
49
- textview = TextView.new do
48
+ textview = TextView.new f1 do
50
49
  name "myView"
51
- row 4
50
+ row 0
52
51
  col 0
53
- #width w-0
52
+ width w-0
54
53
  #height h-4
54
+ height h-2
55
55
  title "README.mrku"
56
56
  title_attrib 'bold'
57
57
  print_footer true
@@ -61,20 +61,19 @@ class TestTabbedPane
61
61
  textview.set_content content #, :WRAP_WORD
62
62
  #textview.show_caret = true
63
63
 
64
- @tab1 = @tp.add_tab "&TextView", textview
65
- #@tabl.add_component textview
66
- #f1 = @tab1.form
64
+ #@tab1 = @tp.add_tab "&TextView" #, textview
65
+ #f1 = @tp.form(@tab1)
66
+ #textview.set_form(f1)
67
+ #@tp.configure_component(textview)
67
68
 
68
69
 
69
70
 
70
71
  #f2 = @tab2.form
72
+ #@tab2 = @tp.add_tab "&Settings" #, texta
73
+ #f2 = @tp.form(@tab2)
71
74
  r = 4
72
75
  texta = TextArea.new do
73
- name "myText"
74
- #row r
75
- #col 2
76
- #width w-5
77
- #height h-5
76
+ name "myText"
78
77
  title "EditMe.txt"
79
78
  title_attrib 'bold'
80
79
  print_footer true
@@ -105,9 +104,25 @@ class TestTabbedPane
105
104
  col 5
106
105
  end
107
106
  end
108
- tab3 = @tp.add_tab "S&ongs"
109
- #f3 = tab3.form
110
- #f3 = @tp.form tab3
107
+ x = RubyCurses::Field.new f3 do
108
+ name 'username'
109
+ row row+6
110
+ bgcolor 'white'
111
+ color 'black'
112
+ col 15
113
+ display_length 20
114
+ set_label Label.new f3, {'text' => 'User Name', 'mnemonic'=> 'u'}
115
+ end
116
+ x = RubyCurses::Field.new f3 do
117
+ name 'nick'
118
+ row row+7
119
+ bgcolor 'white'
120
+ color 'black'
121
+ col 15
122
+ display_length 10
123
+ set_label Label.new f3, {'text' => 'Nick Name', 'mnemonic'=> 'n'}
124
+ end
125
+
111
126
  data = [["Pathetique",3,"Tchaikovsky",3.21, true, "WIP"],
112
127
  ["Ali Maula Ali Maula",3,"NFAK",3.47, true, "WIP"],
113
128
  ["Tera Hijr Mera Nasib",92,"Razia Sultan",412, true, "Fin"],
@@ -138,17 +153,14 @@ class TestTabbedPane
138
153
  # We can skip sizing too for large components, so comp will fill the TP.
139
154
  atable = Table.new do
140
155
  name "mytable"
141
- #row row
142
- #col 0
143
- #width 76
144
- #height h - 4
145
156
  #title "A Table"
146
157
  #title_attrib (Ncurses::A_REVERSE | Ncurses::A_BOLD)
147
158
  cell_editing_allowed true
148
159
  editing_policy :EDITING_AUTO
149
160
  set_data data, colnames
150
161
  end
151
- tab3.component = atable
162
+ tab3 = @tp.add_tab "S&ongs", atable
163
+ #tab3.component = atable
152
164
  sel_col = Variable.new 0
153
165
  sel_col.value = 0
154
166
  tcm = atable.get_table_column_model
@@ -160,7 +172,7 @@ class TestTabbedPane
160
172
  tcm.column(3).width 7
161
173
  tcm.column(4).width 5
162
174
  tcm.column(5).width 6
163
- @help = "F1 to quit. M-s M-t M-e M-o, TAB, M-x to add tab #{$0} Check logger too"
175
+ @help = "F1 to quit. M-s M-t M-e M-o, TAB. M-x to add tab #{$0} M-h/M-l to scroll tabs"
164
176
  RubyCurses::Label.new @form, {'text' => @help, "row" => r+h+2, "col" => 2, "color" => "yellow"}
165
177
 
166
178
  # M-x when inside the buttons form will create a new tab
@@ -46,6 +46,7 @@ class Tester
46
46
  @vim.add lb1, :FIRST, :AUTO #nil #0.7:AUTO
47
47
  @vim.add ["mercury","venus","earth","mars","jupiter", "saturn"], :FIRST, :AUTO
48
48
  @vim.add alist, :FIRST, 0.4, stfl
49
+ #@vim.add alist, :FIRST, nil, stfl
49
50
  @vim.add alist.shuffle, :FIRST, nil, stfl
50
51
  @vim.add lb2, :SECOND, :AUTO
51
52
  @vim.add str, :SECOND, :AUTO
@@ -69,14 +70,14 @@ class Tester
69
70
  k_button.command { |form| @vim.decrease_weight }
70
71
 
71
72
  #
72
- @help = "F1 to quit. "
73
+ @help = "F10 to quit. "
73
74
  RubyCurses::Label.new @form, {'text' => @help, "row" => 1, "col" => 2, "color" => "yellow"}
74
75
  @form.repaint
75
76
  @window.wrefresh
76
77
  Ncurses::Panel.update_panels
77
78
  ctr = 0
78
79
  row = 2
79
- while((ch = @window.getchar()) != KEY_F1 )
80
+ while((ch = @window.getchar()) != Ncurses::KEY_F10 )
80
81
  ret = @form.handle_key(ch)
81
82
  @window.wrefresh
82
83
  #ret = @vim.handle_key ch
data/lib/rbcurse.rb CHANGED
@@ -4,5 +4,5 @@ require 'ver/window'
4
4
  require 'rbcurse/rwidget'
5
5
  require 'rbcurse/rdialogs'
6
6
  class Rbcurse
7
- VERSION = '1.3.0'
7
+ VERSION = '1.4.0'
8
8
  end
@@ -3,6 +3,14 @@ require 'rbcurse/rwidget'
3
3
  include RubyCurses
4
4
  module RubyCurses
5
5
  ## encapsulates behaviour allowing centralization
6
+ # == Example
7
+ # a = Action.new("&New Row") { commands }
8
+ # a.accelerator "Alt N"
9
+ # menu.add(a)
10
+ # b = Button.new form do
11
+ # action a
12
+ # ...
13
+ # end
6
14
  class Action < Proc
7
15
  include EventHandler
8
16
  include ConfigSetup
data/lib/rbcurse/app.rb CHANGED
@@ -9,7 +9,6 @@ Todo:
9
9
  Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
10
 
11
11
  =end
12
- #require 'ncurses'
13
12
  require 'logger'
14
13
  require 'rbcurse'
15
14
 
@@ -19,9 +18,8 @@ $tt.name = "$tt"
19
18
  require 'forwardable'
20
19
  module Kernel
21
20
  extend Forwardable
22
- def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list, :say_with_pause
21
+ def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list, :say_with_pause, :hide_bottomline
23
22
  end
24
- #include Ncurses # FFI 2011-09-8
25
23
  include RubyCurses
26
24
  include RubyCurses::Utils
27
25
  include Io
@@ -83,9 +81,6 @@ module RubyCurses
83
81
 
84
82
  extend Forwardable
85
83
  def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list
86
- #@tt = Bottomline.new @window, @message_row
87
- #extend Forwardable
88
- #def_delegators :@tt, :ask, :say, :agree, :choose
89
84
 
90
85
  # TODO: i should be able to pass window coords here in config
91
86
  # :title
@@ -122,11 +117,12 @@ module RubyCurses
122
117
  colors = Ncurses.COLORS
123
118
  $log.debug "START #{colors} colors --------- #{$0} win: #{@window} "
124
119
  end
120
+ =begin
121
+ # trying without 2011-10-8
125
122
  require 'rbcurse/extras/stdscrwindow'
126
123
  awin = StdscrWindow.new
127
124
  $tt.window = awin; $tt.message_row = @message_row
128
- # window created in run !!!
129
- #$tt.window = @window; $tt.message_row = @message_row
125
+ =end
130
126
  end
131
127
  def logger; return $log; end
132
128
  def close
@@ -134,6 +130,7 @@ module RubyCurses
134
130
  @window.destroy if !@window.nil?
135
131
  $log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} "
136
132
  if @stop_ncurses_on_close
133
+ $tt.destroy # added on 2011-10-9 since we created a window, but only hid it after use
137
134
  VER::stop_ncurses
138
135
  $log.debug " CLOSING NCURSES"
139
136
  end
@@ -187,19 +184,24 @@ module RubyCurses
187
184
  # updates a global var with text. Calling app has to set up a Variable with that name and attach to
188
185
  # a label so it can be printed.
189
186
  def message text
187
+ $status_message.value = text # trying out 2011-10-9
190
188
  @message.value = text
191
189
  end
192
190
  def message_row row
193
- @message_label.row = row
191
+ raise "Please use create_message_label first as message_label is no longer default behaviour" unless @message_label
192
+ @message_label.row = row
194
193
  end
195
194
  # during a process, when you wish to update status, since ordinarily the thread is busy
196
195
  # and form does not get control back, so the window won't refresh.
197
196
  # NOTE: use this only if +message+ is not working
198
197
  # XXX Not sure if this is working after move to ffi-ncurses, check the demos
199
198
  def message_immediate text
199
+ $status_message.value = text # trying out 2011-10-9 user needs to use in statusline command
200
200
  message text
201
- @message_label.repaint
202
- @window.refresh
201
+ if @message_label
202
+ @message_label.repaint
203
+ @window.refresh
204
+ end
203
205
  end
204
206
  # NOTE XXX using stdscr results in the screen going black if a dialog
205
207
  # or other window is popped up, this was great but has not worked out.
@@ -208,23 +210,29 @@ module RubyCurses
208
210
  # so at end of printing raw_messages, use message() for final status.
209
211
  # Usage: application is inside a long processing loop and wishes to print ongoing status
210
212
  # (similar to message_immediate) but faster and less involved
213
+ # @deprecated since it uses stdscr. Use say_with_pause or use rdialogs status_window, see test2.rb
211
214
  def raw_message text
215
+ $log.warn "WARNING: don't use this method as it uses stdscr. Use rdialogs statuswindow."
216
+ row = @message_label ? @message_label.row : Ncurses.LINES-1
212
217
  # experimentally trying stdscr instead of label
213
218
  scr = FFI::NCurses.stdscr
214
219
  text = "%-80s" % text
215
- Ncurses.mvprintw @message_label.row ,0, text
220
+ Ncurses.mvprintw row ,0, text
216
221
  #@_stext ||= ""
217
222
  #@_stext << text
218
223
  ## appending is quite a pain, maybe we should make it separate.
219
224
  #stext = "%-80s" % @_stext
220
- #Ncurses.mvprintw @message_label.row ,0, stext[-80..-1]
225
+ #Ncurses.mvprintw row ,0, stext[-80..-1]
221
226
  #scr.refresh() # NW w FFI XXX
222
227
  #FFI::NCurses.refresh
223
228
  end
224
229
  # shows a simple progress bar on last row, using stdscr
225
230
  # @param [Float, Array<Fixnum,Fixnum>] percentage, or part/total
226
231
  # If Array of two numbers is given then also print part/total on left of bar
232
+ # @deprecated - don't use stdscr at all, use rdialogs status_window (see test2.rb)
227
233
  def raw_progress arg
234
+ $log.warning "WARNING: don't use this method as it uses stdscr"
235
+ row = @message_label ? @message_label.row : Ncurses.LINES-1
228
236
  s = nil
229
237
  case arg
230
238
  when Array
@@ -241,8 +249,8 @@ module RubyCurses
241
249
  startcol = endcol - 12
242
250
  stext = ("=" * (pc*10).to_i)
243
251
  text = "[" + "%-10s" % stext + "]"
244
- Ncurses.mvprintw( @message_label.row ,startcol-10, s) if s
245
- Ncurses.mvprintw @message_label.row ,startcol, text
252
+ Ncurses.mvprintw( row ,startcol-10, s) if s
253
+ Ncurses.mvprintw row ,startcol, text
246
254
  #scr.refresh() # XXX FFI NW
247
255
 
248
256
  end
@@ -410,7 +418,7 @@ module RubyCurses
410
418
  alert "#{self.class} does not respond to #{cmd} "
411
419
  ret = false
412
420
  ret = execute_this(cmd, *cmdline) if respond_to?(:execute_this, true)
413
- say("#{self.class} does not respond to #{cmd} ", :color_pair => $promptcolor) unless ret
421
+ say_with_pause("#{self.class} does not respond to #{cmd} ", :color_pair => $promptcolor) unless ret
414
422
  # should be able to say in red as error
415
423
  end
416
424
  end
@@ -726,10 +734,13 @@ module RubyCurses
726
734
  require 'rbcurse/applicationheader'
727
735
  header = ApplicationHeader.new @form, title, config, &block
728
736
  end
737
+
738
+ # prints pine-like key labels
729
739
  def dock labels, config={}, &block
730
740
  require 'rbcurse/keylabelprinter'
731
741
  klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block
732
742
  end
743
+
733
744
  def link *args, &block
734
745
  require 'rbcurse/extras/rlink'
735
746
  config = {}
@@ -1060,16 +1071,18 @@ module RubyCurses
1060
1071
  return cmd if opts.include? cmd
1061
1072
  matches = opts.grep Regexp.new("^#{cmd}")
1062
1073
  end
1074
+ # Now i am not creating this unless user wants it. Pls avoid it.
1075
+ # Use either say_with_pause, or put $status_message in command of statusline
1076
+ # @deprecated
1077
+ def create_message_label row=Ncurses.LINES-1
1078
+ @message_label = RubyCurses::Label.new @form, {:text_variable => @message, :name=>"message_label",:row => row, :col => 0, :display_length => Ncurses.COLS, :height => 1, :color => :white}
1079
+ end
1063
1080
  def run &block
1064
1081
  begin
1065
1082
 
1066
1083
  # check if user has passed window coord in config, else root window
1067
1084
  @window = VER::Window.root_window
1068
- #$tt.window = @window; $tt.message_row = @message_row
1069
1085
  awin = @window
1070
- #require 'rbcurse/extras/stdscrwindow'
1071
- #awin = StdscrWindow.new
1072
- #$tt.window = awin; $tt.message_row = @message_row
1073
1086
  catch(:close) do
1074
1087
  @form = Form.new @window
1075
1088
  @form.bind_key([?\C-x, ?c]) { suspend(false) do
@@ -1103,7 +1116,7 @@ module RubyCurses
1103
1116
  rcmd = _resolve_command(opts, cmd) if !opts.include?(cmd)
1104
1117
  if rcmd.size == 1
1105
1118
  cmd = rcmd.first
1106
- else
1119
+ elsif !rcmd.empty?
1107
1120
  say_with_pause "Cannot resolve #{cmd}. Matches are: #{rcmd} "
1108
1121
  end
1109
1122
  end
@@ -1121,14 +1134,17 @@ module RubyCurses
1121
1134
  end
1122
1135
  end
1123
1136
  else
1124
- say("Command [#{cmd}] not supported by #{self.class} ")
1137
+ say_with_pause("Command [#{cmd}] not supported by #{self.class} ", :color_pair => $promptcolor)
1125
1138
  end
1126
1139
  end
1127
1140
  }
1128
1141
  @form.bind_key(KEY_F1){ display_app_help }
1142
+ @form.bind_key([?q,?q]){ throw :close } if $log.debug?
1143
+
1129
1144
  @message = Variable.new
1130
1145
  @message.value = ""
1131
- @message_label = RubyCurses::Label.new @form, {:text_variable => @message, :name=>"message_label",:row => Ncurses.LINES-1, :col => 0, :display_length => Ncurses.COLS, :height => 1, :color => :white}
1146
+ $status_message ||= Variable.new # remember there are multiple levels of apps
1147
+ $status_message.value = ""
1132
1148
  $error_message.update_command { @message.set_value($error_message.value) }
1133
1149
  if block
1134
1150
  begin
@@ -15,6 +15,11 @@ require 'pathname'
15
15
 
16
16
  May later use a Label and Field.
17
17
 
18
+ NOTE : Pls avoid directly using this class. I am trying to redo this so ask, agree and say
19
+ can create their own window and be done with it. The hurdle in that is that ask calls
20
+ say, so when to close the window is not clear within say. Some shakeup is expected by
21
+ 1.4.0 or so.
22
+
18
23
  =end
19
24
  module RubyCurses
20
25
 
@@ -83,7 +88,20 @@ module RubyCurses
83
88
  attr_accessor :name # for debugging
84
89
  def initialize win=nil, row=nil
85
90
  @window = win
86
- @message_row = row
91
+ #@window.wrefresh
92
+ #Ncurses::Panel.update_panels
93
+ #@message_row = row
94
+ @message_row = 0 # 2011-10-8
95
+ end
96
+ #
97
+ # create a window at bottom and show and hide it.
98
+ # Causing a stack overflow since Window creates a bottomline too !
99
+ #
100
+ def _create_footer_window h = 1 , w = Ncurses.COLS, t = Ncurses.LINES-1, l = 0
101
+ ewin = VER::Window.new(h, w , t, l)
102
+ #ewin.bkgd(Ncurses.COLOR_PAIR($promptcolor));
103
+ @window = ewin
104
+ return ewin
87
105
  end
88
106
 
89
107
  class QuestionError < StandardError
@@ -947,7 +965,10 @@ module RubyCurses
947
965
  end
948
966
  end
949
967
  def ask(question, answer_type=String, &details)
950
- #clear_line 80
968
+ $log.debug "XXXX inside ask win #{@window} "
969
+ #@window.show #unless @window.visible?
970
+ @window ||= _create_footer_window
971
+
951
972
  @question ||= Question.new(question, answer_type, &details)
952
973
  say(@question) #unless @question.echo == true
953
974
 
@@ -961,6 +982,7 @@ module RubyCurses
961
982
  end
962
983
 
963
984
  begin
985
+ # FIXME a C-c still returns default to user !
964
986
  @answer = @question.answer_or_default(get_response)
965
987
  unless @question.valid_answer?(@answer)
966
988
  explain_error(:not_valid)
@@ -1010,10 +1032,38 @@ module RubyCurses
1010
1032
  rescue Question::NoAutoCompleteMatch
1011
1033
  explain_error(:no_completion)
1012
1034
  retry
1035
+ rescue Interrupt
1036
+ $log.warn "User interrupted ask() get_response does not want operation to proceed"
1037
+ return nil
1013
1038
  ensure
1014
1039
  @question = nil # Reset Question object.
1040
+ hide # assuming this method made it visible, not sure if this is called.
1041
+ end
1042
+ end
1043
+ #
1044
+ # bottomline user has to hide window if he called say().
1045
+ # Call this if you find the window persists after using some method from here
1046
+ # usually say or ask.
1047
+ #
1048
+ # @param [int, float] time to sleep before hiding window.
1049
+ #
1050
+ def hide wait=nil
1051
+ if @window
1052
+ sleep(wait) if wait
1053
+ @window.hide
1054
+ @window.wrefresh
1055
+ #Ncurses::Panel.update_panels
1015
1056
  end
1016
1057
  end
1058
+ alias :hide_bottomline :hide
1059
+ #
1060
+ # destroy window, to be called by app when shutting down
1061
+ # since we are normally hiding the window only.
1062
+ def destroy
1063
+ $log.debug "bottomline destroy... #{@window} "
1064
+ @window.destroy if @window
1065
+ @window = nil
1066
+ end
1017
1067
 
1018
1068
  #
1019
1069
  # The basic output method for HighLine objects.
@@ -1025,14 +1075,21 @@ module RubyCurses
1025
1075
  # question. Also, ansi color constants will not work. Be careful what ruby code
1026
1076
  # you pass in.
1027
1077
  #
1078
+ # NOTE: This uses a window, so it will persist in the last row. You must call
1079
+ # hide_bottomline to remove the window. It is preferable to call say_with_pause
1080
+ # from user programs
1081
+ #
1028
1082
  def say statement, config={}
1083
+ @window ||= _create_footer_window
1084
+ #@window.show unless @window.visible? # this will need to be hidden manually NOTE
1085
+ $log.debug "XXX: inside say win #{@window} !"
1029
1086
  case statement
1030
1087
  when Question
1031
1088
 
1032
1089
  if config.has_key? :color_pair
1033
1090
  $log.debug "INSIDE QUESTION 2 " if $log.debug?
1034
1091
  else
1035
- $log.debug "XXXX SAY using #{statement.color_pair} " if $log.debug?
1092
+ $log.debug "XXXX SAY using colorpair: #{statement.color_pair} " if $log.debug?
1036
1093
  config[:color_pair] = statement.color_pair
1037
1094
  end
1038
1095
  else
@@ -1041,15 +1098,22 @@ module RubyCurses
1041
1098
  statement = statement.to_str
1042
1099
  template = ERB.new(statement, nil, "%")
1043
1100
  statement = template.result(binding)
1044
- #puts statement
1101
+
1045
1102
  @prompt_length = statement.length # required by ask since it prints after
1046
1103
  @statement = statement #
1047
1104
  clear_line
1048
1105
  print_str statement, config
1049
1106
  end
1107
+ #
1108
+ # display some text at bottom and wait for a key before hiding window
1109
+ #
1050
1110
  def say_with_pause statement, config={}
1111
+ @window ||= _create_footer_window
1051
1112
  say statement, config
1113
+ @window.wrefresh
1114
+ Ncurses::Panel.update_panels
1052
1115
  ch=@window.getchar()
1116
+ hide
1053
1117
  end
1054
1118
  # A helper method for sending the output stream and error and repeat
1055
1119
  # of the question.
@@ -1065,10 +1129,14 @@ module RubyCurses
1065
1129
  end
1066
1130
  end
1067
1131
 
1132
+ #
1133
+ # Internal method for printing a string
1134
+ #
1068
1135
  def print_str(text, config={})
1069
1136
  win = config.fetch(:window, @window) # assuming its in App
1070
- x = config.fetch :x, @message_row # Ncurses.LINES-1
1137
+ x = config.fetch :x, 0 # @message_row # Ncurses.LINES-1, 0 since one line window 2011-10-8
1071
1138
  y = config.fetch :y, 0
1139
+ $log.debug "XXX: print_str #{win} with text : #{text} at #{x} #{y} "
1072
1140
  color = config[:color_pair] || $datacolor
1073
1141
  raise "no window for ask print in #{self.class} name: #{name} " unless win
1074
1142
  color=Ncurses.COLOR_PAIR(color);
@@ -1151,12 +1219,14 @@ module RubyCurses
1151
1219
  curpos -= 1 if curpos > 0
1152
1220
  len -= 1 if len > @prompt_length
1153
1221
  win.move r, c+len # since getchar is not going back on del and bs wmove to move FFIWINDOW
1222
+ win.wrefresh
1154
1223
  next
1155
1224
  when KEY_RIGHT
1156
1225
  if curpos < str.length
1157
1226
  curpos += 1 #if curpos < str.length
1158
1227
  len += 1
1159
1228
  win.move r, c+len # since getchar is not going back on del and bs
1229
+ win.wrefresh
1160
1230
  end
1161
1231
  next
1162
1232
  when ?\C-a.getbyte(0)
@@ -1323,6 +1393,7 @@ module RubyCurses
1323
1393
  print_str(@question.echo * str.length, :y => @prompt_length+0)
1324
1394
  end
1325
1395
  win.move r, c+len # more for arrow keys, curpos may not be end
1396
+ win.wrefresh # 2011-10-10
1326
1397
  prevchar = ch
1327
1398
  end
1328
1399
  $log.debug "XXXW bottomline: after while loop"
@@ -1374,6 +1445,9 @@ module RubyCurses
1374
1445
  if ret == 0
1375
1446
  return @question.change_case(@question.remove_whitespace(str))
1376
1447
  end
1448
+ if ret == -1
1449
+ raise Interrupt
1450
+ end
1377
1451
  return ""
1378
1452
  end
1379
1453
  def agree( yes_or_no_question, character = nil )
@@ -1441,22 +1515,28 @@ module RubyCurses
1441
1515
  end
1442
1516
  # Allows a selection in which options are shown over prompt. As user types
1443
1517
  # options are narrowed down.
1518
+ # NOTE: For a directory we are not showing a slash, so currently you
1519
+ # have to enter the slash manually when searching.
1444
1520
  # FIXME we can put remarks in fron as in memacs such as [No matches] or [single completion]
1445
1521
  # @param [Array] a list of items to select from
1446
1522
  # NOTE: if you use this please copy it to your app. This does not conform to highline's
1447
1523
  # choose, and I'd like to somehow get it to be identical.
1448
1524
  #
1449
1525
  def choose list1, config={}
1526
+ dirlist = true
1450
1527
  case list1
1451
1528
  when NilClass
1452
- list1 = Dir.glob("*")
1529
+ #list1 = Dir.glob("*")
1530
+ list1 = Dir.glob("*").collect { |f| File.directory?(f) ? f+"/" : f }
1453
1531
  when String
1454
- list1 = Dir.glob(list1)
1532
+ list1 = Dir.glob(list1).collect { |f| File.directory?(f) ? f+"/" : f }
1455
1533
  when Array
1534
+ dirlist = false
1456
1535
  # let it be, that's how it should come
1457
1536
  else
1458
1537
  # Dir listing as default
1459
- list1 = Dir.glob("*")
1538
+ #list1 = Dir.glob("*")
1539
+ list1 = Dir.glob("*").collect { |f| File.directory?(f) ? f+"/" : f }
1460
1540
  end
1461
1541
  require 'rbcurse/rcommandwindow'
1462
1542
  prompt = config[:prompt] || "Choose: "
@@ -1466,12 +1546,24 @@ module RubyCurses
1466
1546
  w = rc.window
1467
1547
  rc.display_menu list1
1468
1548
  # earlier wmove bombed, now move is (window.rb 121)
1469
- str = ask(prompt) { |q| q.change_proc = Proc.new { |str| w.wmove(1,1) ; w.wclrtobot; l = list1.select{|e| e.index(str)==0} ; rc.display_menu l; l} }
1549
+ str = ask(prompt) { |q| q.change_proc = Proc.new { |str| w.wmove(1,1) ; w.wclrtobot;
1550
+ l = list1.select{|e| e.index(str)==0} ;
1551
+ if (l.size == 0 || str[-1]=='/') && dirlist
1552
+ # used to help complete directories so we can drill up and down
1553
+ #l = Dir.glob(str+"*")
1554
+ l = Dir.glob(str +"*").collect { |f| File.directory?(f) ? f+"/" : f }
1555
+ end
1556
+ rc.display_menu l;
1557
+ l
1558
+ } }
1470
1559
  # need some validation here that its in the list TODO
1471
1560
  ensure
1472
1561
  rc.destroy
1473
1562
  rc = nil
1563
+ hide_bottomline # since we called ask() we need to close bottomline
1474
1564
  end
1565
+ hide_bottomline # since we called ask() we need to close bottomline
1566
+ return str
1475
1567
  end
1476
1568
  def display_text_interactive text, config={}
1477
1569
  require 'rbcurse/rcommandwindow'
@@ -1630,10 +1722,6 @@ if __FILE__ == $PROGRAM_NAME
1630
1722
  App.new do
1631
1723
  header = app_header "rbcurse 1.2.0", :text_center => "**** Demo", :text_right =>"New Improved!", :color => :black, :bgcolor => :white, :attr => :bold
1632
1724
  message "Press F1 to exit from here"
1633
- ######## $tt.window = @window; $tt.message_row = @message_row
1634
- #@tt = Bottomline.new @window, @message_row
1635
- #extend Forwardable
1636
- #def_delegators :@tt, :ask, :say, :agree, :choose
1637
1725
 
1638
1726
  #stack :margin_top => 2, :margin => 5, :width => 30 do
1639
1727
  #end # stack