canis 0.0.4

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