rbcurse 1.3.0 → 1.4.0

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