rbcurse 1.4.1 → 1.5.0.pre1

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 (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