canis 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/CHANGES +52 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +2 -0
- data/canis.gemspec +25 -0
- data/examples/alpmenu.rb +46 -0
- data/examples/app.sample +19 -0
- data/examples/appemail.rb +191 -0
- data/examples/atree.rb +105 -0
- data/examples/bline.rb +181 -0
- data/examples/common/devel.rb +319 -0
- data/examples/common/file.rb +93 -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 +59 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +16 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +506 -0
- data/examples/dirtree.rb +177 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +212 -0
- data/examples/tasks.rb +179 -0
- data/examples/term2.rb +88 -0
- data/examples/testbuttons.rb +307 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testdb.rb +182 -0
- data/examples/testfields.rb +208 -0
- data/examples/testflowlayout.rb +43 -0
- data/examples/testkeypress.rb +98 -0
- data/examples/testlistbox.rb +187 -0
- data/examples/testlistbox1.rb +199 -0
- data/examples/testmessagebox.rb +144 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +107 -0
- data/examples/testsplitlayout.rb +53 -0
- data/examples/testsplitlayout1.rb +49 -0
- data/examples/teststacklayout.rb +48 -0
- data/examples/testwsshortcuts.rb +68 -0
- data/examples/testwsshortcuts2.rb +129 -0
- data/lib/canis.rb +16 -0
- data/lib/canis/core/docs/index.txt +104 -0
- data/lib/canis/core/docs/list.txt +16 -0
- data/lib/canis/core/docs/style_help.yml +34 -0
- data/lib/canis/core/docs/tabbedpane.txt +15 -0
- data/lib/canis/core/docs/table.txt +31 -0
- data/lib/canis/core/docs/textpad.txt +48 -0
- data/lib/canis/core/docs/tree.txt +23 -0
- data/lib/canis/core/include/.DS_Store +0 -0
- data/lib/canis/core/include/action.rb +83 -0
- data/lib/canis/core/include/actionmanager.rb +49 -0
- data/lib/canis/core/include/appmethods.rb +179 -0
- data/lib/canis/core/include/bordertitle.rb +49 -0
- data/lib/canis/core/include/canisparser.rb +100 -0
- data/lib/canis/core/include/colorparser.rb +437 -0
- data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
- data/lib/canis/core/include/io.rb +320 -0
- data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
- data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
- data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
- data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
- data/lib/canis/core/include/listbindings.rb +89 -0
- data/lib/canis/core/include/listeditable.rb +319 -0
- data/lib/canis/core/include/listoperations.rb +61 -0
- data/lib/canis/core/include/listselectionmodel.rb +388 -0
- data/lib/canis/core/include/multibuffer.rb +173 -0
- data/lib/canis/core/include/ractionevent.rb +73 -0
- data/lib/canis/core/include/rchangeevent.rb +27 -0
- data/lib/canis/core/include/rhistory.rb +95 -0
- data/lib/canis/core/include/rinputdataevent.rb +47 -0
- data/lib/canis/core/include/textdocument.rb +111 -0
- data/lib/canis/core/include/vieditable.rb +175 -0
- data/lib/canis/core/include/widgetmenu.rb +66 -0
- data/lib/canis/core/system/colormap.rb +165 -0
- data/lib/canis/core/system/keydefs.rb +32 -0
- data/lib/canis/core/system/ncurses.rb +237 -0
- data/lib/canis/core/system/panel.rb +129 -0
- data/lib/canis/core/system/window.rb +1081 -0
- data/lib/canis/core/util/ansiparser.rb +119 -0
- data/lib/canis/core/util/app.rb +696 -0
- data/lib/canis/core/util/basestack.rb +412 -0
- data/lib/canis/core/util/defaultcolorparser.rb +84 -0
- data/lib/canis/core/util/extras/README +5 -0
- data/lib/canis/core/util/extras/bottomline.rb +1815 -0
- data/lib/canis/core/util/extras/padreader.rb +192 -0
- data/lib/canis/core/util/focusmanager.rb +31 -0
- data/lib/canis/core/util/helpmanager.rb +160 -0
- data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
- data/lib/canis/core/util/promptmenu.rb +235 -0
- data/lib/canis/core/util/rcommandwindow.rb +933 -0
- data/lib/canis/core/util/rdialogs.rb +520 -0
- data/lib/canis/core/util/textutils.rb +74 -0
- data/lib/canis/core/util/viewer.rb +238 -0
- data/lib/canis/core/util/widgetshortcuts.rb +508 -0
- data/lib/canis/core/widgets/applicationheader.rb +103 -0
- data/lib/canis/core/widgets/box.rb +58 -0
- data/lib/canis/core/widgets/divider.rb +310 -0
- data/lib/canis/core/widgets/extras/README.md +12 -0
- data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
- data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
- data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
- data/lib/canis/core/widgets/listbox.rb +326 -0
- data/lib/canis/core/widgets/listfooter.rb +86 -0
- data/lib/canis/core/widgets/rcombo.rb +210 -0
- data/lib/canis/core/widgets/rcontainer.rb +415 -0
- data/lib/canis/core/widgets/rlink.rb +30 -0
- data/lib/canis/core/widgets/rmenu.rb +970 -0
- data/lib/canis/core/widgets/rmenulink.rb +30 -0
- data/lib/canis/core/widgets/rmessagebox.rb +400 -0
- data/lib/canis/core/widgets/rprogress.rb +118 -0
- data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
- data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/canis/core/widgets/rwidget.rb +3634 -0
- data/lib/canis/core/widgets/scrollbar.rb +147 -0
- data/lib/canis/core/widgets/statusline.rb +113 -0
- data/lib/canis/core/widgets/table.rb +1072 -0
- data/lib/canis/core/widgets/tabular.rb +264 -0
- data/lib/canis/core/widgets/textpad.rb +1674 -0
- data/lib/canis/core/widgets/tree.rb +690 -0
- data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
- data/lib/canis/version.rb +3 -0
- 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
|