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,328 +0,0 @@
1
- # --------------------------------------------------------------------------------- #
2
- # File: newmessagebox.rb
3
- # Description: This is a cleaner attempt at messagebox on the lines of
4
- # the new tabbedpane and window.
5
- # Author: rkumar http://github.com/rkumar/rbcurse/
6
- # Date: 03.11.11 - 22:15
7
- # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
8
- # Last update: 03.11.11 - 23:47
9
- # == CHANGES
10
- # == TODO
11
- # _ <ENTER> should result in OK being pressed if its default, ESC should result in cancel esp 2 time
12
- # ensure that text and message are used in isolation and not with other things
13
- #
14
- # _ determine window size, but we are doing instance eval later.
15
- #
16
- # _ maybe have shortcuts for some widgets field, buttons, text and label and
17
- # share with app and otherszz
18
- #
19
- # _ stack, flow and grid
20
- #
21
- # --------------------------------------------------------------------------------- #
22
-
23
- require 'rbcurse'
24
- require 'rbcurse/common/bordertitle'
25
-
26
- include RubyCurses
27
- class NewMessagebox
28
- include BorderTitle
29
- include RubyCurses::Utils
30
-
31
- attr_reader :form
32
- attr_reader :window
33
- dsl_accessor :button_type
34
- #
35
- # a message to be printed, usually this will be the only thing supplied
36
- # with an OK button. This should be a short string, a label will be used
37
- # and input_config passed to it
38
-
39
- #dsl_accessor :message
40
- # you can also set button_orientation : :right, :left, :center
41
- #
42
- def initialize config={}, &block
43
-
44
- h = config.fetch(:height, nil)
45
- w = config.fetch(:width, nil)
46
- t = config.fetch(:row, nil)
47
- l = config.fetch(:col, nil)
48
- if h && w && t && l
49
- @window = VER::Window.new :height => h, :width => w, :top => t, :left => l
50
- @graphic = @window
51
- end
52
- @form = Form.new @window
53
-
54
- config.each_pair { |k,v| instance_variable_set("@#{k}",v) }
55
- @config = config
56
- @row = 0
57
- @col = 0
58
- @row_offset = 1
59
- @col_offset = 2
60
- #bordertitle_init
61
- @color ||= :black
62
- @bgcolor ||= :white
63
-
64
- instance_eval &block if block_given?
65
-
66
- end
67
- def item widget
68
- # remove from existing form if set
69
- widget.set_form @form
70
- widget.row ||= 0
71
- widget.col ||= 0
72
- # i don't know button_offset as yet
73
- widget.row += @row_offset
74
- widget.col += @col_offset
75
- # in most cases this override is okay, but what if user has set it
76
- # The problem is that widget and field are doing a default setting so i don't know
77
- # if user has set or widget has done a default setting. NOTE
78
- widget.color @color # we are overriding colors, how to avoid since widget sets it
79
- widget.bgcolor @bgcolor
80
- widget.attr = @attr if @attr # we are overriding what user has put. DARN !
81
- @maxrow ||= 0
82
- @maxrow = widget.row if widget.row > @maxrow
83
- @suggested_h = @height || @maxrow+6
84
- end
85
- alias :add :item
86
- # returns button index
87
- # Call this after instantiating the window
88
- def run
89
- repaint
90
- @form.repaint
91
- @window.wrefresh
92
- return handle_keys
93
- end
94
- def repaint
95
- _create_window unless @window
96
- acolor = get_color $reverscolor # this implicitly uses color and bgcolor fooling me often
97
- $log.debug " MESSAGE BOX bg:#{@bgcolor} , co:#{@color} , colorpair:#{acolor}"
98
- @window.wbkgd(Ncurses.COLOR_PAIR(acolor)); # does not work on xterm-256color
99
-
100
- #print_borders unless @suppress_borders # do this once only, unless everything changes
101
- #@window.print_border_mb 1,2, @height, @width, $normalcolor, FFI::NCurses::A_REVERSE
102
- @color_pair = get_color($datacolor)
103
- bordercolor = @border_color || @color_pair
104
- borderatt = @border_attrib || Ncurses::A_NORMAL
105
- @window.wattron(Ncurses.COLOR_PAIR(bordercolor) | (borderatt || FFI::NCurses::A_NORMAL))
106
- @window.print_border_mb 1,2, @height, @width, bordercolor, borderatt
107
- @window.wattroff(Ncurses.COLOR_PAIR(bordercolor) | (borderatt || FFI::NCurses::A_NORMAL))
108
- title = " "+@title+" "
109
- @window.printstring(@row=1,@col=(@width-title.length)/2,title, color=$normalcolor)
110
- #print_message if @message
111
- create_action_buttons unless @action_buttons
112
- end
113
- # Pass a short message to be printed.
114
- # This creates a label for a short message, and a field for a long one.
115
- # @yield field created
116
- # @param [String] text to display
117
- def message message # yield label or field being used for display for further customization
118
- @suggested_h = @height || 10
119
- @suggested_w = @width || 60
120
- message_col = 5
121
- r = 3
122
- len = message.length
123
- @suggested_w = len + 8 + message_col if len < @suggested_w - 8 - message_col
124
-
125
- display_length = @suggested_w-8
126
- display_length -= message_col
127
- message_height = 2
128
- clr = @color || :white
129
- bgclr = @bgcolor || :black
130
-
131
- # trying this out. sometimes very long labels get truncated, so i give a field in wchich user
132
- # can use arrow key or C-a and C-e
133
- if message.size > display_length
134
- message_label = RubyCurses::Field.new @form, {:text => message, :name=>"message_label",
135
- :row => r, :col => message_col, :display_length => display_length,
136
- :bgcolor => bgclr , :color => clr, :editable => false}
137
- else
138
- message_label = RubyCurses::Label.new @form, {:text => message, :name=>"message_label",
139
- :row => r, :col => message_col, :display_length => display_length,
140
- :height => message_height, :bgcolor => bgclr , :color => clr}
141
- end
142
- yield message_label if block_given?
143
- end
144
-
145
- # This is for larger messages, or messages where the size is not known.
146
- # A textview object is created and yielded.
147
- #
148
- def text message
149
- @suggested_w = @width || (FFI::NCurses.COLS * 0.70).floor
150
- @suggested_h = @height || (FFI::NCurses.LINES * 0.70).floor
151
-
152
- message_col = 3
153
- r = 2
154
- display_length = @suggested_w-4
155
- display_length -= message_col
156
- clr = @color || :white
157
- bgclr = @bgcolor || :black
158
-
159
- if message.is_a? Array
160
- # reduce width and height if you can based on array contents
161
- else
162
- message = wrap_text(message, display_length).split("\n")
163
- end
164
- message_height = message.size
165
- # reduce if possible if its not required.
166
- #
167
- r1 = (FFI::NCurses.LINES-@suggested_h)/2
168
- r1 = r1.floor
169
- w = @suggested_w
170
- c1 = (FFI::NCurses.COLS-w)/2
171
- c1 = c1.floor
172
- @suggested_row = r1
173
- @suggested_col = c1
174
- brow = @button_row || @suggested_h-4
175
- available_ht = brow - r + 1
176
- message_height = [message_height, available_ht].min
177
- require 'rbcurse/rtextview'
178
- message_label = RubyCurses::TextView.new @form, {:name=>"message_label", :text => message,
179
- :row => r, :col => message_col, :width => display_length, :suppress_borders => true,
180
- :height => message_height, :bgcolor => bgclr , :color => clr}
181
- #message_label.set_content message
182
- yield message_label if block_given?
183
-
184
- end
185
- # returns button index
186
- private
187
- def handle_keys
188
- buttonindex = catch(:close) do
189
- while((ch = @window.getchar()) != FFI::NCurses::KEY_F10 )
190
- break if ch == ?\C-q.getbyte(0)
191
- begin
192
- @form.handle_key(ch)
193
- @window.wrefresh
194
- rescue => err
195
- $log.debug( err) if err
196
- $log.debug(err.backtrace.join("\n")) if err
197
- alert "Got an exception in NewMessagebox: #{err}. Check log"
198
- $error_message.value = ""
199
- ensure
200
- end
201
-
202
- end # while loop
203
- end # close
204
- $log.debug "XXX: CALLER GOT #{buttonindex} "
205
- @window.destroy
206
- return buttonindex
207
- end
208
- private
209
- def create_action_buttons
210
- return unless @button_type
211
- case @button_type.to_s.downcase
212
- when "ok"
213
- make_buttons ["&OK"]
214
- when "ok_cancel" #, "input", "list", "field_list"
215
- make_buttons %w[&OK &Cancel]
216
- when "ok_apply_cancel" #, "input", "list", "field_list"
217
- make_buttons %w[&OK &Apply &Cancel]
218
- when "yes_no"
219
- make_buttons %w[&Yes &No]
220
- when "yes_no_cancel"
221
- make_buttons ["&Yes", "&No", "&Cancel"]
222
- when "custom"
223
- raise "Blank list of buttons passed to custom" if @buttons.nil? or @buttons.size == 0
224
- make_buttons @buttons
225
- else
226
- $log.warn "No buttontype passed for creating tabbedpane. Not creating any"
227
- #make_buttons ["&OK"]
228
- end
229
- end
230
- private
231
- def make_buttons names
232
- @action_buttons = []
233
- $log.debug "XXX: came to NTP make buttons FORM= #{@form.name} names #{names} "
234
- total = names.inject(0) {|total, item| total + item.length + 4}
235
- bcol = align_buttons total, @button_orientation
236
-
237
- # this craps out when height is zero
238
- brow = @row + @height-4
239
- brow = FFI::NCurses.LINES-2 if brow < 0
240
- @button_row = brow
241
- #color_pair = get_color($normalcolor)
242
- #@window.wattron(Ncurses.COLOR_PAIR(color_pair) | (@attrib || FFI::NCurses::A_NORMAL))
243
- #@window.mvwhline( brow-1, @col+1, Ncurses::ACS_HLINE, @width-2)
244
- #@window.wattroff(Ncurses.COLOR_PAIR(color_pair) | (@attrib || FFI::NCurses::A_NORMAL))
245
- $log.debug "XXX: putting buttons :on #{brow} , #{bcol} : #{@row} , #{@height} "
246
- button_ct=0
247
- tpp = self
248
- _color = @color
249
- _bgcolor = @bgcolor
250
- names.each_with_index do |bname, ix|
251
- text = bname
252
- #underline = @underlines[ix] if !@underlines.nil?
253
-
254
- button = Button.new @form do
255
- text text
256
- name bname
257
- row brow
258
- col bcol
259
- #underline underline
260
- highlight_background $reversecolor
261
- color _color
262
- bgcolor _bgcolor
263
- end
264
- @action_buttons << button
265
- button.form = @form
266
- button.override_graphic @graphic
267
- index = button_ct
268
- tpp = self
269
- button.command { |form| @selected_index = index; @stop = true;
270
- # ActionEvent has source event and action_command
271
- action = ActionEvent.new(tpp, index, button.text)
272
- if @command
273
- @command.call(action, @args)
274
- else
275
- # default action if you don't specify anything
276
- throw(:close, @selected_index)
277
- end
278
- }
279
- button_ct += 1
280
- bcol += text.length+6
281
- end
282
- end
283
- def _create_window
284
-
285
- @width = @suggested_w || 60
286
- @height = @suggested_h || 10
287
- if @suggested_row
288
- @row = @suggested_row
289
- else
290
- @row = ((FFI::NCurses.LINES-@height)/2).floor
291
- end
292
- if @suggested_col
293
- @col = @suggested_col
294
- else
295
- w = @width
296
- @col = ((FFI::NCurses.COLS-w)/2).floor
297
- end
298
- @window = VER::Window.new :height => @height, :width => @width, :top => @row, :left => @col
299
- @graphic = @window
300
- @form.window = @window
301
- end
302
- #
303
- # specify a code block to be fired when an action button is pressed
304
- # This will supply (to the code block) an ActionEvent followed by
305
- # whatever args that were given.
306
- # ActionEvent contains source, event, action_command which map to
307
- # the messagebox, selected_index (base 0) and button title.
308
- #
309
- public
310
- def command *args, &blk
311
- @command = blk
312
- @args = args
313
- end
314
-
315
- # returns starting column for buttons to start painting
316
- # Not very correct in case of :right
317
- private
318
- def align_buttons textlen, orient=:center
319
- case orient
320
- when :left
321
- return @col+@col_offset
322
- when :right
323
- return (@width-textlen)-5
324
- else
325
- return (@width-textlen)/2
326
- end
327
- end
328
- end
@@ -1,612 +0,0 @@
1
- =begin
2
- * Name: newtabbedpane.rb
3
- * Description : This is radically simplified tabbedpane. The earlier version
4
- was too complex with multiple forms and pads, and a scrollform. This uses
5
- the external form and has some very simple programming to handle the whole thing.
6
- * Author: rkumar (http://github.com/rkumar/rbcurse/)
7
- * Date: 2011-10-20
8
- * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
9
- * Last update: Sat Oct 22 18:40:49 IST 2011
10
-
11
- == CHANGES
12
- == TODO
13
- on start first buttons bottom should not be lined.
14
- Alt-1-9 to goto tabs
15
- add remove tabs at any time - started, untested
16
- events for tab add/remove/etc
17
- =end
18
- require 'rbcurse'
19
- ##
20
- module RubyCurses
21
- class NewTabbedPane < Widget
22
- dsl_property :title, :title_attrib
23
- # what kind of buttons, if this is a window, :ok :ok_camcel :ok_apply_cancel
24
- dsl_accessor :button_type
25
- attr_reader :button_row
26
- # index of tab that is currently open
27
- attr_reader :current_tab
28
-
29
-
30
- def initialize form=nil, config={}, &block
31
- @_events ||= []
32
- @_events.push(:PRESS)
33
- @button_gap = 2
34
- init_vars
35
- super
36
- @focusable = true
37
- @editable = true
38
- @col_offset = 2
39
- raise ArgumentError, "NewTabbedPane : row or col not set: r: #{@row} c: #{@col} " unless @row && @col
40
- end
41
-
42
- # Add a tab
43
- def tab title, config={}, &block
44
- #@tab_components[title]=[]
45
- #@tabs << Tab.new(title, self, config, &block)
46
- insert_tab @tabs.count, title, config, &block
47
- self
48
- end
49
- alias :add_tab :tab
50
-
51
- # a shortcut for binding a command to a press of an action button
52
- # The block will be passed
53
- # This is only relevant if you have asked for buttons to be created, which is
54
- # only relevant in a TabbedWindow
55
- # ActionEvent has source event and action_command
56
- def command *args, &block
57
- bind :PRESS, *args, &block
58
- end
59
-
60
- # -------------- tab maintenance commands ------------------ #
61
-
62
- def insert_tab index, title, config={}, &block
63
- @tabs.insert(index, Tab.new(title, self, config, &block) )
64
- end
65
- def remove_tab tab
66
- @tabs.delete tab
67
- self
68
- end
69
- def remove_all
70
- @tabs = []
71
- self
72
- end
73
- def remove_tab_at index = @current_tab
74
- @tabs.delete_at index
75
- end
76
-
77
- def repaint
78
- @current_tab ||= 0
79
- @button_row ||= @row + 2
80
- @separator_row = @button_row + 1 # hope we have it by now, where to print separator
81
- @separator_row0 = @button_row - 1 unless @button_row == @row + 1
82
- @separator_row2 = @row + @height - 3 # hope we have it by now, where to print separator
83
- #return unless @repaint_required
84
- if @buttons.empty?
85
- _create_buttons
86
- @components = @buttons.dup
87
- @components.push(*@tabs[@current_tab].items)
88
- create_action_buttons
89
- @components.push(*@action_buttons)
90
- elsif @tab_changed
91
- @components = @buttons.dup
92
- @components.push(*@tabs[@current_tab].items)
93
- @components.push(*@action_buttons)
94
- @tab_changed = false
95
- end
96
- # if some major change has happened then repaint everything
97
- if @repaint_required
98
- $log.debug " NEWTAB repaint graphic #{@graphic} "
99
- print_borders unless @suppress_borders # do this once only, unless everything changes
100
- print_separator1
101
- @components.each { |e| e.repaint_all(true); e.repaint }
102
- else
103
- @components.each { |e| e.repaint }
104
- end # if repaint_required
105
- print_border if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
106
- @repaint_required = false
107
- end
108
- def handle_key ch
109
- $log.debug " NEWTABBED handle_key #{ch} "
110
- return if @components.empty?
111
- _multiplier = ($multiplier == 0 ? 1 : $multiplier )
112
-
113
- # should this go here 2011-10-19
114
- unless @_entered
115
- $log.warn "WARN: calling ON_ENTER since in this situation it was not called"
116
- on_enter
117
- end
118
- #if ch == KEY_TAB
119
- #$log.debug "NEWTABBED GOTO NEXT"
120
- #return goto_next_component
121
- #elsif ch == KEY_BTAB
122
- #return goto_prev_component
123
- #end
124
- comp = @current_component
125
- $log.debug " NEWTABBED handle_key #{ch}: #{comp}"
126
- if comp
127
- ret = comp.handle_key(ch)
128
- $log.debug " NEWTABBED handle_key#{ch}: #{comp} returned #{ret} "
129
- if ret != :UNHANDLED
130
- comp.repaint # NOTE: if we don;t do this, then it won't get repainted. I will have to repaint ALL
131
- # in repaint of this.
132
- return ret
133
- end
134
- $log.debug "XXX NEWTABBED key unhandled by comp #{comp.name} "
135
- else
136
- Ncurses.beep
137
- $log.warn "XXX NEWTABBED key unhandled NULL comp"
138
- end
139
- case ch
140
- when ?\C-c.getbyte(0)
141
- $multiplier = 0
142
- return 0
143
- when ?0.getbyte(0)..?9.getbyte(0)
144
- $log.debug " VIM coming here to set multiplier #{$multiplier} "
145
- $multiplier *= 10 ; $multiplier += (ch-48)
146
- return 0
147
- end
148
- ret = process_key ch, self
149
- # allow user to map left and right if he wants
150
- if ret == :UNHANDLED
151
- case ch
152
- when KEY_UP, KEY_BTAB
153
- # form will pick this up and do needful
154
- return goto_prev_component #unless on_first_component?
155
- when KEY_LEFT
156
- # if i don't check for first component, key will go back to form,
157
- # but not be processes. so focussed remain here, but be false.
158
- # In case of returnign an unhandled TAB, on_leave will happen and cursor will move to
159
- # previous component outside of this.
160
- return goto_prev_component unless on_first_component?
161
- when KEY_RIGHT, KEY_TAB
162
- return goto_next_component #unless on_last_component?
163
- when KEY_DOWN
164
- if on_a_button?
165
- return goto_first_item
166
- else
167
- return goto_next_component #unless on_last_component?
168
- end
169
- else
170
- #@_entered = false
171
- return :UNHANDLED
172
- end
173
- end
174
-
175
- $multiplier = 0
176
- return 0
177
- end
178
- # on enter processing
179
- # Very often the first may be a label !
180
- def on_enter
181
- # if BTAB, the last comp
182
- if $current_key == KEY_BTAB
183
- @current_component = @components.last
184
- else
185
- @current_component = @components.first
186
- end
187
- return unless @current_component
188
- $log.debug " NEWTABBED came to ON_ENTER #{@current_component} "
189
- set_form_row
190
- @_entered = true
191
- end
192
- def on_leave
193
- @_entered = false
194
- super
195
- end
196
- # takes focus to first item (after buttons)
197
- def goto_first_item
198
- bc = @buttons.count
199
- @components[bc..-1].each { |c|
200
- if c.focusable
201
- leave_current_component
202
- @current_component = c
203
- set_form_row
204
- break
205
- end
206
- }
207
- end
208
- def goto_last_item
209
- bc = @buttons.count
210
- f = nil
211
- @components[bc..-1].each { |c|
212
- if c.focusable
213
- f = c
214
- end
215
- }
216
- if f
217
- leave_current_component
218
- @current_component = f
219
- set_form_row
220
- end
221
- end
222
- def goto_next_component
223
- if @current_component != nil
224
- leave_current_component
225
- if on_last_component?
226
- @_entered = false
227
- return :UNHANDLED
228
- end
229
- @current_index = @components.index(@current_component)
230
- index = @current_index + 1
231
- index.upto(@components.length-1) do |i|
232
- f = @components[i]
233
- if f.focusable
234
- @current_index = i
235
- @current_component = f
236
- return set_form_row
237
- end
238
- end
239
- end
240
- @_entered = false
241
- return :UNHANDLED
242
- end
243
- def goto_prev_component
244
- if @current_component != nil
245
- leave_current_component
246
- if on_first_component?
247
- @_entered = false
248
- return :UNHANDLED
249
- end
250
- @current_index = @components.index(@current_component)
251
- index = @current_index -= 1
252
- index.downto(0) do |i|
253
- f = @components[i]
254
- if f.focusable
255
- @current_index = i
256
- @current_component = f
257
- return set_form_row
258
- end
259
- end
260
- end
261
- return :UNHANDLED
262
- end
263
- # private
264
- def set_form_row
265
- return :UNHANDLED if @current_component.nil?
266
- $log.debug " NEWTABBED on enter sfr #{@current_component} "
267
- @current_component.on_enter
268
- @current_component.set_form_row # why was this missing in vimsplit. is it
269
- # that on_enter does a set_form_row
270
- @current_component.set_form_col # XXX
271
- @current_component.repaint
272
- # XXX compo should do set_form_row and col if it has that
273
- end
274
- # private
275
- def set_form_col
276
- return if @current_component.nil?
277
- $log.debug " #{@name} NEWTABBED set_form_col calling sfc for #{@current_component.name} "
278
- @current_component.set_form_col
279
- end
280
- # leave the component we are on.
281
- # This should be followed by all containers, so that the on_leave action
282
- # of earlier comp can be displayed, such as dimming components selections
283
- def leave_current_component
284
- @current_component.on_leave
285
- # NOTE this is required, since repaint will just not happen otherwise
286
- # Some components are erroneously repainting all, after setting this to true so it is
287
- # working there.
288
- @current_component.repaint_required true
289
- $log.debug " after on_leave VIMS XXX #{@current_component.focussed} #{@current_component.name}"
290
- @current_component.repaint
291
- end
292
-
293
- # is focus on first component
294
- def on_first_component?
295
- @current_component == @components.first
296
- end
297
- # is focus on last component
298
- def on_last_component?
299
- @current_component == @components.last
300
- end
301
- def on_a_button?
302
- @components.index(@current_component) < @buttons.count
303
- end
304
- # set focus on given component
305
- # Sometimes you have the handle to component, and you want to move focus to it
306
- def goto_component comp
307
- return if comp == @current_component
308
- leave_current_component
309
- @current_component = comp
310
- set_form_row
311
- end
312
- def set_current_tab t
313
- return if @current_tab == t
314
- @current_tab = t
315
- goto_component @components[t]
316
- @tab_changed = true
317
- @repaint_required = true
318
- self
319
- end
320
-
321
- def DEPRECATED_handle_key ch # :nodoc
322
- map_keys unless @keys_mapped
323
- ret = process_key ch, self
324
- @multiplier = 0
325
- return :UNHANDLED if ret == :UNHANDLED
326
- return 0
327
- end
328
-
329
- # Put all the housekeeping stuff at the end
330
- private
331
- def init_vars
332
- @buttons = []
333
- @tabs = []
334
- #@tab_components = {}
335
- @bottombuttons = []
336
- #
337
- # I'll keep current tabs comps in this to simplify
338
- @components = []
339
- @_entered = false
340
- end
341
-
342
- def map_keys
343
- @keys_mapped = true
344
- #bind_key(?q, :myproc)
345
- #bind_key(32, :myproc)
346
- end
347
-
348
- def _create_buttons
349
- $log.debug "XXX: INSIDE create_buttons col_offset #{@col_offset} "
350
- v = Variable.new
351
- r = @button_row # @row + 1
352
- col = @col + @col_offset
353
- @tabs.each_with_index { |t, i|
354
- txt = t.text
355
- @buttons << TabButton.new(nil) do
356
- variable v
357
- text txt
358
- name txt
359
- #value txt
360
- row r
361
- col col
362
- surround_chars ['','']
363
- selected_background 'green'
364
- selected_foreground 'white'
365
-
366
- end
367
- b = @buttons.last
368
- b.command do
369
- set_current_tab i
370
- end
371
- b.form = @form
372
- b.override_graphic @graphic
373
- col += txt.length + @button_gap
374
- }
375
- end # _create_buttons
376
- private
377
- def print_borders
378
- width = @width
379
- height = @height-1
380
- window = @graphic
381
- startcol = @col
382
- startrow = @row
383
- @color_pair = get_color($datacolor)
384
- $log.debug "NTP #{name}: window.print_border #{startrow}, #{startcol} , h:#{height}, w:#{width} , @color_pair, @attr "
385
- window.print_border startrow, startcol, height, width, @color_pair, @attr
386
- print_title
387
- end
388
- def print_separator1
389
-
390
- width = @width
391
- height = @height-1
392
- window = @graphic
393
- startcol = @col
394
- startrow = @row
395
- @color_pair = get_color($datacolor)
396
- r = @separator_row
397
- c = @col + @col_offset
398
-
399
- urcorner = []
400
- #window.printstring r, c, '-' * (@width-2), @color_pair, @attr
401
- window.mvwhline( r, @col+1, Ncurses::ACS_HLINE, @width-2)
402
- @buttons.each_with_index do |b, i|
403
- l = b.text.length
404
- if b.selected?
405
- if false #c == @col + @col_offset
406
- cc = c
407
- ll = l+1
408
- else
409
- cc = c-1
410
- ll = l+2
411
- end
412
- #rr = r -1 #unless rr == @col
413
- window.printstring r, cc, " "*ll, @color_pair, @attr
414
- #window.printstring r, cc-1, FFI::NCurses::ACS_HLINE.chr*ll, @color_pair, @attr
415
- #window.printstring r-2, cc, FFI::NCurses::ACS_HLINE.chr*ll, @color_pair, @attr
416
- window.mvwaddch r, cc-1, FFI::NCurses::ACS_LRCORNER unless cc-1 <= @col
417
- window.mvwaddch r, c+l+1, FFI::NCurses::ACS_LLCORNER
418
- else
419
- window.mvwaddch r, c+l+1, FFI::NCurses::ACS_BTEE
420
- end
421
-
422
- #window.printstring r-2, c, FFI::NCurses::ACS_HLINE*l, @color_pair, @attr
423
- #tt = b.text
424
- #window.printstring r, c, tt, @color_pair, @attr
425
- c += l + 1
426
- #window.mvwaddch r, c, '+'.ord
427
- window.mvwaddch r-1, c, FFI::NCurses::ACS_VLINE
428
- window.mvwaddch r-2, c, FFI::NCurses::ACS_URCORNER #ACS_TTEE
429
- #window.mvwaddch r-2, c+1, '/'.ord
430
- urcorner << c
431
- c+=@button_gap
432
- end
433
- window.mvwhline( @separator_row0, @col + 1, Ncurses::ACS_HLINE, c-@col-1-@button_gap)
434
- window.mvwhline( @separator_row2, @col + 1, Ncurses::ACS_HLINE, @width-2)
435
- urcorner.each do |c|
436
- window.mvwaddch r-2, c, FFI::NCurses::ACS_URCORNER #ACS_TTEE
437
- end
438
- end
439
- def print_title
440
- return unless @title
441
- _title = @title
442
- if @title.length > @width - 2
443
- _title = @title[0..@width-2]
444
- end
445
- @graphic.printstring( @row, @col+(@width-_title.length)/2, _title,
446
- @color_pair, @title_attrib) unless @title.nil?
447
- end
448
-
449
- #
450
- # create the buttons at the bottom OK/ APPLY/ CANCEL
451
-
452
- def create_action_buttons
453
- return unless @button_type
454
- case @button_type.to_s.downcase
455
- when "ok"
456
- make_buttons ["&OK"]
457
- when "ok_cancel" #, "input", "list", "field_list"
458
- make_buttons %w[&OK &Cancel]
459
- when "ok_apply_cancel" #, "input", "list", "field_list"
460
- make_buttons %w[&OK &Apply &Cancel]
461
- when "yes_no"
462
- make_buttons %w[&Yes &No]
463
- when "yes_no_cancel"
464
- make_buttons ["&Yes", "&No", "&Cancel"]
465
- when "custom"
466
- raise "Blank list of buttons passed to custom" if @buttons.nil? or @buttons.size == 0
467
- make_buttons @buttons
468
- else
469
- $log.warn "No buttontype passed for creating tabbedpane. Not creating any"
470
- #make_buttons ["&OK"]
471
- end
472
- end
473
- def make_buttons names
474
- @action_buttons = []
475
- $log.debug "XXX: came to NTP make buttons FORM= #{@form.name} names #{names} "
476
- total = names.inject(0) {|total, item| total + item.length + 4}
477
- bcol = center_column total
478
-
479
- # this craps out when height is zero
480
- brow = @row + @height-2
481
- brow = FFI::NCurses.LINES-2 if brow < 0
482
- $log.debug "XXX: putting buttons :on #{brow} : #{@row} , #{@height} "
483
- button_ct=0
484
- tpp = self
485
- names.each_with_index do |bname, ix|
486
- text = bname
487
- #underline = @underlines[ix] if !@underlines.nil?
488
-
489
- button = Button.new nil do
490
- text text
491
- name bname
492
- row brow
493
- col bcol
494
- #underline underline
495
- highlight_background $reversecolor
496
- color $datacolor
497
- bgcolor $datacolor
498
- end
499
- @action_buttons << button
500
- button.form = @form
501
- button.override_graphic @graphic
502
- index = button_ct
503
- tpp = self
504
- button.command { |form| @selected_index = index; @stop = true;
505
- # ActionEvent has source event and action_command
506
- fire_handler :PRESS, ActionEvent.new(tpp, index, button.text)
507
- #throw(:close, @selected_index)
508
- }
509
- button_ct += 1
510
- bcol += text.length+6
511
- end
512
- end
513
- def center_column textlen
514
- width = @col + @width
515
- return (width-textlen)/2
516
- end
517
-
518
- ## ADD ABOVE
519
- end # class
520
-
521
- class Tab
522
- attr_accessor :text
523
- attr_reader :config
524
- attr_reader :items
525
- attr_accessor :parent_component
526
- attr_accessor :index
527
- attr_accessor :button # so you can set an event on it 2011-10-4
528
- attr_accessor :row_offset
529
- attr_accessor :col_offset
530
- def initialize text, parent_component, aconfig={}, &block
531
- @text = text
532
- @items = []
533
- @config = aconfig
534
- @parent_component = parent_component
535
- @row_offset ||= 2
536
- @col_offset ||= 2
537
- @config.each_pair { |k,v| variable_set(k,v) }
538
- instance_eval &block if block_given?
539
- end
540
- def item widget
541
- widget.form = @parent_component.form
542
- widget.override_graphic @parent_component.form.window
543
- # these will fail if TP put inside some other container. NOTE
544
- widget.row ||= 0
545
- widget.col ||= 0
546
- # If we knew it was only widget we could expand it
547
- if widget.kind_of?(Container) #|| widget.respond_to?(:width)
548
- widget.width ||= @parent_component.width-3
549
- end
550
- # Darn ! this was setting Label to fully height
551
- if widget.kind_of?(Container) #|| widget.respond_to?(:height)
552
- widget.height ||= @parent_component.height-3
553
- end
554
- # i don't know button_offset as yet
555
- widget.row += @row_offset + @parent_component.row + 1
556
- widget.col += @col_offset + @parent_component.col
557
- @items << widget
558
- end
559
- end # class tab
560
- class TabButton < RadioButton
561
- attr_accessor :display_tab_on_traversal
562
- def getvalue_for_paint
563
- @text
564
- end
565
- def selected?
566
- @variable.value == @value
567
- end
568
-
569
- end
570
-
571
- end # module
572
- if __FILE__ == $PROGRAM_NAME
573
- require 'rbcurse/app'
574
- require 'rbcurse/rcontainer'
575
- App.new do
576
- #r = Container.new nil, :row => 1, :col => 2, :width => 40, :height => 10, :title => "A container"
577
- r = Container.new nil, :suppress_borders => true
578
- f1 = field "name", :maxlen => 20, :display_length => 20, :bgcolor => :white,
579
- :color => :black, :text => "abc", :label => ' Name: '
580
- f2 = field "email", :display_length => 20, :bgcolor => :white,
581
- :color => :blue, :text => "me@google.com", :label => 'Email: '
582
- f3 = radio :group => :grp, :text => "red", :value => "RED", :color => :red
583
- f4 = radio :group => :grp, :text => "blue", :value => "BLUE", :color => :blue
584
- f5 = radio :group => :grp, :text => "green", :value => "GREEN", :color => :green
585
- r.add(f1)
586
- r.add(f2)
587
- r.add(f3,f4,f5)
588
- NewTabbedPane.new @form, :row => 3, :col => 5, :width => 60, :height => 20 do
589
- title "User Setup"
590
- button_type :ok_apply_cancel
591
- tab "&Profile" do
592
- item Field.new nil, :row => 2, :col => 2, :text => "enter your name", :label => ' Name: '
593
- item Field.new nil, :row => 3, :col => 2, :text => "enter your email", :label => 'Email: '
594
- end
595
- tab "&Settings" do
596
- item CheckBox.new nil, :row => 2, :col => 2, :text => "Use HTTPS", :mnemonic => 'u'
597
- item CheckBox.new nil, :row => 3, :col => 2, :text => "Quit with confirm", :mnemonic => 'q'
598
- end
599
- tab "&Term" do
600
- radio = Variable.new
601
- item RadioButton.new nil, :row => 2, :col => 2, :text => "&xterm", :value => "xterm", :variable => radio
602
- item RadioButton.new nil, :row => 3, :col => 2, :text => "sc&reen", :value => "screen", :variable => radio
603
- radio.update_command() {|rb| ENV['TERM']=rb.value }
604
- end
605
- tab "Conta&iner" do
606
- item r
607
- end
608
-
609
- end
610
- end # app
611
-
612
- end