rbcurse 1.4.0 → 1.4.1.pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/NOTES +68 -0
- data/README.markdown +73 -330
- data/TODO2.txt +2 -2
- data/VERSION +1 -1
- data/examples/abasiclist.rb +8 -2
- data/examples/alpmenu.rb +1 -1
- data/examples/app.rb +1 -24
- data/examples/appdirtree.rb +1 -1
- data/examples/appemail.rb +8 -14
- data/examples/appemaillb.rb +2 -2
- data/examples/appgcompose.rb +7 -5
- data/examples/common/file.rb +40 -0
- data/examples/{rmail.rb → common/rmail.rb} +0 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +60 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/{todocsv.csv → data/todocsv.csv} +0 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +49 -14
- data/examples/{appgmail.rb → deprecated/appgmail.rb} +1 -1
- data/examples/{splitp.rb → deprecated/splitp.rb} +0 -0
- data/examples/{testscrolllb.rb → deprecated/testscrolllb.rb} +0 -0
- data/examples/{testscrollp.rb → deprecated/testscrollp.rb} +0 -0
- data/examples/{testscrollta.rb → deprecated/testscrollta.rb} +0 -0
- data/examples/{testscrolltable.rb → deprecated/testscrolltable.rb} +0 -0
- data/examples/{testsplit.rb → deprecated/testsplit.rb} +0 -0
- data/examples/{testsplit2.rb → deprecated/testsplit2.rb} +0 -0
- data/examples/{testsplit3.rb → deprecated/testsplit3.rb} +0 -0
- data/examples/{testsplit3_1.rb → deprecated/testsplit3_1.rb} +0 -0
- data/examples/{testsplit3a.rb → deprecated/testsplit3a.rb} +0 -0
- data/examples/{testsplit3b.rb → deprecated/testsplit3b.rb} +0 -0
- data/examples/{testsplitta.rb → deprecated/testsplitta.rb} +0 -0
- data/examples/{testsplittv.rb → deprecated/testsplittv.rb} +0 -0
- data/examples/{testsplittvv.rb → deprecated/testsplittvv.rb} +0 -0
- data/examples/{testtpane.rb → deprecated/testtpane.rb} +0 -0
- data/examples/{testtpane2.rb → deprecated/testtpane2.rb} +0 -0
- data/examples/{testtpanetable.rb → deprecated/testtpanetable.rb} +0 -0
- data/examples/dirtree.rb +17 -7
- data/examples/experimental/resultsetdemo.rb +280 -0
- data/examples/experimental/testmform.rb +35 -0
- data/examples/{testscroller.rb → experimental/testscroller.rb} +1 -19
- data/examples/experimental/teststackflow.rb +111 -0
- data/examples/menu1.rb +1 -0
- data/examples/multispl.rb +4 -4
- data/examples/newmessagebox.rb +130 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +0 -3
- data/examples/qdfilechooser.rb +0 -3
- data/examples/rfe.rb +134 -18
- data/examples/rfe_renderer.rb +48 -2
- data/examples/sqlc.rb +2 -1
- data/examples/sqlm.rb +0 -2
- data/examples/table1.rb +1 -7
- data/examples/term2.rb +4 -1
- data/examples/test1.rb +0 -5
- data/examples/test2.rb +42 -31
- data/examples/testapp2.rb +8 -1
- data/examples/testchars.rb +0 -4
- data/examples/testcombo.rb +5 -9
- data/examples/testkeypress.rb +0 -3
- data/examples/testmenu.rb +0 -4
- data/examples/testmulticomp.rb +3 -5
- data/examples/testmulticontainer.rb +94 -0
- data/examples/testtable.rb +0 -5
- data/examples/testtabp.rb +16 -18
- data/examples/testtodo.rb +1 -5
- data/examples/testwsshortcuts.rb +64 -0
- data/examples/testwsshortcuts2.rb +126 -0
- data/examples/viewtodo.rb +1 -4
- data/lib/rbcurse.rb +1 -1
- data/lib/rbcurse/app.rb +92 -69
- data/lib/rbcurse/applicationheader.rb +46 -6
- data/lib/rbcurse/celleditor.rb +1 -9
- data/lib/rbcurse/comboboxcellrenderer.rb +0 -4
- data/lib/rbcurse/common/ansiparser.rb +117 -0
- data/{examples → lib/rbcurse/common}/appmethods.rb +25 -0
- data/lib/rbcurse/common/basestack.rb +407 -0
- data/lib/rbcurse/common/bordertitle.rb +41 -0
- data/lib/rbcurse/common/chunk.rb +177 -0
- data/lib/rbcurse/common/colorparser.rb +71 -0
- data/lib/rbcurse/common/keydefs.rb +30 -0
- data/lib/rbcurse/common/widgetshortcuts.rb +302 -0
- data/lib/rbcurse/deprecated/README.markdown +12 -0
- data/lib/rbcurse/{rscrollpane.rb → deprecated/rscrollpane.rb} +0 -0
- data/lib/rbcurse/{rsplitpane.rb → deprecated/rsplitpane.rb} +0 -0
- data/lib/rbcurse/{rsplitpane2.rb → deprecated/rsplitpane2.rb} +0 -0
- data/lib/rbcurse/{rviewport.rb → deprecated/rviewport.rb} +0 -0
- data/lib/rbcurse/experimental/README.markdown +14 -0
- data/lib/rbcurse/experimental/resultsettextview.rb +585 -0
- data/lib/rbcurse/experimental/stackflow.rb +478 -0
- data/lib/rbcurse/extras/bottomline.rb +85 -16
- data/lib/rbcurse/extras/box.rb +58 -0
- data/lib/rbcurse/extras/directorylist.rb +1 -1
- data/lib/rbcurse/extras/horizlist.rb +203 -0
- data/lib/rbcurse/extras/listselectable.rb +8 -0
- data/lib/rbcurse/extras/multiform.rb +330 -0
- data/lib/rbcurse/extras/multilinelabel.rb +142 -0
- data/lib/rbcurse/extras/newmessagebox.rb +328 -0
- data/lib/rbcurse/extras/newtabbedpane.rb +612 -0
- data/lib/rbcurse/extras/newtabbedwindow.rb +68 -0
- data/lib/rbcurse/extras/padreader.rb +189 -0
- data/lib/rbcurse/extras/rcomboedit.rb +256 -0
- data/lib/rbcurse/extras/resultsetbrowser.rb +281 -0
- data/lib/rbcurse/extras/statusline.rb +44 -6
- data/lib/rbcurse/extras/tabularwidget.rb +141 -104
- data/lib/rbcurse/extras/textpad.rb +516 -0
- data/lib/rbcurse/extras/viewer.rb +2 -0
- data/lib/rbcurse/io.rb +120 -3
- data/lib/rbcurse/listcellrenderer.rb +2 -1
- data/lib/rbcurse/listkeys.rb +1 -1
- data/lib/rbcurse/listscrollable.rb +72 -7
- data/lib/rbcurse/rbasiclistbox.rb +64 -12
- data/lib/rbcurse/rchangeevent.rb +0 -1
- data/lib/rbcurse/rcombo.rb +54 -59
- data/lib/rbcurse/rcommandwindow.rb +46 -10
- data/lib/rbcurse/rcontainer.rb +415 -0
- data/lib/rbcurse/rdialogs.rb +242 -165
- data/lib/rbcurse/rinputdataevent.rb +0 -1
- data/lib/rbcurse/rlistbox.rb +19 -9
- data/lib/rbcurse/rmessagebox.rb +1 -5
- data/lib/rbcurse/rmulticontainer.rb +64 -61
- data/lib/rbcurse/rmultitextview.rb +0 -2
- data/lib/rbcurse/rpopupmenu.rb +0 -2
- data/lib/rbcurse/rscrollform.rb +61 -12
- data/lib/rbcurse/rtabbedpane.rb +89 -73
- data/lib/rbcurse/rtabbedwindow.rb +53 -211
- data/lib/rbcurse/rtable.rb +0 -2
- data/lib/rbcurse/rtextarea.rb +14 -14
- data/lib/rbcurse/rtextview.rb +165 -50
- data/lib/rbcurse/rvimsplit.rb +15 -12
- data/lib/rbcurse/rwidget.rb +404 -150
- data/lib/rbcurse/table/tablecellrenderer.rb +1 -4
- data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -3
- data/lib/ver/ncurses.rb +1 -9
- data/lib/ver/rpad.rb +375 -0
- data/lib/ver/window.rb +262 -440
- metadata +73 -31
@@ -0,0 +1,328 @@
|
|
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
|
@@ -0,0 +1,612 @@
|
|
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
|