canis 0.0.4

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 (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES +52 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +24 -0
  7. data/Rakefile +2 -0
  8. data/canis.gemspec +25 -0
  9. data/examples/alpmenu.rb +46 -0
  10. data/examples/app.sample +19 -0
  11. data/examples/appemail.rb +191 -0
  12. data/examples/atree.rb +105 -0
  13. data/examples/bline.rb +181 -0
  14. data/examples/common/devel.rb +319 -0
  15. data/examples/common/file.rb +93 -0
  16. data/examples/data/README.markdown +9 -0
  17. data/examples/data/brew.txt +38 -0
  18. data/examples/data/color.2 +37 -0
  19. data/examples/data/gemlist.txt +59 -0
  20. data/examples/data/lotr.txt +12 -0
  21. data/examples/data/ports.txt +136 -0
  22. data/examples/data/table.txt +37 -0
  23. data/examples/data/tasks.csv +88 -0
  24. data/examples/data/tasks.txt +27 -0
  25. data/examples/data/todo.txt +16 -0
  26. data/examples/data/todocsv.csv +28 -0
  27. data/examples/data/unix1.txt +21 -0
  28. data/examples/data/unix2.txt +11 -0
  29. data/examples/dbdemo.rb +506 -0
  30. data/examples/dirtree.rb +177 -0
  31. data/examples/newtabbedwindow.rb +100 -0
  32. data/examples/newtesttabp.rb +92 -0
  33. data/examples/tabular.rb +212 -0
  34. data/examples/tasks.rb +179 -0
  35. data/examples/term2.rb +88 -0
  36. data/examples/testbuttons.rb +307 -0
  37. data/examples/testcombo.rb +102 -0
  38. data/examples/testdb.rb +182 -0
  39. data/examples/testfields.rb +208 -0
  40. data/examples/testflowlayout.rb +43 -0
  41. data/examples/testkeypress.rb +98 -0
  42. data/examples/testlistbox.rb +187 -0
  43. data/examples/testlistbox1.rb +199 -0
  44. data/examples/testmessagebox.rb +144 -0
  45. data/examples/testprogress.rb +116 -0
  46. data/examples/testree.rb +107 -0
  47. data/examples/testsplitlayout.rb +53 -0
  48. data/examples/testsplitlayout1.rb +49 -0
  49. data/examples/teststacklayout.rb +48 -0
  50. data/examples/testwsshortcuts.rb +68 -0
  51. data/examples/testwsshortcuts2.rb +129 -0
  52. data/lib/canis.rb +16 -0
  53. data/lib/canis/core/docs/index.txt +104 -0
  54. data/lib/canis/core/docs/list.txt +16 -0
  55. data/lib/canis/core/docs/style_help.yml +34 -0
  56. data/lib/canis/core/docs/tabbedpane.txt +15 -0
  57. data/lib/canis/core/docs/table.txt +31 -0
  58. data/lib/canis/core/docs/textpad.txt +48 -0
  59. data/lib/canis/core/docs/tree.txt +23 -0
  60. data/lib/canis/core/include/.DS_Store +0 -0
  61. data/lib/canis/core/include/action.rb +83 -0
  62. data/lib/canis/core/include/actionmanager.rb +49 -0
  63. data/lib/canis/core/include/appmethods.rb +179 -0
  64. data/lib/canis/core/include/bordertitle.rb +49 -0
  65. data/lib/canis/core/include/canisparser.rb +100 -0
  66. data/lib/canis/core/include/colorparser.rb +437 -0
  67. data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
  68. data/lib/canis/core/include/io.rb +320 -0
  69. data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
  70. data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
  71. data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
  72. data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
  73. data/lib/canis/core/include/listbindings.rb +89 -0
  74. data/lib/canis/core/include/listeditable.rb +319 -0
  75. data/lib/canis/core/include/listoperations.rb +61 -0
  76. data/lib/canis/core/include/listselectionmodel.rb +388 -0
  77. data/lib/canis/core/include/multibuffer.rb +173 -0
  78. data/lib/canis/core/include/ractionevent.rb +73 -0
  79. data/lib/canis/core/include/rchangeevent.rb +27 -0
  80. data/lib/canis/core/include/rhistory.rb +95 -0
  81. data/lib/canis/core/include/rinputdataevent.rb +47 -0
  82. data/lib/canis/core/include/textdocument.rb +111 -0
  83. data/lib/canis/core/include/vieditable.rb +175 -0
  84. data/lib/canis/core/include/widgetmenu.rb +66 -0
  85. data/lib/canis/core/system/colormap.rb +165 -0
  86. data/lib/canis/core/system/keydefs.rb +32 -0
  87. data/lib/canis/core/system/ncurses.rb +237 -0
  88. data/lib/canis/core/system/panel.rb +129 -0
  89. data/lib/canis/core/system/window.rb +1081 -0
  90. data/lib/canis/core/util/ansiparser.rb +119 -0
  91. data/lib/canis/core/util/app.rb +696 -0
  92. data/lib/canis/core/util/basestack.rb +412 -0
  93. data/lib/canis/core/util/defaultcolorparser.rb +84 -0
  94. data/lib/canis/core/util/extras/README +5 -0
  95. data/lib/canis/core/util/extras/bottomline.rb +1815 -0
  96. data/lib/canis/core/util/extras/padreader.rb +192 -0
  97. data/lib/canis/core/util/focusmanager.rb +31 -0
  98. data/lib/canis/core/util/helpmanager.rb +160 -0
  99. data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
  100. data/lib/canis/core/util/promptmenu.rb +235 -0
  101. data/lib/canis/core/util/rcommandwindow.rb +933 -0
  102. data/lib/canis/core/util/rdialogs.rb +520 -0
  103. data/lib/canis/core/util/textutils.rb +74 -0
  104. data/lib/canis/core/util/viewer.rb +238 -0
  105. data/lib/canis/core/util/widgetshortcuts.rb +508 -0
  106. data/lib/canis/core/widgets/applicationheader.rb +103 -0
  107. data/lib/canis/core/widgets/box.rb +58 -0
  108. data/lib/canis/core/widgets/divider.rb +310 -0
  109. data/lib/canis/core/widgets/extras/README.md +12 -0
  110. data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
  111. data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
  112. data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
  113. data/lib/canis/core/widgets/listbox.rb +326 -0
  114. data/lib/canis/core/widgets/listfooter.rb +86 -0
  115. data/lib/canis/core/widgets/rcombo.rb +210 -0
  116. data/lib/canis/core/widgets/rcontainer.rb +415 -0
  117. data/lib/canis/core/widgets/rlink.rb +30 -0
  118. data/lib/canis/core/widgets/rmenu.rb +970 -0
  119. data/lib/canis/core/widgets/rmenulink.rb +30 -0
  120. data/lib/canis/core/widgets/rmessagebox.rb +400 -0
  121. data/lib/canis/core/widgets/rprogress.rb +118 -0
  122. data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
  123. data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
  124. data/lib/canis/core/widgets/rwidget.rb +3634 -0
  125. data/lib/canis/core/widgets/scrollbar.rb +147 -0
  126. data/lib/canis/core/widgets/statusline.rb +113 -0
  127. data/lib/canis/core/widgets/table.rb +1072 -0
  128. data/lib/canis/core/widgets/tabular.rb +264 -0
  129. data/lib/canis/core/widgets/textpad.rb +1674 -0
  130. data/lib/canis/core/widgets/tree.rb +690 -0
  131. data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
  132. data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
  133. data/lib/canis/version.rb +3 -0
  134. metadata +229 -0
@@ -0,0 +1,631 @@
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: jkepler (http://github.com/mare-imbrium/canis/)
7
+ * Date: 2011-10-20
8
+ * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
9
+ * Last update: 2014-07-10 00:29
10
+
11
+ == CHANGES
12
+ As of 1.5.0, this replaces the earlier TabbedPane which
13
+ now lies in lib/canis/deprecated/widgets
14
+ in the canis repo.
15
+ == TODO
16
+ on start first buttons bottom should not be lined.
17
+ Alt-1-9 to goto tabs
18
+ add remove tabs at any time - started, untested
19
+ events for tab add/remove/etc
20
+ =end
21
+ require 'canis'
22
+ ##
23
+ module Canis
24
+ class TabbedPane < Widget
25
+ dsl_property :title, :title_attrib
26
+ # what kind of buttons, if this is a window, :ok :ok_camcel :ok_apply_cancel
27
+ dsl_accessor :button_type
28
+ attr_reader :button_row
29
+ # index of tab that is currently open
30
+ attr_reader :current_tab
31
+
32
+
33
+ def initialize form=nil, config={}, &block
34
+ @_events ||= []
35
+ @_events.push(:PRESS)
36
+ @button_gap = 2
37
+ init_vars
38
+ super
39
+ @focusable = true
40
+ @editable = true
41
+ @col_offset = 2
42
+ raise ArgumentError, "NewTabbedPane : row or col not set: r: #{@row} c: #{@col} " unless @row && @col
43
+ end
44
+
45
+ # Add a tab
46
+ # @param String name of tab, may have ampersand for hotkey/accelerator
47
+ def tab title, config={}, &block
48
+ #@tab_components[title]=[]
49
+ #@tabs << Tab.new(title, self, config, &block)
50
+ insert_tab @tabs.count, title, config, &block
51
+ self
52
+ end
53
+ alias :add_tab :tab
54
+
55
+ # a shortcut for binding a command to a press of an action button
56
+ # The block will be passed
57
+ # This is only relevant if you have asked for buttons to be created, which is
58
+ # only relevant in a TabbedWindow
59
+ # ActionEvent has source event and action_command
60
+ def command *args, &block
61
+ bind :PRESS, *args, &block
62
+ end
63
+
64
+ # -------------- tab maintenance commands ------------------ #
65
+
66
+ # insert a tab at index, with title
67
+ def insert_tab index, title, config={}, &block
68
+ @tabs.insert(index, Tab.new(title, self, config, &block) )
69
+ end
70
+ # remove given tab
71
+ def remove_tab tab
72
+ @tabs.delete tab
73
+ self
74
+ end
75
+ # remove all tabs
76
+ def remove_all
77
+ @tabs = []
78
+ self
79
+ end
80
+ # remove tab at given index, defaulting to current
81
+ def remove_tab_at index = @current_tab
82
+ @tabs.delete_at index
83
+ end
84
+
85
+ def repaint
86
+ @current_tab ||= 0
87
+ @button_row ||= @row + 2
88
+ @separator_row = @button_row + 1 # hope we have it by now, where to print separator
89
+ @separator_row0 = @button_row - 1 unless @button_row == @row + 1
90
+ @separator_row2 = @row + @height - 3 # hope we have it by now, where to print separator
91
+ #return unless @repaint_required
92
+ if @buttons.empty?
93
+ _create_buttons
94
+ @components = @buttons.dup
95
+ @components.push(*@tabs[@current_tab].items)
96
+ create_action_buttons
97
+ @components.push(*@action_buttons)
98
+ elsif @tab_changed
99
+ @components = @buttons.dup
100
+ @components.push(*@tabs[@current_tab].items)
101
+ @components.push(*@action_buttons)
102
+ @tab_changed = false
103
+ end
104
+ # if some major change has happened then repaint everything
105
+ if @repaint_required
106
+ $log.debug " NEWTAB repaint graphic #{@graphic} "
107
+ print_borders unless @suppress_borders # do this once only, unless everything changes
108
+ print_separator1
109
+ @components.each { |e| e.repaint_all(true); e.repaint }
110
+ else
111
+ @components.each { |e| e.repaint }
112
+ end # if repaint_required
113
+ # next line is not called. earlier the 's' was missing, suppress_borders is not false
114
+ print_borders if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
115
+ @repaint_required = false
116
+ end
117
+ def handle_key ch
118
+ $log.debug " NEWTABBED handle_key #{ch} "
119
+ return if @components.empty?
120
+ _multiplier = ($multiplier == 0 ? 1 : $multiplier )
121
+
122
+ # should this go here 2011-10-19
123
+ unless @_entered
124
+ $log.warn "WARN: calling ON_ENTER since in this situation it was not called"
125
+ on_enter
126
+ end
127
+ #if ch == KEY_TAB
128
+ #$log.debug "NEWTABBED GOTO NEXT"
129
+ #return goto_next_component
130
+ #elsif ch == KEY_BTAB
131
+ #return goto_prev_component
132
+ #end
133
+ comp = @current_component
134
+ $log.debug " NEWTABBED handle_key #{ch}: #{comp}"
135
+ if comp
136
+ ret = comp.handle_key(ch)
137
+ $log.debug " NEWTABBED handle_key#{ch}: #{comp} returned #{ret} "
138
+ if ret != :UNHANDLED
139
+ comp.repaint # NOTE: if we don;t do this, then it won't get repainted. I will have to repaint ALL
140
+ # in repaint of this.
141
+ return ret
142
+ end
143
+ $log.debug "XXX NEWTABBED key unhandled by comp #{comp.name} "
144
+ else
145
+ Ncurses.beep
146
+ $log.warn "XXX NEWTABBED key unhandled NULL comp"
147
+ end
148
+ case ch
149
+ when ?\C-c.getbyte(0)
150
+ $multiplier = 0
151
+ return 0
152
+ when ?0.getbyte(0)..?9.getbyte(0)
153
+ $log.debug " VIM coming here to set multiplier #{$multiplier} "
154
+ $multiplier *= 10 ; $multiplier += (ch-48)
155
+ return 0
156
+ end
157
+ ret = process_key ch, self
158
+ # allow user to map left and right if he wants
159
+ if ret == :UNHANDLED
160
+ case ch
161
+ when KEY_UP, KEY_BTAB
162
+ # form will pick this up and do needful
163
+ return goto_prev_component #unless on_first_component?
164
+ when KEY_LEFT
165
+ # if i don't check for first component, key will go back to form,
166
+ # but not be processes. so focussed remain here, but be false.
167
+ # In case of returnign an unhandled TAB, on_leave will happen and cursor will move to
168
+ # previous component outside of this.
169
+ return goto_prev_component unless on_first_component?
170
+ when KEY_RIGHT, KEY_TAB
171
+ return goto_next_component #unless on_last_component?
172
+ when KEY_DOWN
173
+ if on_a_button?
174
+ return goto_first_item
175
+ else
176
+ return goto_next_component #unless on_last_component?
177
+ end
178
+ else
179
+ #@_entered = false
180
+ return :UNHANDLED
181
+ end
182
+ end
183
+
184
+ $multiplier = 0
185
+ return 0
186
+ end
187
+ # on enter processing
188
+ # Very often the first may be a label !
189
+ def on_enter
190
+ # if BTAB, the last comp
191
+ if $current_key == KEY_BTAB
192
+ @current_component = @components.last
193
+ else
194
+ @current_component = @components.first
195
+ end
196
+ return unless @current_component
197
+ $log.debug " NEWTABBED came to ON_ENTER #{@current_component} "
198
+ set_form_row
199
+ @_entered = true
200
+ end
201
+ def on_leave
202
+ @_entered = false
203
+ super
204
+ end
205
+ # takes focus to first item (after buttons)
206
+ def goto_first_item
207
+ bc = @buttons.count
208
+ @components[bc..-1].each { |c|
209
+ if c.focusable
210
+ leave_current_component
211
+ @current_component = c
212
+ set_form_row
213
+ break
214
+ end
215
+ }
216
+ end
217
+
218
+ # takes focus to last item
219
+ def goto_last_item
220
+ bc = @buttons.count
221
+ f = nil
222
+ @components[bc..-1].each { |c|
223
+ if c.focusable
224
+ f = c
225
+ end
226
+ }
227
+ if f
228
+ leave_current_component
229
+ @current_component = f
230
+ set_form_row
231
+ end
232
+ end
233
+ # take focus to the next component or item
234
+ # Called from DOWN, RIGHT or Tab
235
+ def goto_next_component
236
+ if @current_component != nil
237
+ leave_current_component
238
+ if on_last_component?
239
+ @_entered = false
240
+ return :UNHANDLED
241
+ end
242
+ @current_index = @components.index(@current_component)
243
+ index = @current_index + 1
244
+ index.upto(@components.length-1) do |i|
245
+ f = @components[i]
246
+ if f.focusable
247
+ @current_index = i
248
+ @current_component = f
249
+ return set_form_row
250
+ end
251
+ end
252
+ end
253
+ @_entered = false
254
+ return :UNHANDLED
255
+ end
256
+ # take focus to prev component or item
257
+ # Called from LEFT, UP or Back Tab
258
+ def goto_prev_component
259
+ if @current_component != nil
260
+ leave_current_component
261
+ if on_first_component?
262
+ @_entered = false
263
+ return :UNHANDLED
264
+ end
265
+ @current_index = @components.index(@current_component)
266
+ index = @current_index -= 1
267
+ index.downto(0) do |i|
268
+ f = @components[i]
269
+ if f.focusable
270
+ @current_index = i
271
+ @current_component = f
272
+ return set_form_row
273
+ end
274
+ end
275
+ end
276
+ return :UNHANDLED
277
+ end
278
+ # private
279
+ def set_form_row
280
+ return :UNHANDLED if @current_component.nil?
281
+ $log.debug " NEWTABBED on enter sfr #{@current_component} "
282
+ @current_component.on_enter
283
+ @current_component.set_form_row # why was this missing in vimsplit. is it
284
+ # that on_enter does a set_form_row
285
+ @current_component.set_form_col # XXX
286
+ @current_component.repaint
287
+ # XXX compo should do set_form_row and col if it has that
288
+ end
289
+ # private
290
+ def set_form_col
291
+ return if @current_component.nil?
292
+ $log.debug " #{@name} NEWTABBED set_form_col calling sfc for #{@current_component.name} "
293
+ @current_component.set_form_col
294
+ end
295
+ # leave the component we are on.
296
+ # This should be followed by all containers, so that the on_leave action
297
+ # of earlier comp can be displayed, such as dimming components selections
298
+ def leave_current_component
299
+ @current_component.on_leave
300
+ # NOTE this is required, since repaint will just not happen otherwise
301
+ # Some components are erroneously repainting all, after setting this to true so it is
302
+ # working there.
303
+ @current_component.repaint_required true
304
+ $log.debug " after on_leave VIMS XXX #{@current_component.focussed} #{@current_component.name}"
305
+ @current_component.repaint
306
+ end
307
+
308
+ # is focus on first component
309
+ def on_first_component?
310
+ @current_component == @components.first
311
+ end
312
+ # is focus on last component
313
+ def on_last_component?
314
+ @current_component == @components.last
315
+ end
316
+ # returns true if user on an action button
317
+ # @return true or false
318
+ def on_a_button?
319
+ @components.index(@current_component) < @buttons.count
320
+ end
321
+ # set focus on given component
322
+ # Sometimes you have the handle to component, and you want to move focus to it
323
+ def goto_component comp
324
+ return if comp == @current_component
325
+ leave_current_component
326
+ @current_component = comp
327
+ set_form_row
328
+ end
329
+ # set current tab to given tab
330
+ # @return self
331
+ def set_current_tab t
332
+ return if @current_tab == t
333
+ @current_tab = t
334
+ goto_component @components[t]
335
+ @tab_changed = true
336
+ @repaint_required = true
337
+ self
338
+ end
339
+
340
+
341
+ # Put all the housekeeping stuff at the end
342
+ private
343
+ def init_vars
344
+ @buttons = []
345
+ @tabs = []
346
+ #@tab_components = {}
347
+ @bottombuttons = []
348
+ #
349
+ # I'll keep current tabs comps in this to simplify
350
+ @components = []
351
+ @_entered = false
352
+ # added on 2014-05-30 - 12:13 otherwise borders not printed first time
353
+ @repaint_all = true
354
+ @repaint_required = true
355
+ end
356
+
357
+ def map_keys
358
+ @keys_mapped = true
359
+ #bind_key(?q, :myproc)
360
+ #bind_key(32, :myproc)
361
+ end
362
+
363
+ # creates the tab buttons (which are radio buttons)
364
+ def _create_buttons
365
+ $log.debug "XXX: INSIDE create_buttons col_offset #{@col_offset} "
366
+ v = Variable.new
367
+ r = @button_row # @row + 1
368
+ col = @col + @col_offset
369
+ @tabs.each_with_index { |t, i|
370
+ txt = t.text
371
+ @buttons << TabButton.new(nil) do
372
+ variable v
373
+ text txt
374
+ name txt
375
+ #value txt
376
+ row r
377
+ col col
378
+ surround_chars ['','']
379
+ selected_bgcolor 'green'
380
+ selected_color 'white'
381
+
382
+ end
383
+ b = @buttons.last
384
+ b.command do
385
+ set_current_tab i
386
+ end
387
+ b.form = @form
388
+ b.override_graphic @graphic
389
+ col += txt.length + @button_gap
390
+ }
391
+ end # _create_buttons
392
+ private
393
+ def print_borders
394
+ width = @width
395
+ height = @height-1
396
+ window = @graphic
397
+ startcol = @col
398
+ startrow = @row
399
+ @color_pair = get_color($datacolor)
400
+ $log.debug "NTP #{name}: window.print_border #{startrow}, #{startcol} , h:#{height}, w:#{width} , @color_pair, @attr "
401
+ window.print_border startrow, startcol, height, width, @color_pair, @attr
402
+ print_title
403
+ end
404
+ def print_separator1
405
+
406
+ width = @width
407
+ height = @height-1
408
+ window = @graphic
409
+ startcol = @col
410
+ startrow = @row
411
+ @color_pair = get_color($datacolor)
412
+ r = @separator_row
413
+ c = @col + @col_offset
414
+
415
+ urcorner = []
416
+ #window.printstring r, c, '-' * (@width-2), @color_pair, @attr
417
+ window.mvwhline( r, @col+1, Ncurses::ACS_HLINE, @width-2)
418
+ @buttons.each_with_index do |b, i|
419
+ l = b.text.length
420
+ if b.selected?
421
+ if false #c == @col + @col_offset
422
+ cc = c
423
+ ll = l+1
424
+ else
425
+ cc = c-1
426
+ ll = l+2
427
+ end
428
+ #rr = r -1 #unless rr == @col
429
+ window.printstring r, cc, " "*ll, @color_pair, @attr
430
+ #window.printstring r, cc-1, FFI::NCurses::ACS_HLINE.chr*ll, @color_pair, @attr
431
+ #window.printstring r-2, cc, FFI::NCurses::ACS_HLINE.chr*ll, @color_pair, @attr
432
+ window.mvwaddch r, cc-1, FFI::NCurses::ACS_LRCORNER unless cc-1 <= @col
433
+ window.mvwaddch r, c+l+1, FFI::NCurses::ACS_LLCORNER
434
+ else
435
+ window.mvwaddch r, c+l+1, FFI::NCurses::ACS_BTEE
436
+ end
437
+
438
+ #window.printstring r-2, c, FFI::NCurses::ACS_HLINE*l, @color_pair, @attr
439
+ #tt = b.text
440
+ #window.printstring r, c, tt, @color_pair, @attr
441
+ c += l + 1
442
+ #window.mvwaddch r, c, '+'.ord
443
+ window.mvwaddch r-1, c, FFI::NCurses::ACS_VLINE
444
+ window.mvwaddch r-2, c, FFI::NCurses::ACS_URCORNER #ACS_TTEE
445
+ #window.mvwaddch r-2, c+1, '/'.ord
446
+ urcorner << c
447
+ c+=@button_gap
448
+ end
449
+ window.mvwhline( @separator_row0, @col + 1, Ncurses::ACS_HLINE, c-@col-1-@button_gap)
450
+ window.mvwhline( @separator_row2, @col + 1, Ncurses::ACS_HLINE, @width-2)
451
+ urcorner.each do |c|
452
+ window.mvwaddch r-2, c, FFI::NCurses::ACS_URCORNER #ACS_TTEE
453
+ end
454
+ end
455
+ def print_title
456
+ return unless @title
457
+ _title = @title
458
+ if @title.length > @width - 2
459
+ _title = @title[0..@width-2]
460
+ end
461
+ @graphic.printstring( @row, @col+(@width-_title.length)/2, _title,
462
+ @color_pair, @title_attrib) unless @title.nil?
463
+ end
464
+
465
+ #
466
+ # Decides which buttons are to be created
467
+ # create the buttons at the bottom OK/ APPLY/ CANCEL
468
+
469
+ def create_action_buttons
470
+ return unless @button_type
471
+ case @button_type.to_s.downcase
472
+ when "ok"
473
+ make_buttons ["&OK"]
474
+ when "ok_cancel" #, "input", "list", "field_list"
475
+ make_buttons %w[&OK &Cancel]
476
+ when "ok_apply_cancel" #, "input", "list", "field_list"
477
+ make_buttons %w[&OK &Apply &Cancel]
478
+ when "yes_no"
479
+ make_buttons %w[&Yes &No]
480
+ when "yes_no_cancel"
481
+ make_buttons ["&Yes", "&No", "&Cancel"]
482
+ when "custom"
483
+ raise "Blank list of buttons passed to custom" if @buttons.nil? or @buttons.size == 0
484
+ make_buttons @buttons
485
+ else
486
+ $log.warn "No buttontype passed for creating tabbedpane. Not creating any"
487
+ #make_buttons ["&OK"]
488
+ end
489
+ end
490
+
491
+ # actually creates the action buttons
492
+ def make_buttons names
493
+ @action_buttons = []
494
+ $log.debug "XXX: came to NTP make buttons FORM= #{@form.name} names #{names} "
495
+ total = names.inject(0) {|total, item| total + item.length + 4}
496
+ bcol = center_column total
497
+
498
+ # this craps out when height is zero
499
+ brow = @row + @height-2
500
+ brow = FFI::NCurses.LINES-2 if brow < 0
501
+ $log.debug "XXX: putting buttons :on #{brow} : #{@row} , #{@height} "
502
+ button_ct=0
503
+ tpp = self
504
+ names.each_with_index do |bname, ix|
505
+ text = bname
506
+ #underline = @underlines[ix] if !@underlines.nil?
507
+
508
+ button = Button.new nil do
509
+ text text
510
+ name bname
511
+ row brow
512
+ col bcol
513
+ #underline underline
514
+ highlight_bgcolor $reversecolor
515
+ color $datacolor
516
+ bgcolor $datacolor
517
+ end
518
+ @action_buttons << button
519
+ button.form = @form
520
+ button.override_graphic @graphic
521
+ index = button_ct
522
+ tpp = self
523
+ button.command { |form| @selected_index = index; @stop = true;
524
+ # ActionEvent has source event and action_command
525
+ fire_handler :PRESS, ActionEvent.new(tpp, index, button.text)
526
+ #throw(:close, @selected_index)
527
+ }
528
+ button_ct += 1
529
+ bcol += text.length+6
530
+ end
531
+ end
532
+ def center_column textlen
533
+ width = @col + @width
534
+ return (width-textlen)/2
535
+ end
536
+
537
+ ## ADD ABOVE
538
+ end # class
539
+
540
+ class Tab
541
+ attr_accessor :text
542
+ attr_reader :config
543
+ attr_reader :items
544
+ attr_accessor :parent_component
545
+ attr_accessor :index
546
+ attr_accessor :button # so you can set an event on it 2011-10-4
547
+ attr_accessor :row_offset
548
+ attr_accessor :col_offset
549
+ def initialize text, parent_component, aconfig={}, &block
550
+ @text = text
551
+ @items = []
552
+ @config = aconfig
553
+ @parent_component = parent_component
554
+ @row_offset ||= 2
555
+ @col_offset ||= 2
556
+ @config.each_pair { |k,v| variable_set(k,v) }
557
+ instance_eval &block if block_given?
558
+ end
559
+ def item widget
560
+ widget.form = @parent_component.form
561
+ widget.override_graphic @parent_component.form.window
562
+ # these will fail if TP put inside some other container. NOTE
563
+ widget.row ||= 0
564
+ widget.col ||= 0
565
+ # If we knew it was only widget we could expand it
566
+ if widget.kind_of?(Canis::Container) #|| widget.respond_to?(:width)
567
+ widget.width ||= @parent_component.width-3
568
+ end
569
+ # Darn ! this was setting Label to fully height
570
+ if widget.kind_of?(Canis::Container) #|| widget.respond_to?(:height)
571
+ widget.height ||= @parent_component.height-3
572
+ end
573
+ # i don't know button_offset as yet
574
+ widget.row += @row_offset + @parent_component.row + 1
575
+ widget.col += @col_offset + @parent_component.col
576
+ @items << widget
577
+ end
578
+ end # class tab
579
+ class TabButton < RadioButton
580
+ attr_accessor :display_tab_on_traversal
581
+ def getvalue_for_paint
582
+ @text
583
+ end
584
+ def selected?
585
+ @variable.value == @value
586
+ end
587
+
588
+ end
589
+
590
+ end # module
591
+ if __FILE__ == $PROGRAM_NAME
592
+ require 'canis/core/util/app'
593
+ require 'canis/core/widgets/rcontainer'
594
+ App.new do
595
+ #r = Container.new nil, :row => 1, :col => 2, :width => 40, :height => 10, :title => "A container"
596
+ r = Container.new nil, :suppress_borders => true
597
+ f1 = field "name", :maxlen => 20, :width => 20, :bgcolor => :white,
598
+ :color => :black, :text => "abc", :label => ' Name: '
599
+ f2 = field "email", :width => 20, :bgcolor => :white,
600
+ :color => :blue, :text => "me@google.com", :label => 'Email: '
601
+ f3 = radio :group => :grp, :text => "red", :value => "RED", :color => :red
602
+ f4 = radio :group => :grp, :text => "blue", :value => "BLUE", :color => :blue
603
+ f5 = radio :group => :grp, :text => "green", :value => "GREEN", :color => :green
604
+ r.add(f1)
605
+ r.add(f2)
606
+ r.add(f3,f4,f5)
607
+ TabbedPane.new @form, :row => 3, :col => 5, :width => 60, :height => 20 do
608
+ title "User Setup"
609
+ button_type :ok_apply_cancel
610
+ tab "&Profile" do
611
+ item LabeledField.new nil, :row => 2, :col => 2, :text => "enter your name", :label => ' Name: '
612
+ item LabeledField.new nil, :row => 3, :col => 2, :text => "enter your email", :label => 'Email: '
613
+ end
614
+ tab "&Settings" do
615
+ item CheckBox.new nil, :row => 2, :col => 2, :text => "Use HTTPS", :mnemonic => 'u'
616
+ item CheckBox.new nil, :row => 3, :col => 2, :text => "Quit with confirm", :mnemonic => 'q'
617
+ end
618
+ tab "&Term" do
619
+ radio = Variable.new
620
+ item RadioButton.new nil, :row => 2, :col => 2, :text => "&xterm", :value => "xterm", :variable => radio
621
+ item RadioButton.new nil, :row => 3, :col => 2, :text => "sc&reen", :value => "screen", :variable => radio
622
+ radio.update_command() {|rb| ENV['TERM']=rb.value }
623
+ end
624
+ tab "Conta&iner" do
625
+ item r
626
+ end
627
+
628
+ end
629
+ end # app
630
+
631
+ end