rbcurse 1.4.1 → 1.5.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/CHANGELOG +31 -0
  2. data/README.markdown +69 -11
  3. data/VERSION +1 -1
  4. data/lib/rbcurse.rb +5 -5
  5. metadata +10 -198
  6. data/Makefile +0 -21
  7. data/Manifest.txt +0 -91
  8. data/TODO +0 -372
  9. data/TODO2.txt +0 -118
  10. data/examples/README.txt +0 -67
  11. data/examples/abasiclist.rb +0 -33
  12. data/examples/alpmenu.rb +0 -42
  13. data/examples/app.rb +0 -859
  14. data/examples/app.sample +0 -10
  15. data/examples/appdirtree.rb +0 -75
  16. data/examples/appemail.rb +0 -191
  17. data/examples/appemaillb.rb +0 -308
  18. data/examples/appgcompose.rb +0 -315
  19. data/examples/atree.rb +0 -64
  20. data/examples/common/file.rb +0 -40
  21. data/examples/common/rmail.rb +0 -257
  22. data/examples/data.txt +0 -683
  23. data/examples/data/README.markdown +0 -9
  24. data/examples/data/brew.txt +0 -38
  25. data/examples/data/color.2 +0 -37
  26. data/examples/data/gemlist.txt +0 -60
  27. data/examples/data/lotr.txt +0 -12
  28. data/examples/data/ports.txt +0 -136
  29. data/examples/data/tasks.txt +0 -27
  30. data/examples/data/todocsv.csv +0 -28
  31. data/examples/data/unix1.txt +0 -21
  32. data/examples/data/unix2.txt +0 -11
  33. data/examples/dbdemo.rb +0 -495
  34. data/examples/deprecated/appgmail.rb +0 -952
  35. data/examples/deprecated/splitp.rb +0 -56
  36. data/examples/deprecated/testscrolllb.rb +0 -86
  37. data/examples/deprecated/testscrollp.rb +0 -88
  38. data/examples/deprecated/testscrollta.rb +0 -80
  39. data/examples/deprecated/testscrolltable.rb +0 -165
  40. data/examples/deprecated/testsplit.rb +0 -87
  41. data/examples/deprecated/testsplit2.rb +0 -123
  42. data/examples/deprecated/testsplit3.rb +0 -215
  43. data/examples/deprecated/testsplit3_1.rb +0 -244
  44. data/examples/deprecated/testsplit3a.rb +0 -215
  45. data/examples/deprecated/testsplit3b.rb +0 -237
  46. data/examples/deprecated/testsplitta.rb +0 -148
  47. data/examples/deprecated/testsplittv.rb +0 -142
  48. data/examples/deprecated/testsplittvv.rb +0 -144
  49. data/examples/deprecated/testtpane.rb +0 -215
  50. data/examples/deprecated/testtpane2.rb +0 -145
  51. data/examples/deprecated/testtpanetable.rb +0 -203
  52. data/examples/dirtree.rb +0 -88
  53. data/examples/experimental/resultsetdemo.rb +0 -280
  54. data/examples/experimental/testmform.rb +0 -35
  55. data/examples/experimental/testscroller.rb +0 -117
  56. data/examples/experimental/teststackflow.rb +0 -111
  57. data/examples/menu1.rb +0 -112
  58. data/examples/multispl.rb +0 -86
  59. data/examples/newmessagebox.rb +0 -130
  60. data/examples/newtabbedwindow.rb +0 -100
  61. data/examples/newtesttabp.rb +0 -121
  62. data/examples/qdfilechooser.rb +0 -68
  63. data/examples/rfe.rb +0 -1195
  64. data/examples/rfe_renderer.rb +0 -121
  65. data/examples/sqlc.rb +0 -454
  66. data/examples/sqlm.rb +0 -437
  67. data/examples/sqlt.rb +0 -408
  68. data/examples/status.txt +0 -68
  69. data/examples/table1.rb +0 -24
  70. data/examples/term2.rb +0 -84
  71. data/examples/test1.rb +0 -239
  72. data/examples/test2.rb +0 -674
  73. data/examples/testapp.rb +0 -44
  74. data/examples/testapp2.rb +0 -58
  75. data/examples/testchars.rb +0 -137
  76. data/examples/testcombo.rb +0 -91
  77. data/examples/testkeypress.rb +0 -66
  78. data/examples/testlistbox.rb +0 -113
  79. data/examples/testmenu.rb +0 -101
  80. data/examples/testmulticomp.rb +0 -70
  81. data/examples/testmulticontainer.rb +0 -94
  82. data/examples/testmultispl.rb +0 -199
  83. data/examples/testree.rb +0 -106
  84. data/examples/testtable.rb +0 -263
  85. data/examples/testtabp.rb +0 -107
  86. data/examples/testtodo.rb +0 -584
  87. data/examples/testvimsplit.rb +0 -112
  88. data/examples/testwsshortcuts.rb +0 -64
  89. data/examples/testwsshortcuts2.rb +0 -126
  90. data/examples/todo.db +0 -0
  91. data/examples/todo.yml +0 -191
  92. data/examples/viewtodo.rb +0 -574
  93. data/lib/rbcurse/action.rb +0 -40
  94. data/lib/rbcurse/app.rb +0 -1374
  95. data/lib/rbcurse/applicationheader.rb +0 -102
  96. data/lib/rbcurse/celleditor.rb +0 -112
  97. data/lib/rbcurse/checkboxcellrenderer.rb +0 -57
  98. data/lib/rbcurse/colormap.rb +0 -159
  99. data/lib/rbcurse/comboboxcellrenderer.rb +0 -30
  100. data/lib/rbcurse/common/ansiparser.rb +0 -117
  101. data/lib/rbcurse/common/appmethods.rb +0 -112
  102. data/lib/rbcurse/common/basestack.rb +0 -407
  103. data/lib/rbcurse/common/bordertitle.rb +0 -41
  104. data/lib/rbcurse/common/chunk.rb +0 -177
  105. data/lib/rbcurse/common/colorparser.rb +0 -71
  106. data/lib/rbcurse/common/keydefs.rb +0 -30
  107. data/lib/rbcurse/common/widgetshortcuts.rb +0 -302
  108. data/lib/rbcurse/defaultlistselectionmodel.rb +0 -79
  109. data/lib/rbcurse/deprecated/README.markdown +0 -12
  110. data/lib/rbcurse/deprecated/rscrollpane.rb +0 -512
  111. data/lib/rbcurse/deprecated/rsplitpane.rb +0 -894
  112. data/lib/rbcurse/deprecated/rsplitpane2.rb +0 -1009
  113. data/lib/rbcurse/deprecated/rviewport.rb +0 -204
  114. data/lib/rbcurse/experimental/README.markdown +0 -14
  115. data/lib/rbcurse/experimental/resultsettextview.rb +0 -585
  116. data/lib/rbcurse/experimental/stackflow.rb +0 -478
  117. data/lib/rbcurse/extras/bottomline.rb +0 -1850
  118. data/lib/rbcurse/extras/box.rb +0 -58
  119. data/lib/rbcurse/extras/directorylist.rb +0 -467
  120. data/lib/rbcurse/extras/directorytree.rb +0 -69
  121. data/lib/rbcurse/extras/divider.rb +0 -310
  122. data/lib/rbcurse/extras/focusmanager.rb +0 -31
  123. data/lib/rbcurse/extras/horizlist.rb +0 -203
  124. data/lib/rbcurse/extras/listselectable.rb +0 -264
  125. data/lib/rbcurse/extras/masterdetail.rb +0 -166
  126. data/lib/rbcurse/extras/menutree.rb +0 -63
  127. data/lib/rbcurse/extras/multiform.rb +0 -330
  128. data/lib/rbcurse/extras/multilinelabel.rb +0 -142
  129. data/lib/rbcurse/extras/newmessagebox.rb +0 -328
  130. data/lib/rbcurse/extras/newtabbedpane.rb +0 -612
  131. data/lib/rbcurse/extras/newtabbedwindow.rb +0 -68
  132. data/lib/rbcurse/extras/padreader.rb +0 -189
  133. data/lib/rbcurse/extras/rcomboedit.rb +0 -256
  134. data/lib/rbcurse/extras/resultsetbrowser.rb +0 -281
  135. data/lib/rbcurse/extras/rlink.rb +0 -27
  136. data/lib/rbcurse/extras/rmenulink.rb +0 -21
  137. data/lib/rbcurse/extras/scrollbar.rb +0 -143
  138. data/lib/rbcurse/extras/statusline.rb +0 -94
  139. data/lib/rbcurse/extras/stdscrwindow.rb +0 -309
  140. data/lib/rbcurse/extras/tableextended.rb +0 -40
  141. data/lib/rbcurse/extras/tabular.rb +0 -264
  142. data/lib/rbcurse/extras/tabularwidget.rb +0 -1150
  143. data/lib/rbcurse/extras/textpad.rb +0 -516
  144. data/lib/rbcurse/extras/viewer.rb +0 -136
  145. data/lib/rbcurse/io.rb +0 -850
  146. data/lib/rbcurse/keylabelprinter.rb +0 -178
  147. data/lib/rbcurse/listcellrenderer.rb +0 -140
  148. data/lib/rbcurse/listeditable.rb +0 -310
  149. data/lib/rbcurse/listkeys.rb +0 -37
  150. data/lib/rbcurse/listscrollable.rb +0 -564
  151. data/lib/rbcurse/listselectable.rb +0 -142
  152. data/lib/rbcurse/mapper.rb +0 -130
  153. data/lib/rbcurse/orderedhash.rb +0 -77
  154. data/lib/rbcurse/ractionevent.rb +0 -67
  155. data/lib/rbcurse/rbasiclistbox.rb +0 -768
  156. data/lib/rbcurse/rchangeevent.rb +0 -27
  157. data/lib/rbcurse/rcombo.rb +0 -238
  158. data/lib/rbcurse/rcommandwindow.rb +0 -587
  159. data/lib/rbcurse/rcontainer.rb +0 -415
  160. data/lib/rbcurse/rdialogs.rb +0 -451
  161. data/lib/rbcurse/rinputdataevent.rb +0 -47
  162. data/lib/rbcurse/rlistbox.rb +0 -1196
  163. data/lib/rbcurse/rmenu.rb +0 -939
  164. data/lib/rbcurse/rmessagebox.rb +0 -348
  165. data/lib/rbcurse/rmulticontainer.rb +0 -304
  166. data/lib/rbcurse/rmultisplit.rb +0 -722
  167. data/lib/rbcurse/rmultitextview.rb +0 -306
  168. data/lib/rbcurse/rpopupmenu.rb +0 -755
  169. data/lib/rbcurse/rprogress.rb +0 -118
  170. data/lib/rbcurse/rscrollform.rb +0 -418
  171. data/lib/rbcurse/rtabbedpane.rb +0 -1158
  172. data/lib/rbcurse/rtabbedwindow.rb +0 -167
  173. data/lib/rbcurse/rtable.rb +0 -1718
  174. data/lib/rbcurse/rtextarea.rb +0 -920
  175. data/lib/rbcurse/rtextview.rb +0 -761
  176. data/lib/rbcurse/rtree.rb +0 -780
  177. data/lib/rbcurse/rvimsplit.rb +0 -763
  178. data/lib/rbcurse/rwidget.rb +0 -2915
  179. data/lib/rbcurse/scrollable.rb +0 -301
  180. data/lib/rbcurse/table/tablecellrenderer.rb +0 -86
  181. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -98
  182. data/lib/rbcurse/tree/treecellrenderer.rb +0 -150
  183. data/lib/rbcurse/tree/treemodel.rb +0 -428
  184. data/lib/rbcurse/undomanager.rb +0 -188
  185. data/lib/rbcurse/vieditable.rb +0 -144
  186. data/lib/ver/keyboard.rb +0 -150
  187. data/lib/ver/keyboard2.rb +0 -170
  188. data/lib/ver/ncurses.rb +0 -218
  189. data/lib/ver/panel.rb +0 -162
  190. data/lib/ver/rpad.rb +0 -375
  191. data/lib/ver/window.rb +0 -882
  192. data/test/test_rbcurse.rb +0 -0
@@ -1,40 +0,0 @@
1
- require 'rbcurse/rwidget'
2
- #include Ncurses # FFI 2011-09-8
3
- include RubyCurses
4
- module RubyCurses
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
14
- class Action < Proc
15
- include EventHandler
16
- include ConfigSetup
17
- # name used on button or menu
18
- dsl_property :name
19
- dsl_property :enabled
20
- dsl_accessor :tooltip_text
21
- dsl_accessor :help_text
22
- dsl_accessor :mnemonic
23
- dsl_accessor :accelerator
24
-
25
- def initialize name, config={}, &block
26
- super &block
27
- @name = name
28
- @name.freeze
29
- @enabled = true
30
- config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
31
- @_events = [:FIRE]
32
- end
33
- def call
34
- return unless @enabled
35
- fire_handler :FIRE, self
36
- super
37
- end
38
- end # class
39
- end # module
40
-
data/lib/rbcurse/app.rb DELETED
@@ -1,1374 +0,0 @@
1
- =begin
2
- * Name: App
3
- * Description: Experimental Application class
4
- * Author: rkumar (arunachalesha)
5
- * file created 2010-09-04 22:10
6
- Todo:
7
- --------
8
- * License:
9
- Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
-
11
- =end
12
- require 'logger'
13
- require 'rbcurse'
14
-
15
- require 'rbcurse/extras/bottomline'
16
- $tt ||= RubyCurses::Bottomline.new
17
- $tt.name = "$tt"
18
- require 'forwardable'
19
- module Kernel
20
- extend Forwardable
21
- def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list, :say_with_pause, :hide_bottomline, :say_with_wait
22
- end
23
- include RubyCurses
24
- include RubyCurses::Utils
25
- include Io
26
- module RubyCurses
27
- extend self
28
-
29
- ##
30
- #
31
- # @since 1.2.0
32
- # TODO -
33
- # / combo
34
- # - popup
35
- # - promptmenu
36
- # - stack and flow should be objects in Form/App?, put in widget when creating
37
- # - box / rect
38
- # - para looks like a label that is more than one line, and calculates rows itself based on text
39
- # - multicontainer
40
- # - multitextview, multisplit
41
- # - tabbedpane
42
- # / table - more work regarding vim keys, also editable
43
- # - margin - is left offset
44
- # http://lethain.com/entry/2007/oct/15/getting-started-shoes-os-x/
45
- #
46
-
47
- class Widget
48
- def changed *args, &block
49
- bind :CHANGED, *args, &block
50
- end
51
- def leave *args, &block
52
- bind :LEAVE, *args, &block
53
- end
54
- def enter *args, &block
55
- bind :ENTER, *args, &block
56
- end
57
- # actually we already have command() for buttons
58
- def click *args, &block
59
- bind :PRESS, *args, &block
60
- end
61
- end
62
- class CheckBox
63
- # a little dicey XXX
64
- def text(*val)
65
- if val.empty?
66
- @value ? @onvalue : @offvalue
67
- else
68
- super
69
- end
70
- end
71
- end
72
- # This is the Application class which does the job of setting up the
73
- # environment, and closing it at the end.
74
- class App
75
- attr_reader :config
76
- attr_reader :form
77
- attr_reader :window
78
- attr_writer :quit_key
79
- # the row on which to prompt user for any inputs
80
- #attr_accessor :prompt_row # 2011-10-17 14:06:22
81
-
82
- extend Forwardable
83
- def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list
84
-
85
- # TODO: i should be able to pass window coords here in config
86
- # :title
87
- def initialize config={}, &block
88
- #$log.debug " inside constructor of APP #{config} "
89
- @config = config
90
- @app_row = @app_col = 0
91
- @stack = [] # stack's coordinates
92
- @flowstack = []
93
- @variables = {}
94
- # if we are creating child objects then we will not use outer form. this object will manage
95
- @current_object = []
96
- @_system_commands = %w{ bind_global bind_component field_help_text }
97
-
98
- init_vars
99
- $log.debug "XXX APP CONFIG: #{@config} " if $log.debug?
100
- run &block
101
- end
102
- def init_vars
103
- @quit_key ||= FFI::NCurses::KEY_F10
104
- # actually this should be maintained inside ncurses pack, so not loaded 2 times.
105
- # this way if we call an app from existing program, App won't start ncurses.
106
- unless $ncurses_started
107
- init_ncurses
108
- end
109
- $lastline = Ncurses.LINES - 1
110
- #@message_row = Ncurses.LINES-1
111
- #@prompt_row = @message_row # hope to use for ask etc # 2011-10-17 14:06:27
112
- unless $log
113
- path = File.join(ENV["LOGDIR"] || "./" ,"rbc13.log")
114
- file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
115
- $log = Logger.new(path)
116
- $log.level = Logger::DEBUG # change to warn when you've tested your app.
117
- colors = Ncurses.COLORS
118
- $log.debug "START #{colors} colors --------- #{$0} win: #{@window} "
119
- end
120
- end
121
- def logger; return $log; end
122
- def close
123
- raw_message_destroy
124
- $log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} "
125
- @window.destroy if !@window.nil?
126
- $log.debug " INSIDE CLOSE, #{@stop_ncurses_on_close} "
127
- if @stop_ncurses_on_close
128
- $tt.destroy # added on 2011-10-9 since we created a window, but only hid it after use
129
- VER::stop_ncurses
130
- $log.debug " CLOSING NCURSES"
131
- end
132
- #p $error_message.value unless $error_message.value.nil?
133
- $log.debug " CLOSING APP"
134
- #end
135
- end
136
- # not sure, but user shuld be able to trap keystrokes if he wants
137
- # but do i still call handle_key if he does, or give him total control.
138
- # But loop is already called by framework
139
- def loop &block
140
- @form.repaint
141
- @window.wrefresh
142
- Ncurses::Panel.update_panels
143
- @break_key = ?\C-q.getbyte(0)
144
- while((ch = @window.getchar()) != @quit_key )
145
- break if ch == @break_key
146
-
147
- if @keyblock
148
- str = keycode_tos ch
149
- @keyblock.call(str.gsub(/-/, "_").to_sym) # not used ever
150
- end
151
-
152
- yield ch if block # <<<----
153
- @form.handle_key ch
154
- #@form.repaint # was this duplicate ?? handle calls repaint not needed
155
- @window.wrefresh
156
- end
157
- end
158
- # if calling loop separately better to call this, since it will shut off ncurses
159
- # and print error on screen.
160
- def safe_loop &block
161
- begin
162
- loop &block
163
- rescue => ex
164
- $log.debug( "APP.rb rescue reached ")
165
- $log.debug( ex) if ex
166
- $log.debug(ex.backtrace.join("\n")) if ex
167
- ensure
168
- close
169
- # putting it here allows it to be printed on screen, otherwise it was not showing at all.
170
- if ex
171
- puts "========== EXCEPTION =========="
172
- p ex
173
- puts "==============================="
174
- puts(ex.backtrace.join("\n"))
175
- end
176
- end
177
- end
178
- # returns a symbol of the key pressed
179
- # e.g. :C_c for Ctrl-C
180
- # :Space, :bs, :M_d etc
181
- def keypress &block
182
- @keyblock = block
183
- end
184
- # updates a global var with text. Calling app has to set up a Variable with that name and attach to
185
- # a label so it can be printed.
186
- def message text
187
- $status_message.value = text # trying out 2011-10-9
188
- #@message.value = text # 2011-10-17 14:07:01
189
- end
190
- # @deprecated please use {#status_line} instead of a message label
191
- def message_row row
192
- raise "Please use create_message_label first as message_label is no longer default behaviour" unless @message_label
193
- @message_label.row = row
194
- end
195
- # during a process, when you wish to update status, since ordinarily the thread is busy
196
- # and form does not get control back, so the window won't refresh.
197
- # This will only update on keystroke since it uses statusline
198
- # @deprecated please use {#status_line} instead of a message label
199
- def message_immediate text
200
- $log.warn "DEPRECATED, use message(), or say_with_pause, or say"
201
- $status_message.value = text # trying out 2011-10-9 user needs to use in statusline command
202
- # 2011-10-17 knocking off label, should be printed on status_line
203
- end
204
- # Usage: application is inside a long processing loop and wishes to print ongoing status
205
- # NOTE: if you use this, you must use raw_message_destroy at some stage, after processing
206
- # or on_leave of object.
207
- # @deprecated Use say_with_pause or use rdialogs status_window, see test2.rb
208
- def raw_message text, config={}, &blk
209
- $raw_window ||= one_line_window last_line(), config, &blk
210
- width = $raw_window.width == 0 ? FFI::NCurses.COLS : $raw_window.width
211
- text = "%-*s" % [width, text]
212
-
213
- $raw_window.attron(Ncurses.COLOR_PAIR($normalcolor) )
214
- $raw_window.printstring 0,0,text, $normalcolor #, 'normal' if @title
215
- $raw_window.wrefresh
216
-
217
- end
218
- def raw_message_destroy
219
- if $raw_window
220
- $raw_window.destroy
221
- $raw_window = nil
222
- end
223
- end
224
- # shows a simple progress bar on last row, using stdscr
225
- # @param [Float, Array<Fixnum,Fixnum>] percentage, or part/total
226
- # If Array of two numbers is given then also print part/total on left of bar
227
- # @deprecated - don't use stdscr at all, use rdialogs status_window (see test2.rb)
228
- def raw_progress arg
229
- $log.warning "WARNING: don't use this method as it uses stdscr"
230
- row = @message_label ? @message_label.row : Ncurses.LINES-1
231
- s = nil
232
- case arg
233
- when Array
234
- #calculate percentage
235
- pc = (arg[0]*1.0)/arg[1]
236
- # print items/total also
237
- s = "%-10s" % "(#{arg[0]}/#{arg[1]})"
238
- when
239
- Float
240
- pc = arg
241
- end
242
- scr = Ncurses.stdscr
243
- endcol = Ncurses.COLS-1
244
- startcol = endcol - 12
245
- stext = ("=" * (pc*10).to_i)
246
- text = "[" + "%-10s" % stext + "]"
247
- Ncurses.mvprintw( row ,startcol-10, s) if s
248
- Ncurses.mvprintw row ,startcol, text
249
- #scr.refresh() # XXX FFI NW
250
-
251
- end
252
- # used only by LiveConsole, if enables in an app, usually only during testing.
253
- def get_binding
254
- return binding()
255
- end
256
- #
257
- # suspends curses so you can play around on the shell
258
- # or in cooked mode like Vim does. Expects a block to be passed.
259
- # Purpose: you can print some stuff without creating a window, or
260
- # just run shell commands without coming out.
261
- # NOTE: if you pass clear as true, then the screen will be cleared
262
- # and you can use puts or print to print. You may have to flush.
263
- # However, with clear as false, the screen will not be cleared. You
264
- # will have to print using printw, and if you expect user input
265
- # you must do a "system /bin/stty sane"
266
- # If you print stuff, you will have to put a getch() or system("read")
267
- # to pause the screen.
268
- def suspend clear=true
269
- return unless block_given?
270
- Ncurses.def_prog_mode
271
- if clear
272
- Ncurses.endwin
273
- # NOTE: avoid false since screen remains half off
274
- # too many issues
275
- else
276
- system "/bin/stty sane"
277
- end
278
- yield if block_given?
279
- Ncurses.reset_prog_mode
280
- if !clear
281
- # Hope we don't screw your terminal up with this constantly.
282
- VER::stop_ncurses
283
- VER::start_ncurses
284
- #@form.reset_all # not required
285
- end
286
- @form.repaint
287
- @window.wrefresh
288
- Ncurses::Panel.update_panels
289
- end
290
- def get_all_commands
291
- opts = @_system_commands.dup
292
- if respond_to? :get_commands
293
- opts.push(*get_commands())
294
- end
295
- opts
296
- end
297
- def display_app_help
298
- if respond_to? :help_text
299
- arr = help_text
300
- else
301
- arr = []
302
- arr << " NO HELP SPECIFIED FOR APP "
303
- arr << " "
304
- arr << " --- General help --- "
305
- arr << " F10 - exit application "
306
- arr << " Alt-x - select commands "
307
- arr << " : - select commands "
308
- arr << " "
309
- end
310
- case arr
311
- when String
312
- arr = arr.split("\n")
313
- when Array
314
- end
315
- w = arr.max_by(&:length).length
316
-
317
- require 'rbcurse/extras/viewer'
318
- RubyCurses::Viewer.view(arr, :layout => [2, 10, [4+arr.size, 24].min, w+2],:close_key => KEY_RETURN, :title => "<Enter> to close", :print_footer => true) do |t|
319
- # you may configure textview further here.
320
- #t.suppress_borders true
321
- #t.color = :black
322
- #t.bgcolor = :white
323
- # or
324
- t.attr = :reverse
325
- end
326
- end
327
- # bind a key to a method at global (form) level
328
- # Note that individual component may be overriding this.
329
- # FIXME: why are we using rawmessage and then getchar when ask would suffice
330
- def bind_global
331
- opts = get_all_commands
332
- cmd = ask("Select a command (TAB for choices) : ", opts)
333
- if cmd.nil? || cmd == ""
334
- say_with_pause "Aborted."
335
- return
336
- end
337
- key = []
338
- str = ""
339
- raw_message "Enter one or 2 keys. Finish with ENTER. Enter first key:"
340
- #raw_message "Enter first key:"
341
- ch = @window.getchar()
342
- raw_message_destroy
343
- if [KEY_ENTER, 10, 13, ?\C-g.getbyte(0)].include? ch
344
- say_with_pause "Aborted."
345
- return
346
- end
347
- key << ch
348
- str << keycode_tos(ch)
349
- raw_message "Enter second key or hit return:"
350
- ch = @window.getchar()
351
- raw_message_destroy
352
- if ch == 3 || ch == ?\C-g.getbyte(0)
353
- say_with_pause "Aborted."
354
- return
355
- end
356
- if ch == 10 || ch == KEY_ENTER || ch == 13
357
- else
358
- key << ch
359
- str << keycode_tos(ch)
360
- end
361
- if !key.empty?
362
- say_with_pause "Binding #{cmd} to #{str} "
363
- key = key[0] if key.size == 1
364
- #@form.bind_key(key, cmd.to_sym) # not finding it, getting called by that comp
365
- @form.bind_key(key){ send(cmd.to_sym) }
366
- end
367
- #message "Bound #{str} to #{cmd} "
368
- raw_message_destroy
369
- end
370
- def bind_component
371
- say_with_pause "Todo. <press>"
372
- # the idea here is to get the current component
373
- # and bind some keys to some methods.
374
- # however, how do we divine the methods we can map to
375
- # and also in some cases the components itself has multiple components
376
- end
377
- # displays help_text associated with field. 2011-10-15
378
- def field_help_text
379
- f = @form.get_current_field
380
- if f.respond_to?('help_text')
381
- h = f.help_text
382
- alert "#{h}"
383
- else
384
- alert "Could not get field #{f} or does not respond to helptext"
385
- end
386
- end
387
- # prompts user for a command. we need to get this back to the calling app
388
- # or have some block stuff TODO
389
- # Actually, this is naive, you would want to pass some values in like current data value
390
- # or lines ??
391
- # Also may want command completion, or help so all commands can be displayed
392
- def get_command_from_user choices=["quit"]
393
- #code, str = rbgetstr(@window, $lastline, 0, "", 80, :default => ":")
394
- #return unless code == 0
395
- @_command_history ||= Array.new
396
- str = ask("Cmd: ", choices) { |q| q.default = @_previous_command; q.history = @_command_history }
397
- @_command_history << str unless @_command_history.include? str
398
- # shell the command
399
- if str =~ /^!/
400
- str = str[1..-1]
401
- suspend(false) {
402
- #system(str);
403
- $log.debug "XXX STR #{str} " if $log.debug?
404
-
405
- output=`#{str}`
406
- system("echo ' ' ");
407
- $log.debug "XXX output #{output} " if $log.debug?
408
- system("echo '#{output}' ");
409
- system("echo Press Enter to continue.");
410
- system("read");
411
- }
412
- return nil # i think
413
- else
414
- # TODO
415
- # here's where we can take internal commands
416
- #alert "[#{str}] string did not match :!"
417
- str = str.to_s #= str[1..-1]
418
- cmdline = str.split
419
- cmd = cmdline.shift #.to_sym
420
- return unless cmd # added 2011-09-11 FFI
421
- if respond_to?(cmd, true)
422
- if cmd == "close"
423
- throw :close # other seg faults in del_panel window.destroy executes 2x
424
- else
425
- res = send cmd, *cmdline
426
- end
427
- else
428
- alert "#{self.class} does not respond to #{cmd} "
429
- ret = false
430
- ret = execute_this(cmd, *cmdline) if respond_to?(:execute_this, true)
431
- say_with_pause("#{self.class} does not respond to #{cmd} ", :color_pair => $promptcolor) unless ret
432
- # should be able to say in red as error
433
- end
434
- end
435
- end
436
- #
437
- # @group methods to create widgets easily
438
- #
439
- # process arguments based on datatype, perhaps making configuration
440
- # of some components easier for caller avoiding too much boiler plate code
441
- #
442
- # create a field
443
- def field *args, &block
444
- config = {}
445
- events = [ :CHANGED, :LEAVE, :ENTER, :CHANGE ]
446
- block_event = :CHANGED # LEAVE, ENTER, CHANGE
447
-
448
- _process_args args, config, block_event, events
449
- config.delete(:title)
450
- _position config
451
- # hope next line doesn't bonk anything
452
- config[:display_length] ||= @stack.last.width if @stack.last # added here not sure 2010-11-17 18:43
453
- field = Field.new @form, config
454
- # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited
455
- if block
456
- field.bind(block_event, &block)
457
- end
458
- return field
459
- end
460
- #instance_eval &block if block_given?
461
- # or
462
- #@blk = block # for later execution using @blk.call()
463
- #colorlabel = Label.new @form, {'text' => "Select a color:", "row" => row, "col" => col, "color"=>"cyan", "mnemonic" => 'S'}
464
- #var = RubyCurses::Label.new @form, {'text_variable' => $results, "row" => r, "col" => fc}
465
-
466
- def label *args
467
- events = block_event = nil
468
- config = {}
469
- _process_args args, config, block_event, events
470
- config[:text] ||= config[:name]
471
- config[:height] ||= 1
472
- config.delete(:title)
473
- _position(config)
474
- label = Label.new @form, config
475
- # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited
476
- return label
477
- end
478
- alias :text :label
479
- def button *args, &block
480
- config = {}
481
- events = [ :PRESS, :LEAVE, :ENTER ]
482
- block_event = :PRESS
483
-
484
- _process_args args, config, block_event, events
485
- config[:text] ||= config[:name]
486
- config.delete(:title)
487
- # flow gets precedence over stack
488
- _position(config)
489
- button = Button.new @form, config
490
- # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited
491
- if block
492
- button.bind(block_event, &block)
493
- end
494
- return button
495
- end
496
- #
497
- # create a list
498
- # Since we are mouseless, one can traverse without selection. So we have a different
499
- # way of selecting row/s and traversal. XXX this aspect of LB's has always troubled me hugely.
500
- def list_box *args, &block
501
- config = {}
502
- # TODO confirm events
503
- # listdataevent has interval added and interval removed, due to multiple
504
- # selection, we have to make that simple for user here.
505
- events = [ :LEAVE, :ENTER, :ENTER_ROW, :LEAVE_ROW, :LIST_DATA_EVENT ]
506
- # TODO how to do this so he gets selected row easily
507
- block_event = :ENTER_ROW
508
-
509
- _process_args args, config, block_event, events
510
- # naive defaults, since list could be large or have very long items
511
- # usually user will provide
512
- if !config.has_key? :height
513
- ll = 0
514
- ll = config[:list].length + 2 if config.has_key? :list
515
- config[:height] ||= ll
516
- config[:height] = 15 if config[:height] > 20
517
- end
518
- if @current_object.empty?
519
- $log.debug "1 APP LB w: #{config[:width]} ,#{config[:name]} "
520
- config[:width] ||= @stack.last.width if @stack.last
521
- $log.debug "2 APP LB w: #{config[:width]} "
522
- config[:width] ||= longest_in_list(config[:list])+2
523
- $log.debug "3 APP LB w: #{config[:width]} "
524
- end
525
- # if no width given, expand to flows width XXX SHOULD BE NOT EXPAND ?
526
- #config[:width] ||= @stack.last.width if @stack.last
527
- #if config.has_key? :choose
528
- config[:default_values] = config.delete :choose
529
- # we make the default single unless specified
530
- config[:selection_mode] = :single unless config.has_key? :selection_mode
531
- if @current_object.empty?
532
- if @instack
533
- # most likely you won't have row and col. should we check or just go ahead
534
- col = @stack.last.margin
535
- config[:row] = @app_row
536
- config[:col] = col
537
- @app_row += config[:height] # this needs to take into account height of prev object
538
- end
539
- end
540
- useform = nil
541
- useform = @form if @current_object.empty?
542
- field = Listbox.new useform, config
543
- # shooz uses CHANGED, which is equivalent to our CHANGE. Our CHANGED means modified and exited
544
- if block
545
- # this way you can't pass params to the block
546
- field.bind(block_event, &block)
547
- end
548
- return field
549
- end
550
-
551
- # toggle button
552
- def toggle *args, &block
553
- config = {}
554
- # TODO confirm events
555
- events = [ :PRESS, :LEAVE, :ENTER ]
556
- block_event = :PRESS
557
- _process_args args, config, block_event, events
558
- config[:text] ||= longest_in_list2( [config[:onvalue], config[:offvalue]])
559
- #config[:onvalue] # needed for flow, we need a better way FIXME
560
- _position(config)
561
- toggle = ToggleButton.new @form, config
562
- if block
563
- toggle.bind(block_event, &block)
564
- end
565
- return toggle
566
- end
567
- # check button
568
- def check *args, &block
569
- config = {}
570
- # TODO confirm events
571
- events = [ :PRESS, :LEAVE, :ENTER ]
572
- block_event = :PRESS
573
- _process_args args, config, block_event, events
574
- _position(config)
575
- toggle = CheckBox.new @form, config
576
- if block
577
- toggle.bind(block_event, &block)
578
- end
579
- return toggle
580
- end
581
- # radio button
582
- def radio *args, &block
583
- config = {}
584
- # TODO confirm events
585
- events = [ :PRESS, :LEAVE, :ENTER ]
586
- block_event = :PRESS
587
- _process_args args, config, block_event, events
588
- a = config[:group]
589
- # FIXME we should check if user has set a varialbe in :variable.
590
- # we should create a variable, so he can use it if he wants.
591
- if @variables.has_key? a
592
- v = @variables[a]
593
- else
594
- v = Variable.new
595
- @variables[a] = v
596
- end
597
- config[:variable] = v
598
- config.delete(:group)
599
- _position(config)
600
- radio = RadioButton.new @form, config
601
- if block
602
- radio.bind(block_event, &block)
603
- end
604
- return radio
605
- end
606
- # editable text area
607
- def textarea *args, &block
608
- require 'rbcurse/rtextarea'
609
- config = {}
610
- # TODO confirm events many more
611
- events = [ :CHANGE, :LEAVE, :ENTER ]
612
- block_event = events[0]
613
- _process_args args, config, block_event, events
614
- config[:width] = config[:display_length] unless config.has_key? :width
615
- _position(config)
616
- # if no width given, expand to flows width
617
- config[:width] ||= @stack.last.width if @stack.last
618
- useform = nil
619
- useform = @form if @current_object.empty?
620
- w = TextArea.new useform, config
621
- if block
622
- w.bind(block_event, &block)
623
- end
624
- return w
625
- end
626
- # similar definitions for textview and resultsettextview
627
- # NOTE This is not allowing me to send blocks,
628
- # so do not use for containers
629
- {
630
- 'rbcurse/rtextview' => 'TextView',
631
- 'rbcurse/experimental/resultsettextview' => 'ResultsetTextView',
632
- 'rbcurse/rcontainer' => 'Container',
633
- 'rbcurse/extras/rcontainer2' => 'Container2',
634
- }.each_pair {|k,p|
635
- eval(
636
- "def #{p.downcase} *args, &block
637
- require \"#{k}\"
638
- config = {}
639
- # TODO confirm events many more
640
- events = [ :PRESS, :LEAVE, :ENTER ]
641
- block_event = events[0]
642
- _process_args args, config, block_event, events
643
- config[:width] = config[:display_length] unless config.has_key? :width
644
- _position(config)
645
- # if no width given, expand to flows width
646
- config[:width] ||= @stack.last.width if @stack.last
647
- raise \"height needed for #{p.downcase}\" if !config.has_key? :height
648
- useform = nil
649
- useform = @form if @current_object.empty?
650
- w = #{p}.new useform, config
651
- if block
652
- w.bind(block_event, &block)
653
- end
654
- return w
655
- end"
656
- )
657
- }
658
- # progress bar
659
- def progress *args, &block
660
- require 'rbcurse/rprogress'
661
- config = {}
662
- # TODO confirm events many more
663
- events = [ :CHANGE, :LEAVE, :ENTER ]
664
- block_event = nil
665
- _process_args args, config, block_event, events
666
- config[:width] = config[:display_length] || 10 unless config.has_key? :width
667
- _position(config)
668
- w = Progress.new @form, config
669
- #if block
670
- #w.bind(block_event, &block)
671
- #end
672
- return w
673
- end
674
-
675
- # table widget
676
- # @example
677
- # data = [["Roger",16,"SWI"], ["Phillip",1, "DEU"]]
678
- # colnames = ["Name", "Wins", "Place"]
679
- # t = table :width => 40, :height => 10, :columns => colnames, :data => data, :estimate_widths => true
680
- # other options are :column_widths => [12,4,12]
681
- # :size_to_fit => true
682
- def table *args, &block
683
- require 'rbcurse/rtable'
684
- config = {}
685
- # TODO confirm events many more
686
- events = [ :ENTER_ROW, :LEAVE, :ENTER ]
687
- block_event = events[0]
688
- _process_args args, config, block_event, events
689
- # if user is leaving out width, then we don't want it in config
690
- # else Widget will put a value of 10 as default, overriding what we've calculated
691
- if config.has_key? :display_length
692
- config[:width] = config[:display_length] unless config.has_key? :width
693
- end
694
- ext = config.delete :extended_keys
695
-
696
- model = nil
697
- _position(config)
698
- # if no width given, expand to flows width
699
- config[:width] ||= @stack.last.width if @stack.last
700
- w = Table.new @form, config
701
- if ext
702
- require 'rbcurse/extras/tableextended'
703
- # so we can increase and decrease column width using keys
704
- w.extend TableExtended
705
- w.bind_key(?w){ w.next_column }
706
- w.bind_key(?b){ w.previous_column }
707
- w.bind_key(?+) { w.increase_column }
708
- w.bind_key(?-) { w.decrease_column }
709
- w.bind_key([?d, ?d]) { w.table_model.delete_at w.current_index }
710
- w.bind_key(?u) { w.table_model.undo w.current_index}
711
- end
712
- if block
713
- w.bind(block_event, &block)
714
- end
715
- return w
716
- end
717
- # print a title on first row
718
- def title string, config={}
719
- ## TODO center it
720
- @window.printstring 1, 30, string, $normalcolor, 'reverse'
721
- end
722
- # print a sutitle on second row
723
- def subtitle string, config={}
724
- @window.printstring 2, 30, string, $datacolor, 'normal'
725
- end
726
- # menu bar
727
- def menubar &block
728
- require 'rbcurse/rmenu'
729
- RubyCurses::MenuBar.new &block
730
- end
731
-
732
- # creates a blank row
733
- def blank rows=1, config={}
734
- @app_row += rows
735
- end
736
- # displays a horizontal line
737
- # takes col (column to start from) from current stack
738
- # take row from app_row
739
- #
740
- # requires width to be passed in config, else defaults to 20
741
- # @example
742
- # hline :width => 55
743
- def hline config={}
744
- row = config[:row] || @app_row
745
- width = config[:width] || 20
746
- _position config
747
- col = config[:col] || 1
748
- @color_pair = config[:color_pair] || $datacolor
749
- @attrib = config[:attrib] || Ncurses::A_NORMAL
750
- @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
751
- @window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width)
752
- @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
753
- @app_row += 1
754
- end
755
- def app_header title, config={}, &block
756
- require 'rbcurse/applicationheader'
757
- header = ApplicationHeader.new @form, title, config, &block
758
- end
759
-
760
- # prints pine-like key labels
761
- def dock labels, config={}, &block
762
- require 'rbcurse/keylabelprinter'
763
- klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block
764
- end
765
-
766
- def link *args, &block
767
- require 'rbcurse/extras/rlink'
768
- config = {}
769
- events = [ :PRESS, :LEAVE, :ENTER ]
770
- block_event = :PRESS
771
- _process_args args, config, block_event, events
772
- _position(config)
773
- config[:text] ||= config.delete :title
774
- config[:highlight_foreground] = "yellow"
775
- config[:highlight_background] = "red"
776
- toggle = Link.new @form, config
777
- if block
778
- toggle.bind(block_event, toggle, &block)
779
- end
780
- return toggle
781
- end
782
- def menulink *args, &block
783
- require 'rbcurse/extras/rmenulink'
784
- config = {}
785
- events = [ :PRESS, :LEAVE, :ENTER ]
786
- block_event = :PRESS
787
- _process_args args, config, block_event, events
788
- _position(config)
789
- config[:text] ||= config.delete :title
790
- config[:highlight_foreground] = "yellow"
791
- config[:highlight_background] = "red"
792
- toggle = MenuLink.new @form, config
793
- if block
794
- toggle.bind(block_event, toggle, &block)
795
- end
796
- return toggle
797
- end
798
- def splitpane *args, &block
799
- require 'rbcurse/rsplitpane2'
800
- config = {}
801
- events = [ :PROPERTY_CHANGE, :LEAVE, :ENTER ]
802
- block_event = events[0]
803
- _process_args args, config, block_event, events
804
- _position(config)
805
- # if no width given, expand to flows width
806
- config[:width] ||= @stack.last.width if @stack.last
807
- config.delete :title
808
- useform = nil
809
- useform = @form if @current_object.empty?
810
-
811
- w = SplitPane.new useform, config
812
- #if block
813
- #w.bind(block_event, w, &block)
814
- #end
815
- if block_given?
816
- @current_object << w
817
- #instance_eval &block if block_given?
818
- yield w
819
- @current_object.pop
820
- end
821
- return w
822
- end
823
- def multisplit *args, &block
824
- require 'rbcurse/rmultisplit'
825
- config = {}
826
- events = [ :PROPERTY_CHANGE, :LEAVE, :ENTER ]
827
- block_event = events[0]
828
- _process_args args, config, block_event, events
829
- _position(config)
830
- # if no width given, expand to flows width
831
- config[:width] ||= @stack.last.width if @stack.last
832
- config.delete :title
833
- useform = nil
834
- useform = @form if @current_object.empty?
835
-
836
- w = MultiSplit.new useform, config
837
- #if block
838
- #w.bind(block_event, w, &block)
839
- #end
840
- if block_given?
841
- @current_object << w
842
- #instance_eval &block if block_given?
843
- yield w
844
- @current_object.pop
845
- end
846
- return w
847
- end
848
- def tree *args, &block
849
- require 'rbcurse/rtree'
850
- config = {}
851
- events = [:TREE_WILL_EXPAND_EVENT, :TREE_EXPANDED_EVENT, :TREE_SELECTION_EVENT, :PROPERTY_CHANGE, :LEAVE, :ENTER ]
852
- block_event = nil
853
- _process_args args, config, block_event, events
854
- config[:height] ||= 10
855
- _position(config)
856
- # if no width given, expand to flows width
857
- config[:width] ||= @stack.last.width if @stack.last
858
- #config.delete :title
859
- useform = nil
860
- useform = @form if @current_object.empty?
861
-
862
- w = Tree.new useform, config, &block
863
- return w
864
- end
865
- def vimsplit *args, &block
866
- require 'rbcurse/rvimsplit'
867
- config = {}
868
- #TODO check these
869
- events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ]
870
- block_event = nil
871
- _process_args args, config, block_event, events
872
- config[:height] ||= 10
873
- _position(config)
874
- # if no width given, expand to flows width
875
- config[:width] ||= @stack.last.width if @stack.last
876
- #config.delete :title
877
- useform = nil
878
- useform = @form if @current_object.empty?
879
-
880
- w = VimSplit.new useform, config # NO BLOCK GIVEN
881
- if block_given?
882
- @current_object << w
883
- #instance_eval &block if block_given?
884
- yield w
885
- @current_object.pop
886
- end
887
- return w
888
- end
889
- # create a readonly list
890
- def basiclist *args, &block
891
- require 'rbcurse/rbasiclistbox'
892
- config = {}
893
- #TODO check these
894
- events = [ :LEAVE, :ENTER, :ENTER_ROW, :LEAVE_ROW, :LIST_DATA_EVENT ]
895
- # TODO how to do this so he gets selected row easily
896
- block_event = :ENTER_ROW
897
- _process_args args, config, block_event, events
898
- # some guesses at a sensible height for listbox
899
- if !config.has_key? :height
900
- ll = 0
901
- ll = config[:list].length + 2 if config.has_key? :list
902
- config[:height] ||= ll
903
- config[:height] = 15 if config[:height] > 20
904
- end
905
- _position(config)
906
- # if no width given, expand to flows width
907
- config[:width] ||= @stack.last.width if @stack.last
908
- config[:width] ||= longest_in_list(config[:list])+2
909
- #config.delete :title
910
- #config[:default_values] = config.delete :choose
911
- config[:selection_mode] = :single unless config.has_key? :selection_mode
912
- useform = nil
913
- useform = @form if @current_object.empty?
914
-
915
- w = BasicListbox.new useform, config # NO BLOCK GIVEN
916
- if block_given?
917
- field.bind(block_event, &block)
918
- end
919
- return w
920
- end
921
- def master_detail *args, &block
922
- require 'rbcurse/extras/masterdetail'
923
- config = {}
924
- events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ]
925
- block_event = nil
926
- _process_args args, config, block_event, events
927
- #config[:height] ||= 10
928
- _position(config)
929
- # if no width given, expand to flows width
930
- config[:width] ||= @stack.last.width if @stack.last
931
- #config.delete :title
932
- useform = nil
933
- useform = @form if @current_object.empty?
934
-
935
- w = MasterDetail.new useform, config # NO BLOCK GIVEN
936
- if block_given?
937
- @current_object << w
938
- yield_or_eval &block
939
- @current_object.pop
940
- end
941
- return w
942
- end
943
- # creates a simple readonly table, that allows users to click on rows
944
- # and also on the header. Header clicking is for column-sorting.
945
- def tabular_widget *args, &block
946
- require 'rbcurse/extras/tabularwidget'
947
- config = {}
948
- events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :CHANGE, :ENTER_ROW, :PRESS ]
949
- block_event = nil
950
- _process_args args, config, block_event, events
951
- config[:height] ||= 10 # not sure if this should be here
952
- _position(config)
953
- # if no width given, expand to stack width
954
- config[:width] ||= @stack.last.width if @stack.last
955
- #config.delete :title
956
- useform = nil
957
- useform = @form if @current_object.empty?
958
-
959
- w = TabularWidget.new useform, config # NO BLOCK GIVEN
960
- if block_given?
961
- @current_object << w
962
- yield_or_eval &block
963
- @current_object.pop
964
- end
965
- return w
966
- end
967
- # scrollbar attached to the right of a parent object
968
- def scrollbar *args, &block
969
- require 'rbcurse/extras/scrollbar'
970
- config = {}
971
- events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ] # # none really at present
972
- block_event = nil
973
- _process_args args, config, block_event, events
974
- raise "parent needed for scrollbar" if !config.has_key? :parent
975
- useform = nil
976
- useform = @form if @current_object.empty?
977
- sb = Scrollbar.new useform, config
978
- end
979
- # divider used to resize neighbouring components TOTEST XXX
980
- def divider *args, &block
981
- require 'rbcurse/extras/divider'
982
- config = {}
983
- events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :DRAG_EVENT ] # # none really at present
984
- block_event = nil
985
- _process_args args, config, block_event, events
986
- useform = nil
987
- useform = @form if @current_object.empty?
988
- sb = Divider.new useform, config
989
- end
990
- # creates a simple readonly table, that allows users to click on rows
991
- # and also on the header. Header clicking is for column-sorting.
992
- def combo *args, &block
993
- require 'rbcurse/rcombo'
994
- config = {}
995
- events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :CHANGE, :ENTER_ROW, :PRESS ] # XXX
996
- block_event = nil
997
- _process_args args, config, block_event, events
998
- _position(config)
999
- # if no width given, expand to flows width
1000
- config[:width] ||= @stack.last.width if @stack.last
1001
- #config.delete :title
1002
- useform = nil
1003
- useform = @form if @current_object.empty?
1004
-
1005
- w = ComboBox.new useform, config # NO BLOCK GIVEN
1006
- if block_given?
1007
- @current_object << w
1008
- yield_or_eval &block
1009
- @current_object.pop
1010
- end
1011
- return w
1012
- end
1013
-
1014
- # ADD new widget above this
1015
-
1016
- # @endgroup
1017
-
1018
- # @group positioning of components
1019
-
1020
- # line up vertically whatever comes in, ignoring r and c
1021
- # margin_top to add to margin of existing stack (if embedded) such as extra spacing
1022
- # margin to add to margin of existing stack, or window (0)
1023
- # NOTE: since these coordins are calculated at start
1024
- # therefore if window resized i can't recalculate.
1025
- Stack = Struct.new(:margin_top, :margin, :width)
1026
- def stack config={}, &block
1027
- @instack = true
1028
- mt = config[:margin_top] || 1
1029
- mr = config[:margin] || 0
1030
- # must take into account margin
1031
- defw = Ncurses.COLS - mr
1032
- config[:width] = defw if config[:width] == :EXPAND
1033
- w = config[:width] || [50, defw].min
1034
- s = Stack.new(mt, mr, w)
1035
- @app_row += mt
1036
- mr += @stack.last.margin if @stack.last
1037
- @stack << s
1038
- yield_or_eval &block if block_given?
1039
- @stack.pop
1040
- @instack = false if @stack.empty?
1041
- @app_row = 0 if @stack.empty?
1042
- end
1043
- # keep adding to right of previous and when no more space
1044
- # move down and continue fitting in.
1045
- # Useful for button positioning. Currently, we can use a second flow
1046
- # to get another row.
1047
- # TODO: move down when row filled
1048
- # TODO: align right, center
1049
- def flow config={}, &block
1050
- @inflow = true
1051
- mt = config[:margin_top] || 0
1052
- @app_row += mt
1053
- col = @flowstack.last || @stack.last.margin || @app_col
1054
- col += config[:margin] || 0
1055
- @flowstack << col
1056
- @flowcol = col
1057
- yield_or_eval &block if block_given?
1058
- @flowstack.pop
1059
- @inflow = false if @flowstack.empty?
1060
- end
1061
-
1062
- private
1063
- def quit
1064
- throw(:close)
1065
- end
1066
- # Initialize curses
1067
- def init_ncurses
1068
- VER::start_ncurses # this is initializing colors via ColorMap.setup
1069
- #$ncurses_started = true
1070
- @stop_ncurses_on_close = true
1071
- end
1072
-
1073
- # returns length of longest
1074
- def longest_in_list list #:nodoc:
1075
- longest = list.inject(0) do |memo,word|
1076
- memo >= word.length ? memo : word.length
1077
- end
1078
- longest
1079
- end
1080
- # returns longest item
1081
- # rows = list.max_by(&:length)
1082
- #
1083
- def longest_in_list2 list #:nodoc:
1084
- longest = list.inject(list[0]) do |memo,word|
1085
- memo.length >= word.length ? memo : word
1086
- end
1087
- longest
1088
- end
1089
-
1090
- # if partial command entered then returns matches
1091
- def _resolve_command opts, cmd
1092
- return cmd if opts.include? cmd
1093
- matches = opts.grep Regexp.new("^#{cmd}")
1094
- end
1095
- # Now i am not creating this unless user wants it. Pls avoid it.
1096
- # Use either say_with_pause, or put $status_message in command of statusline
1097
- # @deprecated please use {#status_line} instead of a message label
1098
- def create_message_label row=Ncurses.LINES-1
1099
- @message_label = RubyCurses::Label.new @form, {:text_variable => @message, :name=>"message_label",:row => row, :col => 0, :display_length => Ncurses.COLS, :height => 1, :color => :white}
1100
- end
1101
-
1102
- def run &block
1103
- begin
1104
-
1105
- # check if user has passed window coord in config, else root window
1106
- @window = VER::Window.root_window
1107
- awin = @window
1108
- catch(:close) do
1109
- @form = Form.new @window
1110
- @form.bind_key([?\C-x, ?c]) { suspend(false) do
1111
- system("tput cup 26 0")
1112
- system("tput ed")
1113
- system("echo Enter C-d to return to application")
1114
- system (ENV['PS1']='\s-\v\$ ')
1115
- system(ENV['SHELL']);
1116
- end
1117
- }
1118
- # this is a very rudimentary default command executer, it does not
1119
- # allow tab completion. App should use M-x with names of commands
1120
- # as in appgmail
1121
- @form.bind_key(?:) {
1122
- str = get_command_from_user
1123
- }
1124
-
1125
- @form.bind_key(?\M-x){
1126
- # TODO previous command to be default
1127
- opts = get_all_commands()
1128
- @_command_history ||= Array.new
1129
- # previous command should be in opts, otherwise it is not in this context
1130
- cmd = ask("Command: ", opts){ |q| q.default = @_previous_command; q.history = @_command_history }
1131
- if cmd.nil? || cmd == ""
1132
- else
1133
- @_command_history << cmd unless @_command_history.include? cmd
1134
- cmdline = cmd.split
1135
- cmd = cmdline.shift
1136
- # check if command is a substring of a larger command
1137
- if !opts.include?(cmd)
1138
- rcmd = _resolve_command(opts, cmd) if !opts.include?(cmd)
1139
- if rcmd.size == 1
1140
- cmd = rcmd.first
1141
- elsif !rcmd.empty?
1142
- say_with_pause "Cannot resolve #{cmd}. Matches are: #{rcmd} "
1143
- end
1144
- end
1145
- if respond_to?(cmd, true)
1146
- @_previous_command = cmd
1147
- #raw_message "calling #{cmd} "
1148
- begin
1149
- send cmd, *cmdline
1150
- rescue => exc
1151
- $log.error "ERR EXC: send throwing an exception now. Duh. IMAP keeps crashing haha !! #{exc} " if $log.debug?
1152
- if exc
1153
- $log.debug( exc)
1154
- $log.debug(exc.backtrace.join("\n"))
1155
- say_with_pause exc.to_s
1156
- end
1157
- end
1158
- else
1159
- say_with_pause("Command [#{cmd}] not supported by #{self.class} ", :color_pair => $promptcolor)
1160
- end
1161
- end
1162
- }
1163
- @form.bind_key(KEY_F1){ display_app_help }
1164
- @form.bind_key([?q,?q]){ throw :close } if $log.debug?
1165
-
1166
- #@message = Variable.new
1167
- #@message.value = ""
1168
- $status_message ||= Variable.new # remember there are multiple levels of apps
1169
- $status_message.value = ""
1170
- #$error_message.update_command { @message.set_value($error_message.value) }
1171
- if block
1172
- begin
1173
- #yield(self, @window, @form)
1174
- #instance_eval &block if block_given?
1175
- yield_or_eval &block if block_given? # modified 2010-11-17 20:36
1176
- loop
1177
- rescue => ex
1178
- $log.debug( "APP.rb rescue reached ")
1179
- $log.debug( ex) if ex
1180
- $log.debug(ex.backtrace.join("\n")) if ex
1181
- ensure
1182
- close
1183
- # putting it here allows it to be printed on screen, otherwise it was not showing at all.
1184
- if ex
1185
- puts "========== EXCEPTION =========="
1186
- p ex
1187
- puts "==============================="
1188
- puts(ex.backtrace.join("\n"))
1189
- end
1190
- end
1191
- nil
1192
- else
1193
- #@close_on_terminate = true
1194
- self
1195
- end #if block
1196
- end
1197
- end
1198
- end
1199
- # TODO
1200
- # process args, all widgets should call this
1201
- def _process_args args, config, block_event, events #:nodoc:
1202
- args.each do |arg|
1203
- case arg
1204
- when Array
1205
- # we can use r,c, w, h
1206
- row, col, display_length, height = arg
1207
- config[:row] = row
1208
- config[:col] = col
1209
- config[:display_length] = display_length if display_length
1210
- config[:width] = display_length if display_length
1211
- # width for most XXX ?
1212
- config[:height] = height if height
1213
- when Hash
1214
- config.merge!(arg)
1215
- if block_event
1216
- block_event = config.delete(:block_event){ block_event }
1217
- raise "Invalid event. Use #{events}" unless events.include? block_event
1218
- end
1219
- when String
1220
- config[:name] = arg
1221
- config[:title] = arg # some may not have title
1222
- #config[:text] = arg # some may not have title
1223
- end
1224
- end
1225
- end # _process
1226
- # position object based on whether in a flow or stack.
1227
- # @app_row is prepared for next object based on this objects ht
1228
- def _position config #:nodoc:
1229
- unless @current_object.empty?
1230
- $log.debug " WWWW returning from position #{@current_object.last} "
1231
- return
1232
- end
1233
- if @inflow
1234
- #col = @flowstack.last
1235
- config[:row] = @app_row
1236
- config[:col] = @flowcol
1237
- $log.debug " YYYY config #{config} "
1238
- if config[:text]
1239
- @flowcol += config[:text].length + 5 # 5 came from buttons
1240
- else
1241
- @flowcol += (config[:length] || 10) + 5 # trying out for combo
1242
- end
1243
- elsif @instack
1244
- # most likely you won't have row and col. should we check or just go ahead
1245
- # what if he has put it 2011-10-19 as in a container
1246
- col = @stack.last.margin
1247
- config[:row] ||= @app_row
1248
- config[:col] ||= col
1249
- @app_row += config[:height] || 1 #unless config[:no_advance]
1250
- # TODO need to allow stack to have its spacing, but we don't have an object as yet.
1251
- end
1252
- end
1253
- end # class
1254
- end # module
1255
- if $0 == __FILE__
1256
- include RubyCurses
1257
- #app = App.new
1258
- #window = app.window
1259
- #window.printstring 2, 30, "Demo of Listbox - rbcurse", $normalcolor, 'reverse'
1260
- #app.logger.info "beforegetch"
1261
- #window.getch
1262
- #app.close
1263
- # this was the yield example, but now we've moved to instance eval
1264
- App.new do
1265
- @window.printstring 0, 30, "Demo of Listbox - rbcurse", $normalcolor, 'reverse'
1266
- @window.printstring 1, 30, "Hit F1 to quit", $datacolor, 'normal'
1267
- form = @form
1268
- fname = "Search"
1269
- r, c = 7, 30
1270
- c += fname.length + 1
1271
- #field1 = field( [r,c, 30], fname, :bgcolor => "cyan", :block_event => :CHANGE) do |fld|
1272
- stack :margin_top => 2, :margin => 10 do
1273
- lbl = label({:text => fname, :color=>'white',:bgcolor=>'red', :mnemonic=> 's'})
1274
- field1 = field( [r,c, 30], fname, :bgcolor => "cyan",:block_event => :CHANGE) do |fld|
1275
- message("You entered #{fld.getvalue}. To quit enter quit and tab out")
1276
- if fld.getvalue == "quit"
1277
- logger.info "you typed quit!"
1278
- throw :close
1279
- end
1280
- end
1281
- #field1.set_label Label.new @form, {:text => fname, :color=>'white',:bgcolor=>'red', :mnemonic=> 's'}
1282
- field1.set_label( lbl )
1283
- field1.enter do
1284
- message "you entered this field"
1285
- end
1286
-
1287
- stack :margin_top => 2, :margin => 0 do
1288
- #label( [8, 30, 60],{:text => "A label", :color=>'white',:bgcolor=>'blue'} )
1289
- end
1290
-
1291
- @bluelabel = label( [8, 30, 60],{:text => "B label", :color=>'white',:bgcolor=>'blue'} )
1292
-
1293
- stack :margin_top => 2, :margin => 0 do
1294
- toggle :onvalue => " Toggle Down ", :offvalue => " Untoggle ", :mnemonic => 'T', :value => true
1295
-
1296
- toggle :onvalue => " On ", :offvalue => " Off ", :value => true do |e|
1297
- alert "You pressed me #{e.state}"
1298
- end
1299
- check :text => "Check me!", :onvalue => "Checked", :offvalue => "Unchecked", :value => true do |e|
1300
- # this works but long and complicated
1301
- #@bluelabel.text = e.item.getvalue ? e.item.onvalue : e.item.offvalue
1302
- @bluelabel.text = e.item.text
1303
- end
1304
- radio :text => "red", :value => "RED", :color => "red", :group => :colors
1305
- radio :text => "green", :value => "GREEN", :color => "green", :group => :colors
1306
- flow do
1307
- button_row = 17
1308
- ok_button = button( [button_row,30], "OK", {:mnemonic => 'O'}) do
1309
- alert("About to dump data into log file!")
1310
- message "Dumped data to log file"
1311
- end
1312
-
1313
- # using ampersand to set mnemonic
1314
- cancel_button = button( [button_row, 40], "&Cancel" ) do
1315
- if confirm("Do your really want to quit?")== :YES
1316
- #throw(:close);
1317
- quit
1318
- else
1319
- message "Quit aborted"
1320
- end
1321
- end # cancel
1322
- button "Don't know"
1323
- end
1324
- flow :margin_top => 2 do
1325
- button "Another"
1326
- button "Line"
1327
- end
1328
- stack :margin_top => 2, :margin => 0 do
1329
- @pbar = progress :width => 20, :bgcolor => 'white', :color => 'red'
1330
- @pbar1 = progress :width => 20, :style => :old
1331
- end
1332
- end
1333
- end # stack
1334
- # lets make another column
1335
- stack :margin_top => 2, :margin => 70 do
1336
- l = label "Column 2"
1337
- f1 = field "afield", :bgcolor => 'white', :color => 'black'
1338
- list_box "A list", :list => ["Square", "Oval", "Rectangle", "Somethinglarge"], :choose => ["Square"]
1339
- lb = list_box "Another", :list => ["Square", "Oval", "Rectangle", "Somethinglarge"] do |list|
1340
- #f1.set_buffer list.text
1341
- #f1.text list.text
1342
- f1.text = list.text
1343
- l.text = list.text.upcase
1344
- end
1345
- t = textarea :height => 10 do |e|
1346
- #@bluelabel.text = e.to_s.tr("\n",' ')
1347
- @bluelabel.text = e.text.gsub("\n"," ")
1348
- len = e.source.get_text.length
1349
- len = len % 20 if len > 20
1350
- $log.debug " PBAR len of text is #{len}: #{len/20.0} "
1351
- @pbar.fraction(len/20.0)
1352
- @pbar1.fraction(len/20.0)
1353
- i = ((len/20.0)*100).to_i
1354
- @pbar.text = "completed:#{i}"
1355
- end
1356
- t.leave do |c|
1357
- @bluelabel.text = c.get_text.gsub("\n"," ")
1358
- end
1359
-
1360
- end
1361
-
1362
- # Allow user to get the keys
1363
- keypress do |key|
1364
- if key == :C_c
1365
- message "You tried to cancel"
1366
- #throw :close
1367
- quit
1368
- else
1369
- #app.message "You pressed #{key}, #{char} "
1370
- message "You pressed #{key}"
1371
- end
1372
- end
1373
- end
1374
- end