rbhex-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/CHANGELOG +2000 -0
- data/LICENSE +56 -0
- data/README.md +44 -0
- data/examples/abasiclist.rb +179 -0
- data/examples/alpmenu.rb +50 -0
- data/examples/app.sample +19 -0
- data/examples/atree.rb +100 -0
- data/examples/bline.rb +136 -0
- data/examples/common/file.rb +45 -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/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +10 -0
- data/examples/data/todo.txt.bak +10 -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 +502 -0
- data/examples/dirtree.rb +94 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +146 -0
- data/examples/tasks.rb +178 -0
- data/examples/term2.rb +84 -0
- data/examples/testbuttons.rb +296 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testfields.rb +195 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +170 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +128 -0
- data/lib/rbhex.rb +6 -0
- data/lib/rbhex/core/docs/index.txt +73 -0
- data/lib/rbhex/core/include/action.rb +80 -0
- data/lib/rbhex/core/include/actionmanager.rb +49 -0
- data/lib/rbhex/core/include/appmethods.rb +214 -0
- data/lib/rbhex/core/include/bordertitle.rb +48 -0
- data/lib/rbhex/core/include/chunk.rb +203 -0
- data/lib/rbhex/core/include/io.rb +553 -0
- data/lib/rbhex/core/include/listbindings.rb +74 -0
- data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
- data/lib/rbhex/core/include/listeditable.rb +317 -0
- data/lib/rbhex/core/include/listscrollable.rb +663 -0
- data/lib/rbhex/core/include/listselectable.rb +271 -0
- data/lib/rbhex/core/include/multibuffer.rb +83 -0
- data/lib/rbhex/core/include/orderedhash.rb +77 -0
- data/lib/rbhex/core/include/ractionevent.rb +73 -0
- data/lib/rbhex/core/include/rchangeevent.rb +27 -0
- data/lib/rbhex/core/include/rhistory.rb +95 -0
- data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
- data/lib/rbhex/core/include/vieditable.rb +172 -0
- data/lib/rbhex/core/include/widgetmenu.rb +66 -0
- data/lib/rbhex/core/system/colormap.rb +165 -0
- data/lib/rbhex/core/system/keyboard.rb +150 -0
- data/lib/rbhex/core/system/keydefs.rb +30 -0
- data/lib/rbhex/core/system/ncurses.rb +236 -0
- data/lib/rbhex/core/system/panel.rb +162 -0
- data/lib/rbhex/core/system/window.rb +913 -0
- data/lib/rbhex/core/util/ansiparser.rb +119 -0
- data/lib/rbhex/core/util/app.rb +1228 -0
- data/lib/rbhex/core/util/basestack.rb +410 -0
- data/lib/rbhex/core/util/bottomline.rb +1859 -0
- data/lib/rbhex/core/util/colorparser.rb +77 -0
- data/lib/rbhex/core/util/focusmanager.rb +31 -0
- data/lib/rbhex/core/util/padreader.rb +192 -0
- data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
- data/lib/rbhex/core/util/rdialogs.rb +574 -0
- data/lib/rbhex/core/util/viewer.rb +149 -0
- data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
- data/lib/rbhex/core/version.rb +5 -0
- data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
- data/lib/rbhex/core/widgets/box.rb +58 -0
- data/lib/rbhex/core/widgets/divider.rb +310 -0
- data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
- data/lib/rbhex/core/widgets/rcombo.rb +253 -0
- data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
- data/lib/rbhex/core/widgets/rlink.rb +30 -0
- data/lib/rbhex/core/widgets/rlist.rb +696 -0
- data/lib/rbhex/core/widgets/rmenu.rb +958 -0
- data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
- data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
- data/lib/rbhex/core/widgets/rprogress.rb +118 -0
- data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
- data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
- data/lib/rbhex/core/widgets/rtextview.rb +739 -0
- data/lib/rbhex/core/widgets/rtree.rb +768 -0
- data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
- data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
- data/lib/rbhex/core/widgets/statusline.rb +113 -0
- data/lib/rbhex/core/widgets/tabular.rb +264 -0
- data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
- data/lib/rbhex/core/widgets/textpad.rb +995 -0
- data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
- data/rbhex-core.gemspec +32 -0
- metadata +172 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
require 'rbhex/core/widgets/rwidget'
|
|
2
|
+
#include Ncurses # FFI 2011-09-8
|
|
3
|
+
include RubyCurses
|
|
4
|
+
module RubyCurses
|
|
5
|
+
#
|
|
6
|
+
# This paints labels for various keys at the bottom of the screen, in 2 rows.
|
|
7
|
+
# This is based on alpines last 2 rows. Modes are supported so that the
|
|
8
|
+
# labels change as you enter a widget.
|
|
9
|
+
# For an example, see dbdemo.rb or rfe.rb
|
|
10
|
+
# NOTE: applications using 'App' use a shortcut "dock" to create this.
|
|
11
|
+
#
|
|
12
|
+
# The most minimal keylabel to print one label in first row, and none in second is:
|
|
13
|
+
# [["F1", "Help"], nil]
|
|
14
|
+
# To print 2 labels, one over the other:
|
|
15
|
+
# [["F1", "Help"], ["F10", "Quit"]]
|
|
16
|
+
#
|
|
17
|
+
class KeyLabelPrinter < Widget
|
|
18
|
+
attr_reader :key_labels
|
|
19
|
+
# the current mode (labels are based on mode, changing the mode, changes the labels
|
|
20
|
+
# displayed)
|
|
21
|
+
dsl_property :mode
|
|
22
|
+
# set the color of the labels, overriding the defaults
|
|
23
|
+
dsl_accessor :footer_color_pair
|
|
24
|
+
# set the color of the mnemonic, overriding the defaults
|
|
25
|
+
dsl_accessor :footer_mnemonic_color_pair
|
|
26
|
+
#attr_accessor :row_relative # lets only advertise this when we've tested it out
|
|
27
|
+
|
|
28
|
+
def initialize form, key_labels, config={}, &block
|
|
29
|
+
|
|
30
|
+
@name = "dock"
|
|
31
|
+
case key_labels
|
|
32
|
+
when Hash
|
|
33
|
+
raise "KeyLabelPrinter: KeyLabels cannot be a hash, Array of key labels required. Perhaps you did not pass labels"
|
|
34
|
+
when Array
|
|
35
|
+
else
|
|
36
|
+
raise "KeyLabelPrinter: Array of key labels required. Perhaps you did not pass labels"
|
|
37
|
+
end
|
|
38
|
+
super form, config, &block
|
|
39
|
+
@mode ||= :normal
|
|
40
|
+
#@key_labels = key_labels
|
|
41
|
+
@key_hash = {}
|
|
42
|
+
@key_hash[@mode] = key_labels
|
|
43
|
+
@editable = false
|
|
44
|
+
@focusable = false
|
|
45
|
+
unless @row
|
|
46
|
+
@row_relative = -2
|
|
47
|
+
@row = Ncurses.LINES + @row_relative
|
|
48
|
+
end
|
|
49
|
+
@col ||= 0
|
|
50
|
+
# if negativ row passed we store as relative to bottom, so we can maintain that.
|
|
51
|
+
if @row < 0
|
|
52
|
+
@row_relative = @row
|
|
53
|
+
@row = Ncurses.LINES - @row
|
|
54
|
+
else
|
|
55
|
+
@row_relative = (Ncurses.LINES - @row) * -1
|
|
56
|
+
end
|
|
57
|
+
@cols ||= Ncurses.COLS-1
|
|
58
|
+
@repaint_required = true
|
|
59
|
+
@footer_color_pair ||= $bottomcolor
|
|
60
|
+
@footer_mnemonic_color_pair ||= $reversecolor #2
|
|
61
|
+
end
|
|
62
|
+
def key_labels mode=@mode
|
|
63
|
+
@key_hash[mode]
|
|
64
|
+
end
|
|
65
|
+
# returns the keys as printed. these may or may not help
|
|
66
|
+
# in validation depedign on what you passed as zeroth index
|
|
67
|
+
def get_current_keys
|
|
68
|
+
a = []
|
|
69
|
+
@key_hash[@mode].each do |arr|
|
|
70
|
+
a << arr[0] unless arr.nil?
|
|
71
|
+
end
|
|
72
|
+
return a
|
|
73
|
+
end
|
|
74
|
+
def getvalue
|
|
75
|
+
@key_hash
|
|
76
|
+
end
|
|
77
|
+
def set_key_labels _key_labels, mode=:normal
|
|
78
|
+
@key_hash[mode] = _key_labels
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# XXX need to move wrapping etc up and done once.
|
|
83
|
+
def repaint
|
|
84
|
+
return unless @repaint_required
|
|
85
|
+
r,c = rowcol
|
|
86
|
+
# this should only happen if there's a change in window
|
|
87
|
+
if @row_relative
|
|
88
|
+
@row = Ncurses.LINES+@row_relative
|
|
89
|
+
end
|
|
90
|
+
arr = key_labels()
|
|
91
|
+
print_key_labels(arr, mode=@mode)
|
|
92
|
+
@repaint_required = false
|
|
93
|
+
end
|
|
94
|
+
# ?? does not use mode, i think key_labels is unused. a hash is now used 2011-10-11 XXX FIXME
|
|
95
|
+
# WARNING, i have not tested this after changing it.
|
|
96
|
+
def append_key_label key, label, mode=@mode
|
|
97
|
+
#@key_labels << [key, label] if !@key_labels.include? [key, label]
|
|
98
|
+
@key_hash[mode] << [key, label] if !@key_hash[mode].include? [key, label]
|
|
99
|
+
@repaint_required = true
|
|
100
|
+
end
|
|
101
|
+
def print_key_labels(arr = key_labels(), mode=@mode)
|
|
102
|
+
#return if !@show_key_labels # XXX
|
|
103
|
+
@win ||= @form.window
|
|
104
|
+
#$log.debug "XXX: PKL #{arr.length}, #{arr}"
|
|
105
|
+
@padding = @cols / (arr.length/2)
|
|
106
|
+
posx = 0
|
|
107
|
+
even = []
|
|
108
|
+
odd = []
|
|
109
|
+
arr.each_index { |i|
|
|
110
|
+
if i % 2 == 0
|
|
111
|
+
#arr[i+1] = ['',''] if arr[i+1].nil?
|
|
112
|
+
nextarr = arr[i+1] || ['', '']
|
|
113
|
+
keyw = [arr[i][0].length, nextarr[0].length].max
|
|
114
|
+
labelw = [arr[i][1].length, nextarr[1].length].max
|
|
115
|
+
|
|
116
|
+
even << [ sprintf("%*s", keyw, arr[i][0]), sprintf("%-*s", labelw, arr[i][1]) ]
|
|
117
|
+
odd << [ sprintf("%*s", keyw, nextarr[0]), sprintf("%-*s", labelw, nextarr[1]) ]
|
|
118
|
+
#$log.debug("loop even: #{even.inspect}")
|
|
119
|
+
else
|
|
120
|
+
end
|
|
121
|
+
}
|
|
122
|
+
#$log.debug("even: #{even.inspect}")
|
|
123
|
+
#$log.debug("odd : #{odd.inspect}")
|
|
124
|
+
#posy = @barrow-1
|
|
125
|
+
posy = @row
|
|
126
|
+
print_key_labels_row(posy, posx, even)
|
|
127
|
+
posy = @row+1
|
|
128
|
+
print_key_labels_row(posy, posx, odd)
|
|
129
|
+
# uncommented next line after ffi-ncurses else not showing till key press FFI 2011-09-17
|
|
130
|
+
@win.wrefresh # needed else secod row not shown after askchoice XXX
|
|
131
|
+
end
|
|
132
|
+
def print_key_labels_row(posy, posx, arr)
|
|
133
|
+
# FIXME: this logic of padding needs to take into account
|
|
134
|
+
# width of window
|
|
135
|
+
padding = 8
|
|
136
|
+
padding = 4 if arr.length > 5
|
|
137
|
+
padding = 2 if arr.length > 7
|
|
138
|
+
padding = 0 if arr.length > 9
|
|
139
|
+
#padding = @padding # XXX 2008-11-13 23:01
|
|
140
|
+
my_form_win = @win
|
|
141
|
+
@win.printstring(posy,0, "%-*s" % [@cols," "], @footer_color_pair, @attr)
|
|
142
|
+
arr.each do |kl|
|
|
143
|
+
key = kl[0]
|
|
144
|
+
lab = kl[1]
|
|
145
|
+
if key !="" # don't print that white blank space for fillers
|
|
146
|
+
color_pair= @footer_mnemonic_color_pair # $reversecolor #2
|
|
147
|
+
x = posx + (key.length - key.strip.length)
|
|
148
|
+
my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
|
|
149
|
+
my_form_win.mvprintw(posy, x, "%s" % kl[0].strip );
|
|
150
|
+
my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
|
|
151
|
+
end
|
|
152
|
+
color_pair=@footer_color_pair
|
|
153
|
+
posx = posx + kl[0].length
|
|
154
|
+
my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
|
|
155
|
+
|
|
156
|
+
#lab = sprintf(" %s %*s" , kl[1], padding, " ");
|
|
157
|
+
lab = sprintf(" %s %s" , kl[1], " "*padding);
|
|
158
|
+
my_form_win.mvprintw(posy, posx, lab)
|
|
159
|
+
my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
|
|
160
|
+
posx = posx + lab.length
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
##
|
|
164
|
+
# updates existing label with a new one.
|
|
165
|
+
# @return true if updated, else false
|
|
166
|
+
# @example update "C-x", "C-x", "Disable"
|
|
167
|
+
def update_application_key_label(display_code, new_display_code, text)
|
|
168
|
+
@repaint_required = true
|
|
169
|
+
labels = key_labels()
|
|
170
|
+
raise "labels are nil !!!" unless labels
|
|
171
|
+
labels.each_index do |ix|
|
|
172
|
+
lab = labels[ix]
|
|
173
|
+
next if lab.nil?
|
|
174
|
+
if lab[0] == display_code
|
|
175
|
+
labels[ix] = [new_display_code , text]
|
|
176
|
+
$log.debug("updated #{labels[ix]}")
|
|
177
|
+
return true
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
return false
|
|
181
|
+
end
|
|
182
|
+
alias :update :update_application_key_label
|
|
183
|
+
##
|
|
184
|
+
# inserts an application label at given index
|
|
185
|
+
# to add the key, use create_datakeys to add bindings
|
|
186
|
+
# remember to call restore_application_key_labels after updating/inserting
|
|
187
|
+
def insert_application_key_label(index, display_code, text)
|
|
188
|
+
@repaint_required = true
|
|
189
|
+
labels = key_labels()
|
|
190
|
+
labels.insert(index, [display_code , text] )
|
|
191
|
+
end
|
|
192
|
+
# ADD HERE KEYLABEL
|
|
193
|
+
end
|
|
194
|
+
end
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
|
2
|
+
# File: rcombo.rb
|
|
3
|
+
# Description: Non-editable combo box.
|
|
4
|
+
# Make it dead-simple to use.
|
|
5
|
+
# This is a simpler version of the original ComboBox which allowed
|
|
6
|
+
# editing and used rlistbox. This simpler class is meant for the rbhex
|
|
7
|
+
# core package and will only depend on a core class if at all.
|
|
8
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
|
9
|
+
# Date: 2011-11-11 - 21:42
|
|
10
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
11
|
+
# Last update: 2014-03-24 16:42
|
|
12
|
+
# ----------------------------------------------------------------------------- #
|
|
13
|
+
#
|
|
14
|
+
require 'rbhex'
|
|
15
|
+
|
|
16
|
+
include RubyCurses
|
|
17
|
+
module RubyCurses
|
|
18
|
+
extend self
|
|
19
|
+
|
|
20
|
+
# the quick approach would be to use field, and just add a popup.
|
|
21
|
+
# Or since we are not editing, we could use a Label and a popup
|
|
22
|
+
# Or just display a label and a popup without using anything else.
|
|
23
|
+
# Thre is an undocumented variable +display_length+ which is the size of the label
|
|
24
|
+
# This is used to position the combo symbol and the popup. This can be calculated
|
|
25
|
+
# based on the label. 2014-03-24 - 16:42
|
|
26
|
+
|
|
27
|
+
class ComboBox < Field
|
|
28
|
+
include RubyCurses::EventHandler
|
|
29
|
+
dsl_accessor :list_config
|
|
30
|
+
|
|
31
|
+
attr_accessor :current_index
|
|
32
|
+
# the symbol you want to use for combos
|
|
33
|
+
attr_accessor :COMBO_SYMBOL
|
|
34
|
+
attr_accessor :show_symbol # show that funny symbol after a combo to signify its a combo
|
|
35
|
+
dsl_accessor :arrow_key_policy # :IGNORE :NEXT_ROW :POPUP
|
|
36
|
+
|
|
37
|
+
def initialize form, config={}, &block
|
|
38
|
+
@arrow_key_policy = :ignore
|
|
39
|
+
@editable = false
|
|
40
|
+
#@COMBO_SYMBOL = "v".ord # trying this out
|
|
41
|
+
# thanks hramrach for fix
|
|
42
|
+
if RUBY_VERSION < "1.9" then
|
|
43
|
+
@COMBO_SYMBOL = "v"[0] # trying this out
|
|
44
|
+
else
|
|
45
|
+
@COMBO_SYMBOL = "v".ord # trying this out
|
|
46
|
+
end
|
|
47
|
+
@current_index = 0
|
|
48
|
+
super
|
|
49
|
+
## this was getting overridden this making the combo editable 2014-03-24 - 16:24
|
|
50
|
+
@editable = false
|
|
51
|
+
# added if check since it was overriding set_buffer in creation. 2009-01-18 00:03
|
|
52
|
+
set_buffer @list[@current_index].dup if @buffer.nil? or @buffer.empty?
|
|
53
|
+
init_vars
|
|
54
|
+
@_events.push(*[:CHANGE, :ENTER_ROW, :LEAVE_ROW])
|
|
55
|
+
end
|
|
56
|
+
def init_vars
|
|
57
|
+
super
|
|
58
|
+
@show_symbol = true if @show_symbol.nil? # if set to false don't touch
|
|
59
|
+
#@show_symbol = false if @label # 2011-11-13
|
|
60
|
+
@COMBO_SYMBOL ||= FFI::NCurses::ACS_DARROW #GEQUAL
|
|
61
|
+
|
|
62
|
+
# next 2 lines giving an error in newtabbedwindow.rb example since the methods
|
|
63
|
+
# have been deprecated.
|
|
64
|
+
#bind_key(KEY_UP) { previous_row }
|
|
65
|
+
#bind_key(KEY_DOWN) { next_row }
|
|
66
|
+
end
|
|
67
|
+
def selected_item
|
|
68
|
+
@list[@current_index]
|
|
69
|
+
end
|
|
70
|
+
def selected_index
|
|
71
|
+
@current_index
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
# convert given list to datamodel
|
|
76
|
+
def list alist=nil
|
|
77
|
+
return @list if alist.nil?
|
|
78
|
+
#@list = RubyCurses::ListDataModel.new(alist)
|
|
79
|
+
@list = alist
|
|
80
|
+
end
|
|
81
|
+
##
|
|
82
|
+
# combo edit box key handling
|
|
83
|
+
# removed UP and DOWN and bound it, so it can be unbound
|
|
84
|
+
def handle_key(ch)
|
|
85
|
+
@current_index ||= 0
|
|
86
|
+
# added 2009-01-18 22:44 no point moving horiz or passing up to Field if not edit
|
|
87
|
+
if !@editable
|
|
88
|
+
if ch == KEY_LEFT or ch == KEY_RIGHT
|
|
89
|
+
return :UNHANDLED
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
case @arrow_key_policy
|
|
93
|
+
when :ignore
|
|
94
|
+
if ch == KEY_DOWN or ch == KEY_UP
|
|
95
|
+
return :UNHANDLED
|
|
96
|
+
end
|
|
97
|
+
when :popup
|
|
98
|
+
if ch == KEY_DOWN or ch == KEY_UP
|
|
99
|
+
popup
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
case ch
|
|
103
|
+
#when KEY_UP # show previous value
|
|
104
|
+
# previous_row
|
|
105
|
+
#when KEY_DOWN # show previous value
|
|
106
|
+
# next_row
|
|
107
|
+
# adding spacebar to popup combo, as in microemacs 2010-10-01 13:21
|
|
108
|
+
when 32, KEY_DOWN+ META_KEY # alt down
|
|
109
|
+
popup # pop up the popup
|
|
110
|
+
else
|
|
111
|
+
super
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
def DEPprevious_row
|
|
115
|
+
@current_index -= 1 if @current_index > 0
|
|
116
|
+
set_buffer @list[@current_index].dup
|
|
117
|
+
set_modified(true) ## ??? not required
|
|
118
|
+
fire_handler :ENTER_ROW, self
|
|
119
|
+
@list.on_enter_row self
|
|
120
|
+
end
|
|
121
|
+
def DEPnext_row
|
|
122
|
+
@current_index += 1 if @current_index < @list.length()-1
|
|
123
|
+
set_buffer @list[@current_index].dup
|
|
124
|
+
set_modified(true) ## ??? not required
|
|
125
|
+
fire_handler :ENTER_ROW, self
|
|
126
|
+
@list.on_enter_row self
|
|
127
|
+
end
|
|
128
|
+
##
|
|
129
|
+
# calls a popup list
|
|
130
|
+
# TODO: should not be positioned so that it goes off edge
|
|
131
|
+
# user's customizations of list should be passed in
|
|
132
|
+
# The dup of listconfig is due to a tricky feature/bug.
|
|
133
|
+
# I try to keep the config hash and instance variables in synch. So
|
|
134
|
+
# this config hash is sent to popuplist which updates its row col and
|
|
135
|
+
# next time we pop up the popup row and col are zero.
|
|
136
|
+
#
|
|
137
|
+
#
|
|
138
|
+
# added dup in PRESS since editing edit field mods this
|
|
139
|
+
# on pressing ENTER, value set back and current_index updated
|
|
140
|
+
def popup
|
|
141
|
+
@list_config ||= {}
|
|
142
|
+
@list_config[:row] ||= @row
|
|
143
|
+
#@list_config[:col] ||= @col
|
|
144
|
+
@list_config[:col] ||= @col + @display_length
|
|
145
|
+
@list_config[:relative_to] ||= self
|
|
146
|
+
# this does not allow us to bind to events in the list
|
|
147
|
+
index = popuplist @list, @list_config
|
|
148
|
+
if index
|
|
149
|
+
set_buffer @list[index].dup
|
|
150
|
+
set_modified(true) if @current_index != index
|
|
151
|
+
@current_index = index
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
def OLDpopup
|
|
155
|
+
listconfig = (@list_config && @list_config.dup) || {}
|
|
156
|
+
dm = @list
|
|
157
|
+
# current item in edit box will be focussed when list pops up
|
|
158
|
+
#$log.debug "XXX POPUP: #{dm.selected_index} = #{@current_index}, value #{@buffer}"
|
|
159
|
+
# we are having some problms when using this in a list. it retains earlier value
|
|
160
|
+
_index = dm.index @buffer
|
|
161
|
+
dm.selected_index = _index # @current_index
|
|
162
|
+
poprow = @row+0 # one row below the edit box
|
|
163
|
+
popcol = @col
|
|
164
|
+
dlength = @display_length
|
|
165
|
+
f = self
|
|
166
|
+
@popup = RubyCurses::PopupList.new do
|
|
167
|
+
row poprow
|
|
168
|
+
col popcol
|
|
169
|
+
width dlength
|
|
170
|
+
list_data_model dm
|
|
171
|
+
list_selection_mode 'single'
|
|
172
|
+
relative_to f
|
|
173
|
+
list_config listconfig
|
|
174
|
+
bind(:PRESS) do |index|
|
|
175
|
+
f.set_buffer dm[index].dup
|
|
176
|
+
f.set_modified(true) if f.current_index != index
|
|
177
|
+
f.current_index = index
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Field putc advances cursor when it gives a char so we override this
|
|
183
|
+
def putc c
|
|
184
|
+
if c >= 0 and c <= 127
|
|
185
|
+
ret = putch c.chr
|
|
186
|
+
if ret == 0
|
|
187
|
+
addcol 1 if @editable
|
|
188
|
+
set_modified
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
return -1 # always ??? XXX
|
|
192
|
+
end
|
|
193
|
+
##
|
|
194
|
+
# field does not give char to non-editable fields so we override
|
|
195
|
+
def putch char
|
|
196
|
+
@current_index ||= 0
|
|
197
|
+
if @editable
|
|
198
|
+
raise "how is it editable here in combo"
|
|
199
|
+
super
|
|
200
|
+
return 0
|
|
201
|
+
else
|
|
202
|
+
match = next_match(char)
|
|
203
|
+
set_buffer match unless match.nil?
|
|
204
|
+
fire_handler :ENTER_ROW, self
|
|
205
|
+
end
|
|
206
|
+
@modified = true
|
|
207
|
+
fire_handler :CHANGE, self # 2008-12-09 14:51 ???
|
|
208
|
+
0
|
|
209
|
+
end
|
|
210
|
+
##
|
|
211
|
+
# the sets the next match in the edit field
|
|
212
|
+
def next_match char
|
|
213
|
+
start = @current_index
|
|
214
|
+
start.upto(@list.length-1) do |ix|
|
|
215
|
+
if @list[ix][0,1].casecmp(char) == 0
|
|
216
|
+
return @list[ix] unless @list[ix] == @buffer
|
|
217
|
+
end
|
|
218
|
+
@current_index += 1
|
|
219
|
+
end
|
|
220
|
+
## could not find, start from zero
|
|
221
|
+
@current_index = 0
|
|
222
|
+
start = [@list.length()-1, start].min
|
|
223
|
+
0.upto(start) do |ix|
|
|
224
|
+
if @list[ix][0,1].casecmp(char) == 0
|
|
225
|
+
return @list[ix] unless @list[ix] == @buffer
|
|
226
|
+
end
|
|
227
|
+
@current_index += 1
|
|
228
|
+
end
|
|
229
|
+
@current_index = [@list.length()-1, @current_index].min
|
|
230
|
+
return nil
|
|
231
|
+
end
|
|
232
|
+
##
|
|
233
|
+
# on leaving the listbox, update the combo/datamodel.
|
|
234
|
+
# we are using methods of the datamodel. Updating our list will have
|
|
235
|
+
# no effect on the list, and wont trigger events.
|
|
236
|
+
# Do not override.
|
|
237
|
+
def on_leave
|
|
238
|
+
fire_handler :LEAVE, self
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def repaint
|
|
242
|
+
super
|
|
243
|
+
c = @col + @display_length
|
|
244
|
+
if @show_symbol # 2009-01-11 18:47
|
|
245
|
+
# i have changed c +1 to c, since we have no right to print beyond display_length
|
|
246
|
+
@form.window.mvwaddch @row, c, @COMBO_SYMBOL # Ncurses::ACS_GEQUAL
|
|
247
|
+
@form.window.mvchgat(y=@row, x=c, max=1, Ncurses::A_REVERSE|Ncurses::A_UNDERLINE, $datacolor, nil)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
end # class ComboBox
|
|
252
|
+
|
|
253
|
+
end # module
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
* Name: A container that manages components placed in it but
|
|
3
|
+
is not a form. Thus it can be safely placed as a widget
|
|
4
|
+
without all the complicatinos of a form embedded inside another.
|
|
5
|
+
NOTE: Still experimental
|
|
6
|
+
* Description
|
|
7
|
+
* Author: rkumar (http://github.com/rkumar/rbcurse/)
|
|
8
|
+
* Date: 21.10.11 - 00:29
|
|
9
|
+
* License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
10
|
+
|
|
11
|
+
* Last update: 23.10.11 - 00:29
|
|
12
|
+
== CHANGES
|
|
13
|
+
Focusables so we don't focus on label
|
|
14
|
+
== TODO
|
|
15
|
+
How to put blank lines in stack - use a blank label
|
|
16
|
+
|
|
17
|
+
- The contaomers and multis need to do their own on_enter and on_leave
|
|
18
|
+
management, they cannot rely on some other container doing it.
|
|
19
|
+
We can only rely on handle_key being called. HK should determine
|
|
20
|
+
whether any set_form row etc needs to be done.
|
|
21
|
+
- Should have its own stack and flow
|
|
22
|
+
=end
|
|
23
|
+
|
|
24
|
+
require 'rbhex'
|
|
25
|
+
|
|
26
|
+
include RubyCurses
|
|
27
|
+
module RubyCurses
|
|
28
|
+
extend self
|
|
29
|
+
|
|
30
|
+
# This is an attempt at having a container which can contain multiple
|
|
31
|
+
# widgets without being a form itself. Having forms within forms
|
|
32
|
+
# complicates code too much, esp cursor positioning. e.g. tabbedpane
|
|
33
|
+
|
|
34
|
+
class Container < Widget
|
|
35
|
+
|
|
36
|
+
dsl_accessor :suppress_borders #to_print_borders
|
|
37
|
+
dsl_accessor :border_attrib, :border_color
|
|
38
|
+
dsl_accessor :title #set this on top
|
|
39
|
+
dsl_accessor :title_attrib #bold, reverse, normal
|
|
40
|
+
# should container stack objects ignoring users row col
|
|
41
|
+
# this is esp needed since App sets row and col which is too early
|
|
42
|
+
# This is now the default value, till i can redo things
|
|
43
|
+
#dsl_accessor :stack
|
|
44
|
+
dsl_accessor :positioning # absolute, relative, stack
|
|
45
|
+
attr_reader :current_component
|
|
46
|
+
|
|
47
|
+
def initialize form=nil, config={}, &block
|
|
48
|
+
@suppress_borders = false
|
|
49
|
+
@row_offset = @col_offset = 1
|
|
50
|
+
@_events ||= []
|
|
51
|
+
@stack = true
|
|
52
|
+
@positioning = :stack
|
|
53
|
+
super
|
|
54
|
+
@focusable = true
|
|
55
|
+
@editable = false
|
|
56
|
+
@components = [] # all components
|
|
57
|
+
@focusables = [] # focusable components, makes checks easier
|
|
58
|
+
|
|
59
|
+
init_vars
|
|
60
|
+
end
|
|
61
|
+
def init_vars
|
|
62
|
+
@repaint_required = true
|
|
63
|
+
@row_offset = @col_offset = 0 if @suppress_borders # FIXME supposed to use this !!
|
|
64
|
+
|
|
65
|
+
@internal_width = 2
|
|
66
|
+
@internal_width = 1 if @suppress_borders
|
|
67
|
+
@name ||= "AContainer"
|
|
68
|
+
@first_time = true
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# NOTE: since we are handling the traversal, we delink the object from any
|
|
73
|
+
# form's widgets array that might have been added. Whenever a form is available,
|
|
74
|
+
# we set it (without adding widget to it) so it can print using the form's window.
|
|
75
|
+
#
|
|
76
|
+
# @param [Widget] to add
|
|
77
|
+
def add *items
|
|
78
|
+
items.each do |c|
|
|
79
|
+
raise ArgumentError, "Nil component passed to add" unless c
|
|
80
|
+
if c.is_a? Widget
|
|
81
|
+
if c.form && c.form != @form
|
|
82
|
+
$log.debug " removing widget VIMSPLIT #{c.class} wr: #{c.row} row:#{@row} ht:#{@height} "
|
|
83
|
+
c.form.remove_widget c
|
|
84
|
+
c.form = nil
|
|
85
|
+
# or should i just stack them myself and screw what you've asked for
|
|
86
|
+
end
|
|
87
|
+
# take it out of form's control. We will control it.
|
|
88
|
+
if c.form
|
|
89
|
+
c.form.remove_widget c
|
|
90
|
+
end
|
|
91
|
+
# shoot, what if at this point the container does not have a form
|
|
92
|
+
attach_form c if @form
|
|
93
|
+
end
|
|
94
|
+
# most likely if you have created both container and widgets
|
|
95
|
+
# inside app, it would have given row after container
|
|
96
|
+
|
|
97
|
+
@components << c
|
|
98
|
+
if c.focusable
|
|
99
|
+
@focusables << c
|
|
100
|
+
@current_component ||= c # only the first else cursor falls on last on enter
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end # items each
|
|
104
|
+
self
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# When we get a form, we silently attach it to this object, without the form
|
|
108
|
+
# knowing. We don't want form managing this object.
|
|
109
|
+
def attach_form c
|
|
110
|
+
c.form = @form
|
|
111
|
+
c.override_graphic @graphic
|
|
112
|
+
c.parent_component = self
|
|
113
|
+
end
|
|
114
|
+
alias :add_widget :add
|
|
115
|
+
def widgets; @components; end
|
|
116
|
+
# what of by_name
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# correct coordinates of comp esp if App has stacked them after this
|
|
120
|
+
# container
|
|
121
|
+
# It is best to use the simple stack feature. The rest could change at any time
|
|
122
|
+
# and is quite arbitrary. Some folks may set absolute locations if container
|
|
123
|
+
# is directly on a form, others may set relative locations if it is inside a
|
|
124
|
+
# tabbed pane or other container. Thus, stacks are best
|
|
125
|
+
def correct_component c
|
|
126
|
+
raise "Form is still not set in Container" unless @form
|
|
127
|
+
attach_form(c) unless c.form
|
|
128
|
+
@last_row ||= @row + 1
|
|
129
|
+
inset = 2
|
|
130
|
+
# 2011-10-20 current default behaviour is to stack
|
|
131
|
+
if @positioning == :stack
|
|
132
|
+
c.row = @last_row
|
|
133
|
+
c.col = @col + inset
|
|
134
|
+
|
|
135
|
+
# do not advance row, save col for next row
|
|
136
|
+
@last_row += 1
|
|
137
|
+
elsif @positioning == :relative # UNTESTED NOTE
|
|
138
|
+
if (c.row || 0) <= 0
|
|
139
|
+
$log.warn "c.row in CONTAINER is #{c.row} "
|
|
140
|
+
c.row = @last_row
|
|
141
|
+
@last_row += 1
|
|
142
|
+
elsif c.row > @row + @height -1
|
|
143
|
+
$log.warn "c.row in CONTAINER exceeds container. #{c.row} "
|
|
144
|
+
c.row -= @height - @row_offset
|
|
145
|
+
else
|
|
146
|
+
# this is where it should come
|
|
147
|
+
c.row += @row + @row_offset
|
|
148
|
+
@last_row = c.row + 1
|
|
149
|
+
end
|
|
150
|
+
if (c.col || 0) <= 0
|
|
151
|
+
c.col = @col + inset + @col_offset
|
|
152
|
+
elsif c.col > @col + @width -1
|
|
153
|
+
c.col -= @width
|
|
154
|
+
elsif c.col == @col
|
|
155
|
+
c.col += @col_offset + inset
|
|
156
|
+
else #f c.col < @col
|
|
157
|
+
c.col += @col+@col_offset
|
|
158
|
+
end
|
|
159
|
+
$log.debug "XXX: CORRECT #{c.name} r:#{c.row} c:#{c.col} "
|
|
160
|
+
end
|
|
161
|
+
@first_time = false
|
|
162
|
+
end
|
|
163
|
+
def check_component c
|
|
164
|
+
raise "row is less than container #{c.row} #{@row} " if c.row <= @row
|
|
165
|
+
raise "col is less than container #{c.col} #{@col} " if c.col <= @col
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
public
|
|
169
|
+
# repaint object
|
|
170
|
+
# called by Form, and sometimes parent component (if not form).
|
|
171
|
+
def repaint
|
|
172
|
+
my_win = @form ? @form.window : @target_window
|
|
173
|
+
@graphic = my_win unless @graphic
|
|
174
|
+
raise " #{@name} NO GRAPHIC set as yet CONTAINER paint " unless @graphic
|
|
175
|
+
@components.each { |e| correct_component e } if @first_time
|
|
176
|
+
#@components.each { |e| check_component e } # seeme one if printing out
|
|
177
|
+
|
|
178
|
+
#return unless @repaint_required
|
|
179
|
+
|
|
180
|
+
# if some major change has happened then repaint everything
|
|
181
|
+
if @repaint_required
|
|
182
|
+
$log.debug " VIM repaint graphic #{@graphic} "
|
|
183
|
+
print_borders unless @suppress_borders # do this once only, unless everything changes
|
|
184
|
+
@components.each { |e| e.repaint_all(true); e.repaint }
|
|
185
|
+
else
|
|
186
|
+
@components.each { |e| e.repaint }
|
|
187
|
+
end # if repaint_required
|
|
188
|
+
|
|
189
|
+
@repaint_required = false
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private
|
|
193
|
+
def print_borders
|
|
194
|
+
width = @width
|
|
195
|
+
height = @height-1 # 2010-01-04 15:30 BUFFERED HEIGHT
|
|
196
|
+
window = @graphic # 2010-01-04 12:37 BUFFERED
|
|
197
|
+
startcol = @col
|
|
198
|
+
startrow = @row
|
|
199
|
+
@color_pair = get_color($datacolor)
|
|
200
|
+
#$log.debug "rlistb #{name}: window.print_border #{startrow}, #{startcol} , h:#{height}, w:#{width} , @color_pair, @attr "
|
|
201
|
+
window.print_border startrow, startcol, height, width, @color_pair, @attr
|
|
202
|
+
print_title
|
|
203
|
+
end
|
|
204
|
+
def print_title
|
|
205
|
+
$log.debug "CONTAINER PRINTING TITLE at #{row} #{col} "
|
|
206
|
+
@graphic.printstring( @row, @col+(@width-@title.length)/2, @title, @color_pair, @title_attrib) unless @title.nil?
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
public
|
|
210
|
+
# called by parent or form, otherwise its private
|
|
211
|
+
def handle_key ch
|
|
212
|
+
$log.debug " CONTAINER handle_key #{ch} "
|
|
213
|
+
return if @components.empty?
|
|
214
|
+
_multiplier = ($multiplier == 0 ? 1 : $multiplier )
|
|
215
|
+
|
|
216
|
+
# should this go here 2011-10-19
|
|
217
|
+
unless @_entered
|
|
218
|
+
$log.warn "XXX WARN: calling ON_ENTER since in this situation it was not called"
|
|
219
|
+
on_enter
|
|
220
|
+
end
|
|
221
|
+
if ch == KEY_TAB
|
|
222
|
+
$log.debug "CONTAINER GOTO NEXT TAB"
|
|
223
|
+
return goto_next_component
|
|
224
|
+
elsif ch == KEY_BTAB
|
|
225
|
+
return goto_prev_component
|
|
226
|
+
end
|
|
227
|
+
comp = @current_component
|
|
228
|
+
$log.debug " CONTAINER handle_key #{ch}: #{comp}"
|
|
229
|
+
if comp
|
|
230
|
+
ret = comp.handle_key(ch)
|
|
231
|
+
$log.debug " CONTAINER handle_key#{ch}: #{comp} returned #{ret} "
|
|
232
|
+
if ret != :UNHANDLED
|
|
233
|
+
comp.repaint # NOTE: if we don;t do this, then it won't get repainted. I will have to repaint ALL
|
|
234
|
+
# in repaint of this.
|
|
235
|
+
return ret
|
|
236
|
+
end
|
|
237
|
+
$log.debug "XXX CONTAINER key unhandled by comp #{comp.name} "
|
|
238
|
+
else
|
|
239
|
+
$log.warn "XXX CONTAINER key unhandled NULL comp"
|
|
240
|
+
end
|
|
241
|
+
case ch
|
|
242
|
+
when ?\C-c.getbyte(0)
|
|
243
|
+
$multiplier = 0
|
|
244
|
+
return 0
|
|
245
|
+
when ?0.getbyte(0)..?9.getbyte(0)
|
|
246
|
+
$log.debug " VIM coming here to set multiplier #{$multiplier} "
|
|
247
|
+
$multiplier *= 10 ; $multiplier += (ch-48)
|
|
248
|
+
return 0
|
|
249
|
+
end
|
|
250
|
+
ret = process_key ch, self
|
|
251
|
+
# allow user to map left and right if he wants
|
|
252
|
+
if ret == :UNHANDLED
|
|
253
|
+
case ch
|
|
254
|
+
when KEY_UP
|
|
255
|
+
# form will pick this up and do needful
|
|
256
|
+
return goto_prev_component #unless on_first_component?
|
|
257
|
+
when KEY_LEFT
|
|
258
|
+
# if i don't check for first component, key will go back to form,
|
|
259
|
+
# but not be processes. so focussed remain here, but be false.
|
|
260
|
+
# In case of returnign an unhandled TAB, on_leave will happen and cursor will move to
|
|
261
|
+
# previous component outside of this.
|
|
262
|
+
return goto_prev_component unless on_first_component?
|
|
263
|
+
when KEY_RIGHT
|
|
264
|
+
return goto_next_component #unless on_last_component?
|
|
265
|
+
when KEY_DOWN
|
|
266
|
+
return goto_next_component #unless on_last_component?
|
|
267
|
+
else
|
|
268
|
+
@_entered = false
|
|
269
|
+
return :UNHANDLED
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
$multiplier = 0
|
|
274
|
+
return 0
|
|
275
|
+
end
|
|
276
|
+
# Actually we should only go to current component if it accepted
|
|
277
|
+
# a key stroke. if user tabbed thru it, then no point going back to
|
|
278
|
+
# it. Go to first or last depending on TAB or BACKTAB otherwise.
|
|
279
|
+
# NOTE: if user comes in using DOWN or UP, last traversed component will get the focus
|
|
280
|
+
#
|
|
281
|
+
def on_enter
|
|
282
|
+
# if BTAB, the last comp XXX they must be focusable FIXME
|
|
283
|
+
if $current_key == KEY_BTAB || $current_key == KEY_UP
|
|
284
|
+
@current_component = @focusables.last
|
|
285
|
+
else
|
|
286
|
+
@current_component = @focusables.first
|
|
287
|
+
end
|
|
288
|
+
return unless @current_component
|
|
289
|
+
$log.debug " CONTAINER came to ON_ENTER #{@current_component} "
|
|
290
|
+
set_form_row
|
|
291
|
+
@_entered = true
|
|
292
|
+
end
|
|
293
|
+
# we cannot be sure that this will be called especially if this is embedded
|
|
294
|
+
# inside some other component
|
|
295
|
+
def on_leave
|
|
296
|
+
@_entered = false
|
|
297
|
+
super
|
|
298
|
+
end
|
|
299
|
+
def goto_next_component
|
|
300
|
+
if @current_component != nil
|
|
301
|
+
leave_current_component
|
|
302
|
+
if on_last_component?
|
|
303
|
+
#@_entered = false
|
|
304
|
+
return :UNHANDLED
|
|
305
|
+
end
|
|
306
|
+
@current_index = @focusables.index(@current_component)
|
|
307
|
+
index = @current_index + 1
|
|
308
|
+
f = @focusables[index]
|
|
309
|
+
if f
|
|
310
|
+
@current_index = index
|
|
311
|
+
@current_component = f
|
|
312
|
+
return set_form_row
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
@_entered = false
|
|
316
|
+
return :UNHANDLED
|
|
317
|
+
end
|
|
318
|
+
def goto_prev_component
|
|
319
|
+
if @current_component != nil
|
|
320
|
+
leave_current_component
|
|
321
|
+
if on_first_component?
|
|
322
|
+
@_entered = false
|
|
323
|
+
return :UNHANDLED
|
|
324
|
+
end
|
|
325
|
+
@current_index = @focusables.index(@current_component)
|
|
326
|
+
index = @current_index -= 1
|
|
327
|
+
f = @focusables[index]
|
|
328
|
+
if f
|
|
329
|
+
@current_index = index
|
|
330
|
+
@current_component = f
|
|
331
|
+
return set_form_row
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
return :UNHANDLED
|
|
335
|
+
end
|
|
336
|
+
# private
|
|
337
|
+
# XXX why are we calling 3 methods in a row, why not OE manages these 3
|
|
338
|
+
# There's double calling going on.
|
|
339
|
+
def set_form_row
|
|
340
|
+
return :UNHANDLED if @current_component.nil?
|
|
341
|
+
cc = @current_component
|
|
342
|
+
$log.debug "CONT #{@name} set_form_row calling sfr for #{cc.name}, r #{cc.row} c: #{cc.col} "
|
|
343
|
+
$log.debug " CONTAINER on enter sfr #{@current_component.name} #{@current_component} "
|
|
344
|
+
|
|
345
|
+
# bug caught here. we were printing a field before it had been set, so it printed out
|
|
346
|
+
@components.each { |e| correct_component e } if @first_time
|
|
347
|
+
@current_component.on_enter
|
|
348
|
+
@current_component.set_form_row # why was this missing in vimsplit. is it
|
|
349
|
+
$log.debug "CONT2 #{@name} set_form_row calling sfr for #{cc.name}, r #{cc.row} c: #{cc.col} "
|
|
350
|
+
# that on_enter does a set_form_row
|
|
351
|
+
@current_component.set_form_col # XXX
|
|
352
|
+
@current_component.repaint # OMG this could happen before we've set row and col
|
|
353
|
+
# XXX compo should do set_form_row and col if it has that
|
|
354
|
+
end
|
|
355
|
+
#
|
|
356
|
+
def set_form_col
|
|
357
|
+
return if @current_component.nil?
|
|
358
|
+
$log.debug " #{@name} CONTAINER EMPTY set_form_col calling sfc for #{@current_component.name} "
|
|
359
|
+
# already called from above.
|
|
360
|
+
#@current_component.set_form_col
|
|
361
|
+
end
|
|
362
|
+
# leave the component we are on.
|
|
363
|
+
# This should be followed by all containers, so that the on_leave action
|
|
364
|
+
# of earlier comp can be displayed, such as dimming components selections
|
|
365
|
+
def leave_current_component
|
|
366
|
+
@current_component.on_leave
|
|
367
|
+
# NOTE this is required, since repaint will just not happen otherwise
|
|
368
|
+
# Some components are erroneously repainting all, after setting this to true so it is
|
|
369
|
+
# working there.
|
|
370
|
+
@current_component.repaint_required true
|
|
371
|
+
$log.debug " after on_leave RCONT XXX #{@current_component.focussed} #{@current_component.name}"
|
|
372
|
+
@current_component.repaint
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# is focus on first component FIXME check for focusable
|
|
376
|
+
def on_first_component?
|
|
377
|
+
@current_component == @focusables.first
|
|
378
|
+
end
|
|
379
|
+
# is focus on last component FIXME check for focusable
|
|
380
|
+
def on_last_component?
|
|
381
|
+
@current_component == @focusables.last
|
|
382
|
+
end
|
|
383
|
+
# set focus on given component
|
|
384
|
+
# Sometimes you have the handle to component, and you want to move focus to it
|
|
385
|
+
def goto_component comp
|
|
386
|
+
return if comp == @current_component
|
|
387
|
+
leave_current_component
|
|
388
|
+
@current_component = comp
|
|
389
|
+
set_form_row
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# ADD HERE ABOVe
|
|
393
|
+
end # class
|
|
394
|
+
end # module
|
|
395
|
+
|
|
396
|
+
if __FILE__ == $PROGRAM_NAME
|
|
397
|
+
require 'rbhex/core/util/app'
|
|
398
|
+
App.new do
|
|
399
|
+
f1 = field "name", :maxlen => 20, :display_length => 20, :bgcolor => :white,
|
|
400
|
+
:color => :black, :text => "abc", :label => " Name: ", :label_color_pair => @datacolor
|
|
401
|
+
f2 = field "email", :display_length => 20, :bgcolor => :white,
|
|
402
|
+
:color => :blue, :text => "me@google.com", :label => "Email: ", :label_color_pair => @datacolor
|
|
403
|
+
f3 = radio :group => :grp, :text => "red", :value => "RED", :color => :red
|
|
404
|
+
f4 = radio :group => :grp, :text => "blue", :value => "BLUE", :color => :blue
|
|
405
|
+
f5 = radio :group => :grp, :text => "green", :value => "GREEN", :color => :green
|
|
406
|
+
stack :margin_top => 2, :margin => 2 do
|
|
407
|
+
r = container :row => 1, :col => 2, :width => 80, :height => 20, :title => "A container"
|
|
408
|
+
r.add(f1)
|
|
409
|
+
r.add(f2)
|
|
410
|
+
r.add(f3,f4,f5)
|
|
411
|
+
sl = status_line
|
|
412
|
+
end # stack
|
|
413
|
+
|
|
414
|
+
end # app
|
|
415
|
+
end # if
|