rbcurse-extras 0.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.
- data/README.md +75 -0
- data/VERSION +1 -0
- data/examples/data/list.txt +300 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/table.txt +36 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/inc/qdfilechooser.rb +70 -0
- data/examples/inc/rfe_renderer.rb +121 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/rfe.rb +1236 -0
- data/examples/test2.rb +670 -0
- data/examples/testeditlist.rb +78 -0
- data/examples/testtable.rb +270 -0
- data/examples/testvimsplit.rb +141 -0
- data/lib/rbcurse/extras/include/celleditor.rb +112 -0
- data/lib/rbcurse/extras/include/checkboxcellrenderer.rb +57 -0
- data/lib/rbcurse/extras/include/comboboxcellrenderer.rb +30 -0
- data/lib/rbcurse/extras/include/defaultlistselectionmodel.rb +79 -0
- data/lib/rbcurse/extras/include/listkeys.rb +37 -0
- data/lib/rbcurse/extras/include/listselectable.rb +144 -0
- data/lib/rbcurse/extras/include/tableextended.rb +40 -0
- data/lib/rbcurse/extras/widgets/horizlist.rb +203 -0
- data/lib/rbcurse/extras/widgets/menutree.rb +63 -0
- data/lib/rbcurse/extras/widgets/multilinelabel.rb +142 -0
- data/lib/rbcurse/extras/widgets/rcomboedit.rb +256 -0
- data/lib/rbcurse/extras/widgets/rlink.rb.moved +27 -0
- data/lib/rbcurse/extras/widgets/rlistbox.rb +1247 -0
- data/lib/rbcurse/extras/widgets/rmenulink.rb.moved +21 -0
- data/lib/rbcurse/extras/widgets/rmulticontainer.rb +304 -0
- data/lib/rbcurse/extras/widgets/rmultisplit.rb +722 -0
- data/lib/rbcurse/extras/widgets/rmultitextview.rb +306 -0
- data/lib/rbcurse/extras/widgets/rpopupmenu.rb +755 -0
- data/lib/rbcurse/extras/widgets/rtable.rb +1758 -0
- data/lib/rbcurse/extras/widgets/rvimsplit.rb +800 -0
- data/lib/rbcurse/extras/widgets/table/tablecellrenderer.rb +86 -0
- data/lib/rbcurse/extras/widgets/table/tabledatecellrenderer.rb +98 -0
- metadata +94 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rbcurse/extras/widgets/rlink'
|
2
|
+
##
|
3
|
+
module RubyCurses
|
4
|
+
class MenuLink < Link
|
5
|
+
dsl_property :description
|
6
|
+
|
7
|
+
def initialize form, config={}, &block
|
8
|
+
super
|
9
|
+
@col_offset = -1 * @col
|
10
|
+
@row_offset = -1 * @row
|
11
|
+
end
|
12
|
+
# added for some standardization 2010-09-07 20:28
|
13
|
+
# alias :text :getvalue # NEXT VERSION
|
14
|
+
# change existing text to label
|
15
|
+
|
16
|
+
def getvalue_for_paint
|
17
|
+
"%s %-12s - %-s" % [ @mnemonic , getvalue(), @description ]
|
18
|
+
end
|
19
|
+
##
|
20
|
+
end # class
|
21
|
+
end # module
|
@@ -0,0 +1,304 @@
|
|
1
|
+
=begin
|
2
|
+
* Name: MultiContainer
|
3
|
+
* Description View (cycle) multiple components in one container using a key or menu
|
4
|
+
* Author: rkumar (arunachalesha)
|
5
|
+
* file created 2010-03-15 10:40
|
6
|
+
--------
|
7
|
+
* License:
|
8
|
+
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
9
|
+
|
10
|
+
=end
|
11
|
+
require 'rbcurse'
|
12
|
+
|
13
|
+
include RubyCurses
|
14
|
+
module RubyCurses
|
15
|
+
extend self
|
16
|
+
|
17
|
+
##
|
18
|
+
# Extends TextView with ability to load more than one file or content
|
19
|
+
# and switch between files (buffers).
|
20
|
+
# NOTE: ideally, i should be able to dynamically add this functionality to either Textview
|
21
|
+
# or TextArea or even ListBox or Table someday. Should then be a Module rather than a class.
|
22
|
+
class MultiContainer < Widget
|
23
|
+
dsl_accessor :title
|
24
|
+
|
25
|
+
|
26
|
+
def initialize form = nil, config={}, &block
|
27
|
+
@focusable = true
|
28
|
+
@row_offset = @col_offset = 1
|
29
|
+
super
|
30
|
+
@bmanager = BufferManager.new self
|
31
|
+
init_vars
|
32
|
+
|
33
|
+
end
|
34
|
+
def init_vars
|
35
|
+
super
|
36
|
+
# the following allows us to navigate buffers with :bn :bp etc (with Alt pressed)
|
37
|
+
bind_key(?\M-:, :buffer_menu)
|
38
|
+
bind_key(?\M-;, :buffer_menu)
|
39
|
+
# bind_key([?\C-x, ?f], :file_edit)
|
40
|
+
bind_key([?\C-x, ?k], :delete_component)
|
41
|
+
bind_key([?\C-x, ?\C-b], :list_components)
|
42
|
+
bind_key(?\M-n, :goto_next_component)
|
43
|
+
bind_key(?\M-p, :goto_prev_component)
|
44
|
+
bind_key(?\M-1, :goto_first_component)
|
45
|
+
# easily cycle using p. n is used for next search.
|
46
|
+
#bind_key(?p, :buffer_previous)
|
47
|
+
@suppress_borders = false
|
48
|
+
@repaint_all = true
|
49
|
+
@name ||= "multicontainer"
|
50
|
+
end
|
51
|
+
## returns current buffer
|
52
|
+
# @return [RBuffer] current buffer
|
53
|
+
def current_component
|
54
|
+
@bmanager.current
|
55
|
+
end
|
56
|
+
##
|
57
|
+
# Add a component with a title
|
58
|
+
# @param [Widget] component
|
59
|
+
# @param [String] title
|
60
|
+
def add component, title
|
61
|
+
component.row = @row+@row_offset+0 # FFI changed 1 to 0 2011-09-12
|
62
|
+
component.col = @col+@col_offset+0 # FFI changed 1 to 0 2011-09-12
|
63
|
+
component.width = @width-2
|
64
|
+
component.height = @height-2
|
65
|
+
component.form = @form
|
66
|
+
component.override_graphic(@graphic)
|
67
|
+
@current_buffer = @bmanager.add component, title
|
68
|
+
@current_component = @current_buffer.component
|
69
|
+
#set_current_component
|
70
|
+
#set_form_row ## FFI added 2011-09-12 to get cursor at start when adding
|
71
|
+
$log.debug "MULTICONT ADD got cb : #{@current_component} "
|
72
|
+
end
|
73
|
+
def set_current_component
|
74
|
+
@current_component = @current_buffer.component
|
75
|
+
@current_title = @current_component.title # NOTE: unused, don't knw what for
|
76
|
+
set_form_row
|
77
|
+
@current_component.repaint_all true
|
78
|
+
end
|
79
|
+
# required otherwise some components may not get correct cursor position on entry
|
80
|
+
# e.g. table
|
81
|
+
def on_enter
|
82
|
+
set_form_row
|
83
|
+
end
|
84
|
+
def set_form_row #:nodoc:
|
85
|
+
if !@current_component.nil?
|
86
|
+
cc = @current_component
|
87
|
+
|
88
|
+
@current_component.on_enter # 2011-10-19 why was this not there earlier
|
89
|
+
|
90
|
+
# 2011-10-21 I've tried removing next 2 lines but there are certain case
|
91
|
+
# that do need them. See testmulticontainer.rb
|
92
|
+
|
93
|
+
@current_component.set_form_row
|
94
|
+
@current_component.set_form_col
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
def set_form_col
|
99
|
+
# deliberately empty since Form will call this and Widgets one is unsuitable
|
100
|
+
# for us
|
101
|
+
end
|
102
|
+
##
|
103
|
+
# multi-container
|
104
|
+
def handle_key ch #:nodoc:
|
105
|
+
$log.debug " MULTI handlekey #{ch}, #{@current_component}"
|
106
|
+
ret = :UNHANDLED
|
107
|
+
return :UNHANDLED unless @current_component
|
108
|
+
|
109
|
+
ret = @current_component.handle_key(ch)
|
110
|
+
$log.debug " MULTI = current comp #{@current_component} returned #{ret} "
|
111
|
+
if ret == :UNHANDLED
|
112
|
+
# check for bindings, these cannot override above keys since placed at end
|
113
|
+
begin
|
114
|
+
ret = process_key ch, self
|
115
|
+
$log.debug " MULTI = process_key returned #{ret} "
|
116
|
+
if ch > 177 && ch < 187
|
117
|
+
n = ch - 177
|
118
|
+
|
119
|
+
component_at(n)
|
120
|
+
ret = 0 # other unhandled goes back
|
121
|
+
# go to component n
|
122
|
+
end
|
123
|
+
rescue => err
|
124
|
+
$error_message.value = err.to_s
|
125
|
+
$log.error " Multicomponent process_key #{err} "
|
126
|
+
$log.debug(err.backtrace.join("\n"))
|
127
|
+
alert err.to_s
|
128
|
+
end
|
129
|
+
return :UNHANDLED if ret == :UNHANDLED
|
130
|
+
end
|
131
|
+
# check for any keys not handled and check our own ones
|
132
|
+
return ret #
|
133
|
+
end
|
134
|
+
def repaint
|
135
|
+
print_border if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
|
136
|
+
return unless @current_component
|
137
|
+
$log.debug " MULTI REPAINT - calling current_comps repaint #{@current_component} "
|
138
|
+
ret = @current_component.repaint
|
139
|
+
end
|
140
|
+
def print_border #:nodoc:
|
141
|
+
#$log.debug " #{@name} print_borders, #{@graphic.name} "
|
142
|
+
color = $datacolor
|
143
|
+
@graphic.print_border_only @row, @col, @height-1, @width, color #, Ncurses::A_REVERSE
|
144
|
+
print_title
|
145
|
+
end
|
146
|
+
def print_title #:nodoc:
|
147
|
+
#$log.debug " print_title #{@row}, #{@col}, #{@width} "
|
148
|
+
_title = @title || "" + @current_title
|
149
|
+
@graphic.printstring( @row, @col+(@width-_title.length)/2, _title, $datacolor, @title_attrib) unless _title.nil?
|
150
|
+
end
|
151
|
+
# this is just a test of the simple "most" menu
|
152
|
+
# can use this for next, prev, first, last, new, delete, overwrite etc
|
153
|
+
def buffer_menu
|
154
|
+
menu = PromptMenu.new self
|
155
|
+
menu.add(menu.create_mitem( 'l', "list buffers", "list buffers ", :list_components ))
|
156
|
+
item = menu.create_mitem( 'b', "Buffer Options", "Buffer Options" )
|
157
|
+
menu1 = PromptMenu.new( self, "Buffer Options")
|
158
|
+
menu1.add(menu1.create_mitem( 'n', "Next", "Switched to next buffer", :goto_next_component ))
|
159
|
+
menu1.add(menu1.create_mitem( 'p', "Prev", "Switched to previous buffer", :goto_prev_component ))
|
160
|
+
menu1.add(menu1.create_mitem( 'f', "First", "Switched to first buffer", :goto_first_component ))
|
161
|
+
menu1.add(menu1.create_mitem( 'l', "Last", "Switched to last buffer", :goto_last_component ))
|
162
|
+
menu1.add(menu1.create_mitem( 'd', "Delete", "Deleted buffer", :delete_component ))
|
163
|
+
item.action = menu1
|
164
|
+
menu.add(item)
|
165
|
+
# how do i know what's available. the application or window should know where to place
|
166
|
+
menu.display @form.window, $error_message_row, $error_message_col, $datacolor #, menu
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
def goto_next_component
|
171
|
+
perror "No other buffer" and return if @bmanager.size < 2
|
172
|
+
|
173
|
+
@current_buffer = @bmanager.next
|
174
|
+
set_current_component
|
175
|
+
end
|
176
|
+
|
177
|
+
def goto_prev_component
|
178
|
+
perror "No other buffer" and return if @bmanager.size < 2
|
179
|
+
|
180
|
+
@current_buffer = @bmanager.previous
|
181
|
+
$log.debug " buffer_prev got #{@current_buffer} "
|
182
|
+
set_current_component
|
183
|
+
end
|
184
|
+
def goto_first_component
|
185
|
+
@current_buffer = @bmanager.first
|
186
|
+
$log.debug " buffer_first got #{@current_buffer} "
|
187
|
+
set_current_component
|
188
|
+
end
|
189
|
+
def goto_last_component
|
190
|
+
@current_buffer = @bmanager.last
|
191
|
+
$log.debug " buffer_last got #{@current_buffer} "
|
192
|
+
set_current_component
|
193
|
+
end
|
194
|
+
def delete_component
|
195
|
+
if @bmanager.size > 1
|
196
|
+
@bmanager.delete_at
|
197
|
+
@current_component = @bmanager.previous
|
198
|
+
set_current_component
|
199
|
+
else
|
200
|
+
perror "Only one buffer. Cannot delete."
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def component_at index
|
205
|
+
cc = @bmanager.element_at index
|
206
|
+
return unless cc
|
207
|
+
@current_component = cc
|
208
|
+
#$log.debug " buffer_last got #{@current_component} "
|
209
|
+
set_current_component
|
210
|
+
end
|
211
|
+
def perror errmess
|
212
|
+
alert errmess
|
213
|
+
#@form.window.print_error_message errmess
|
214
|
+
end
|
215
|
+
def list_components
|
216
|
+
$log.debug " TODO buffers_list: #{@bmanager.size} "
|
217
|
+
menu = PromptMenu.new self
|
218
|
+
@bmanager.each_with_index{ |b, ix|
|
219
|
+
aproc = Proc.new { component_at(ix) }
|
220
|
+
name = b.title
|
221
|
+
num = ix + 1
|
222
|
+
menu.add(menu.create_mitem( num.to_s, name, "Switched to buffer #{ix}", aproc ))
|
223
|
+
}
|
224
|
+
menu.display @form.window, $error_message_row, $error_message_col, $datacolor
|
225
|
+
end
|
226
|
+
end # class multicontainer
|
227
|
+
##
|
228
|
+
# Handles multiple buffers, navigation, maintenance etc
|
229
|
+
# Instantiated at startup of
|
230
|
+
#
|
231
|
+
class BufferManager
|
232
|
+
include Enumerable
|
233
|
+
def initialize source
|
234
|
+
@source = source
|
235
|
+
@buffers = [] # contains RBuffer
|
236
|
+
@counter = 0
|
237
|
+
# for each buffer i need to store data, current_index (row), curpos (col offset) and title (filename).
|
238
|
+
end
|
239
|
+
def element_at index
|
240
|
+
@buffers[index]
|
241
|
+
end
|
242
|
+
def each
|
243
|
+
@buffers.each {|k| yield(k)}
|
244
|
+
end
|
245
|
+
|
246
|
+
##
|
247
|
+
# @return [RBuffer] current buffer/file
|
248
|
+
##
|
249
|
+
def current
|
250
|
+
@buffers[@counter]
|
251
|
+
end
|
252
|
+
##
|
253
|
+
# Would have liked to just return next buffer and not get lost in details of caller
|
254
|
+
#
|
255
|
+
# @return [RBuffer] next buffer/file
|
256
|
+
##
|
257
|
+
def next
|
258
|
+
@counter += 1
|
259
|
+
@counter = 0 if @counter >= @buffers.size
|
260
|
+
@buffers[@counter]
|
261
|
+
end
|
262
|
+
##
|
263
|
+
# @return [RBuffer] previous buffer/file
|
264
|
+
##
|
265
|
+
def previous
|
266
|
+
$log.debug " previous bs: #{@buffers.size}, #{@counter} "
|
267
|
+
@counter -= 1
|
268
|
+
return last() if @counter < 0
|
269
|
+
$log.debug " previous ctr #{@counter} "
|
270
|
+
@buffers[@counter]
|
271
|
+
end
|
272
|
+
def first
|
273
|
+
@counter = 0
|
274
|
+
@buffers[@counter]
|
275
|
+
end
|
276
|
+
def last
|
277
|
+
@counter = @buffers.size - 1
|
278
|
+
@buffers[@counter]
|
279
|
+
end
|
280
|
+
##
|
281
|
+
def delete_at index=@counter
|
282
|
+
@buffers.delete_at index
|
283
|
+
end
|
284
|
+
def delete_by_name name
|
285
|
+
@buffers.delete_if {|b| b.filename == name }
|
286
|
+
end
|
287
|
+
def insert component, position, title=nil
|
288
|
+
anew = RComponents.new(component, title)
|
289
|
+
@buffers.insert position, anew
|
290
|
+
@counter = position
|
291
|
+
return anew
|
292
|
+
end
|
293
|
+
def add component, title=nil
|
294
|
+
$log.debug " ADD H: #{component.height} C: #{component.width} "
|
295
|
+
insert component, @buffers.size, title
|
296
|
+
end
|
297
|
+
def size
|
298
|
+
@buffers.size
|
299
|
+
end
|
300
|
+
alias :count :size
|
301
|
+
end
|
302
|
+
RComponents = Struct.new(:component, :title)
|
303
|
+
|
304
|
+
end # modul
|
@@ -0,0 +1,722 @@
|
|
1
|
+
=begin
|
2
|
+
* Name: MultiSplit
|
3
|
+
* Description: allows user to create multiple splits
|
4
|
+
* This diverges from the standard SplitPane which allowed one split only.
|
5
|
+
This is inspired by the column-browse pattern as in when we view rdoc in a browser.
|
6
|
+
A user does not need to create multiple split panes embedded inside each other, we
|
7
|
+
don't have that kind of space, and expanding can be tricky since there is no mouse
|
8
|
+
to select panes. Mostly, this makes creating apps with this pattern easy for user.
|
9
|
+
|
10
|
+
|
11
|
+
* NOTE that VERTICAL_SPLIT means the *divider* is vertical.
|
12
|
+
* Author: rkumar (arunachalesha)
|
13
|
+
* file created 2010-08-31 20:18
|
14
|
+
Todo:
|
15
|
+
--------
|
16
|
+
* License:
|
17
|
+
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
18
|
+
|
19
|
+
=end
|
20
|
+
#require 'rubygems'
|
21
|
+
#require 'ncurses'
|
22
|
+
require 'logger'
|
23
|
+
require 'rbcurse'
|
24
|
+
|
25
|
+
#include Ncurses # FFI 2011-09-8
|
26
|
+
include RubyCurses
|
27
|
+
module RubyCurses
|
28
|
+
extend self
|
29
|
+
|
30
|
+
##
|
31
|
+
# A MultiSplit allows user to split N components vertically or horizontally.
|
32
|
+
# such as 3 listboxes, each dependent on what is selected in previous.
|
33
|
+
# This is the column-browse pattern, as in ruby's rdoc when seen in a browser.
|
34
|
+
# Also, this can be used for directory browsing, as in OSX Finder.
|
35
|
+
# One can keep adding components, and scroll
|
36
|
+
# back and forth, so we can have more components than are visible. See testmultispl.rb
|
37
|
+
# for a demo of this.
|
38
|
+
#
|
39
|
+
# This class allows for adding components in one direction, vertical or horizontal. It differs
|
40
|
+
# from Vimsplit in that you can have offscreen windows and scroll through. Vimsplit shows
|
41
|
+
# all windows but allows stacking and flowing of components.
|
42
|
+
#
|
43
|
+
# @since 1.1.5
|
44
|
+
# TODO -
|
45
|
+
# [ ] Don't print title if width less than title XXX or truncate - listbox
|
46
|
+
# x user specify max panes to show (beyond that hide and pan)
|
47
|
+
# x how many can be created
|
48
|
+
# - to squeeze panes and fit all or hide and pan
|
49
|
+
# x allow resize of panes
|
50
|
+
# - allow orientation change or not
|
51
|
+
# x some anamoly reg LEAVE and ENTER from last object
|
52
|
+
# x should we not be managing on_enter of listboxes when tabbing ?
|
53
|
+
# x how many panes to show, max to create
|
54
|
+
# x increase size - currently i recalc each time!
|
55
|
+
# x print more marker
|
56
|
+
# - allow user to specify preferred sizes and respect that
|
57
|
+
# x don't move to an empty list, can have a crash
|
58
|
+
#
|
59
|
+
|
60
|
+
class MultiSplit < Widget
|
61
|
+
dsl_property :orientation # :VERTICAL_SPLIT or :HORIZONTAL_SPLIT
|
62
|
+
dsl_accessor :border_color
|
63
|
+
dsl_accessor :border_attrib
|
64
|
+
# if no components have been added at time of repainting
|
65
|
+
#+ we could use this. This idea if that a user may want to
|
66
|
+
#+ show blank splits.
|
67
|
+
dsl_property :split_count
|
68
|
+
# should we allow adding more than split_count
|
69
|
+
# currently, we don't scroll, we narrow what is shown
|
70
|
+
dsl_accessor :unlimited
|
71
|
+
# allow user to resize components, default true
|
72
|
+
dsl_accessor :allow_resizing # XXX unused
|
73
|
+
# allow user to flip / exhange 2 components or not, default false
|
74
|
+
dsl_accessor :allow_exchanging # XXX unused
|
75
|
+
# when focus reenters this component, should it focus
|
76
|
+
# on first internal component, or last focused component.
|
77
|
+
# True means it will focus on first component (or last, if backtabbing)
|
78
|
+
dsl_accessor :cyclic_behavior
|
79
|
+
# maximum to show, if less than split_count then scrolling
|
80
|
+
dsl_property :max_visible
|
81
|
+
attr_reader :components
|
82
|
+
# should borders be suppressed or printed
|
83
|
+
dsl_accessor :suppress_borders
|
84
|
+
|
85
|
+
#attr_accessor :one_touch_expandable # boolean, default true # XXX
|
86
|
+
|
87
|
+
def initialize form, config={}, &block
|
88
|
+
@focusable = true
|
89
|
+
@editable = false
|
90
|
+
@cyclic_behavior = true
|
91
|
+
@row = 0
|
92
|
+
@col = 0
|
93
|
+
@split_count = nil
|
94
|
+
# this is the list of components
|
95
|
+
@components = []
|
96
|
+
# need to recalculate offsets and dimensions of all comps since new one added
|
97
|
+
# to be done once in repaint, and whenever a new one added (in repaint)
|
98
|
+
@recalc_required = true
|
99
|
+
@row_offset = @col_offset = 1
|
100
|
+
@suppress_borders = false
|
101
|
+
super
|
102
|
+
@orig_col = @col
|
103
|
+
@use_absolute = true; # set to true if not using subwins XXX CLEAN THIS
|
104
|
+
init_vars
|
105
|
+
end
|
106
|
+
def init_vars #:nodoc:
|
107
|
+
@_first_column_print = 0 # added 2009-10-07 11:25
|
108
|
+
@max_visible ||= @split_count
|
109
|
+
@_last_column_print = @_first_column_print + @max_visible - 1
|
110
|
+
|
111
|
+
# cascade_changes keeps the child exactly sized as per the pane which looks nice
|
112
|
+
#+ but may not really be what you want.
|
113
|
+
@cascade_changes=true
|
114
|
+
## if this splp is increased (ht or wid) then expand the child
|
115
|
+
@cascade_boundary_changes = true
|
116
|
+
@orientation ||= :HORIZONTAL_SPLIT # added 2010-01-13 15:05 since not set
|
117
|
+
|
118
|
+
# true means will request child to create a buffer, since cropping will be needed
|
119
|
+
# FIXME: if true then increases in size are not having effect !!!
|
120
|
+
@_child_buffering = false # private, internal. not to be changed by callers.
|
121
|
+
#@one_touch_expandable = true
|
122
|
+
#@is_expanding = false
|
123
|
+
@row_offset = @col_offset = 0 if @suppress_borders
|
124
|
+
|
125
|
+
#bind_key([?\C-w, ?o], :expand)
|
126
|
+
#bind_key([?\C-w, ?1], :expand)
|
127
|
+
#bind_key([?\C-w, ?2], :unexpand)
|
128
|
+
#bind_key([?\C-w, ?x], :exchange)
|
129
|
+
bind_key(?w, :goto_next_component)
|
130
|
+
bind_key(?b, :goto_prev_component)
|
131
|
+
bind_key([?\C-w, ?-], :decrease)
|
132
|
+
bind_key([?\C-w, ?+], :increase)
|
133
|
+
bind_key([?\C-w, ?=], :same)
|
134
|
+
|
135
|
+
end
|
136
|
+
##
|
137
|
+
# adds a component to the multisplit
|
138
|
+
# When you add a component to a container such as multisplit, be sure
|
139
|
+
# you create it with a nil form object, or else the main form will try to manage it.
|
140
|
+
# Containers typically manage their own components such as navigation and they
|
141
|
+
# give it the form/graphic object they were created with.
|
142
|
+
# @param [widget] a widget object to stack in a pane
|
143
|
+
def add comp
|
144
|
+
# for starters to make life simple, we force user to specify how many splits
|
145
|
+
# This is largely because i don;t know much about the buffering thing, is it still
|
146
|
+
# needed here or what. If we can postpone it, then we can compute this in a loop
|
147
|
+
# in repaint
|
148
|
+
raise "split_count must be given first. How many splits there will be." unless @split_count
|
149
|
+
$log.debug " multisplit: Adding a component #{@components.size} "
|
150
|
+
|
151
|
+
# until we hide those outside bounds, or are able to scroll, lets not allow add if
|
152
|
+
# exceeds
|
153
|
+
if @components.size >= @split_count
|
154
|
+
if @unlimited
|
155
|
+
#@split_count = @components.size + 1
|
156
|
+
# calc of width depending on ths
|
157
|
+
else
|
158
|
+
Ncurses.beep
|
159
|
+
return
|
160
|
+
end
|
161
|
+
end
|
162
|
+
@recalc_required = true
|
163
|
+
@components = [] if @components.nil?
|
164
|
+
@components << comp
|
165
|
+
#comp.height = nil # nuking listboxes height since it gets calculated
|
166
|
+
comp.parent_component = self
|
167
|
+
# dang ! this can go out of bounds ! XXX tab goes out
|
168
|
+
index = @components.size - 1 # expected as base 0 in compute
|
169
|
+
#index = @max_visible - 1 if index > @max_visible - 1
|
170
|
+
# all this ado to prevent cursor going out in the first display
|
171
|
+
# when index exceeds visible, since compute now uses running balance
|
172
|
+
if index > @max_visible - 1
|
173
|
+
# we copy the coords of the previous one
|
174
|
+
prev = @components[index-1]
|
175
|
+
comp.row = prev.row
|
176
|
+
comp.col = prev.col
|
177
|
+
comp.width = prev.width
|
178
|
+
comp.height = prev.height
|
179
|
+
else
|
180
|
+
compute_component comp, index
|
181
|
+
end
|
182
|
+
comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1, :right => comp.width-1, :form => @form ) # removed on 2011-09-29
|
183
|
+
comp.min_height ||= 5
|
184
|
+
comp.min_width ||= 5
|
185
|
+
return self
|
186
|
+
end
|
187
|
+
alias :<< :add
|
188
|
+
|
189
|
+
def [](index)
|
190
|
+
raise "MultiSplit: Please add components first" unless @components
|
191
|
+
@components[index]
|
192
|
+
end
|
193
|
+
def size
|
194
|
+
@components.size
|
195
|
+
end
|
196
|
+
alias :length :size
|
197
|
+
##
|
198
|
+
# compute component dimensions in one place
|
199
|
+
# @param [widget] a widget
|
200
|
+
# @param [Fixnum] offset in list of components
|
201
|
+
# XXX if called from outside balance can have last value !!!
|
202
|
+
# FIXME for last component, take as much as is left height or width
|
203
|
+
# otherwise odd figures will leave on row unoccupied
|
204
|
+
def compute_component comp, index
|
205
|
+
@balance ||= 0
|
206
|
+
if @orientation == :HORIZONTAL_SPLIT
|
207
|
+
# XXX NOT TESTED TODO
|
208
|
+
@comp_height = (@height / @split_count) - 0
|
209
|
+
@comp_width = @width
|
210
|
+
h = @comp_height
|
211
|
+
if @recalc_required
|
212
|
+
comp.height = h # listboxes etal calculate a height so that will stand !! XXX
|
213
|
+
else
|
214
|
+
comp.height ||= h # listboxes etal calculate a height so that will stand !! XXX
|
215
|
+
end
|
216
|
+
w = @comp_width
|
217
|
+
#r = @row + ( comp.height * index)
|
218
|
+
r = @row + @balance
|
219
|
+
if r > @row + @height
|
220
|
+
r = @row + @height
|
221
|
+
end
|
222
|
+
#alert "r #{@row} h #{@height} ::: comp row #{r} h #{h} bal:#{@balance} "
|
223
|
+
@balance += comp.height
|
224
|
+
c = @col
|
225
|
+
comp.width = w
|
226
|
+
comp.row = r
|
227
|
+
comp.col = c
|
228
|
+
else
|
229
|
+
@comp_height = @height
|
230
|
+
@comp_width = (@width / @split_count) - 0
|
231
|
+
h = @comp_height
|
232
|
+
w = @comp_width
|
233
|
+
if @recalc_required
|
234
|
+
comp.width = w
|
235
|
+
else
|
236
|
+
comp.width ||= w
|
237
|
+
end
|
238
|
+
#c = @col + ( w * index) # this makes them all equal
|
239
|
+
c = @col + @balance
|
240
|
+
if c > @col + @width
|
241
|
+
c = @col + @width
|
242
|
+
end
|
243
|
+
$log.debug "XXXX index #{index} , w #{comp.width} , c = #{c} , bal #{@balance} c+w:#{@col+@width} "
|
244
|
+
#if index < @max_visible - 1
|
245
|
+
@balance += comp.width
|
246
|
+
#end
|
247
|
+
r = @row
|
248
|
+
comp.height = h
|
249
|
+
comp.row = r
|
250
|
+
comp.col = c
|
251
|
+
#$log.debug " XXXX index r c #{r} #{c} "
|
252
|
+
end
|
253
|
+
comp
|
254
|
+
end
|
255
|
+
def increase
|
256
|
+
_multiplier = ($multiplier == 0 ? 1 : $multiplier )
|
257
|
+
delta = _multiplier
|
258
|
+
c = @current_component
|
259
|
+
n = get_next_component
|
260
|
+
n = get_prev_component unless n
|
261
|
+
return unless n
|
262
|
+
if @orientation == :HORIZONTAL_SPLIT
|
263
|
+
if n.height > 3 + delta
|
264
|
+
c.height += delta
|
265
|
+
n.height -= delta
|
266
|
+
end
|
267
|
+
else
|
268
|
+
if n.width > 3 + delta
|
269
|
+
c.width += delta
|
270
|
+
n.width -= delta
|
271
|
+
end
|
272
|
+
end
|
273
|
+
@repaint_required = true
|
274
|
+
self
|
275
|
+
end
|
276
|
+
# decrease size of current component.
|
277
|
+
# if last one, then border printing exceeds right boundary. values look okay
|
278
|
+
# dunno why XXX FIXME
|
279
|
+
def decrease
|
280
|
+
_multiplier = ($multiplier == 0 ? 1 : $multiplier )
|
281
|
+
delta = _multiplier
|
282
|
+
$log.debug "XXXX decrease got mult #{$_multiplier} "
|
283
|
+
c = @current_component
|
284
|
+
# if decreasing last component then increase previous
|
285
|
+
# otherwise always increase the next
|
286
|
+
n = get_next_component || get_prev_component
|
287
|
+
return unless n # if no other, don't allow
|
288
|
+
if @orientation == :HORIZONTAL_SPLIT
|
289
|
+
c.height -= delta
|
290
|
+
n.height += delta
|
291
|
+
# TODO
|
292
|
+
else
|
293
|
+
if c.width > 3 + delta
|
294
|
+
c.width -= delta
|
295
|
+
n.width += delta
|
296
|
+
end
|
297
|
+
end
|
298
|
+
@repaint_required = true
|
299
|
+
self
|
300
|
+
end
|
301
|
+
def same
|
302
|
+
@components.each do |comp|
|
303
|
+
comp.height = @comp_height
|
304
|
+
comp.width = @comp_width
|
305
|
+
end
|
306
|
+
@repaint_required = true
|
307
|
+
self
|
308
|
+
end
|
309
|
+
# @return [widget] next component or nil if no next
|
310
|
+
def get_next_component
|
311
|
+
return @components[@current_index+1]
|
312
|
+
end
|
313
|
+
# @return [widget] prev component or nil if no next
|
314
|
+
def get_prev_component
|
315
|
+
return nil if @current_index == 0
|
316
|
+
return @components[@current_index-1]
|
317
|
+
end
|
318
|
+
##
|
319
|
+
#
|
320
|
+
# change height of splitpane
|
321
|
+
# @param val [int] new height of splitpane
|
322
|
+
# @return [int] old ht if nil passed
|
323
|
+
def height(*val)
|
324
|
+
return @height if val.empty?
|
325
|
+
oldvalue = @height || 0
|
326
|
+
super
|
327
|
+
@height = val[0]
|
328
|
+
return if @components.nil? || @components.empty?
|
329
|
+
delta = @height - oldvalue
|
330
|
+
@repaint_required = true
|
331
|
+
if !@cascade_boundary_changes.nil?
|
332
|
+
# must tell children if height changed which will happen in nested splitpanes
|
333
|
+
# must adjust to components own offsets too
|
334
|
+
if @orientation == :VERTICAL_SPLIT
|
335
|
+
@components.each do |e|
|
336
|
+
e.height += delta
|
337
|
+
end
|
338
|
+
else
|
339
|
+
e = @components.first
|
340
|
+
e.height += delta
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
##
|
345
|
+
# change width of splitpane
|
346
|
+
# @param val [int, nil] new width of splitpane
|
347
|
+
# @return [int] old width if nil passed
|
348
|
+
# NOTE: if VERTICAL, then expand or contract only second
|
349
|
+
# If HORIZ then expand / contract both
|
350
|
+
# Actually this is very complicated since reducing should take into account min_width
|
351
|
+
def width(*val)
|
352
|
+
return @width if val.empty?
|
353
|
+
# must tell children if height changed which will happen in nested splitpanes
|
354
|
+
oldvalue = @width || 0
|
355
|
+
super
|
356
|
+
@width = val[0]
|
357
|
+
delta = @width - oldvalue
|
358
|
+
$log.debug " SPLP #{@name} width #{oldvalue}, #{@width}, #{delta} "
|
359
|
+
@repaint_required = true
|
360
|
+
if !@cascade_boundary_changes.nil?
|
361
|
+
# must adjust to components own offsets too
|
362
|
+
# NOTE: 2010-01-10 20:11 if we increase width by one, each time will both components get increased by one.
|
363
|
+
if @orientation == :HORIZONTAL_SPLIT
|
364
|
+
@components.each do |e|
|
365
|
+
e.width += delta
|
366
|
+
end
|
367
|
+
else
|
368
|
+
# any change in width must effect col of others too ! 2010-08-31 21:57 AUG2010
|
369
|
+
# which is why this should be done in repaint and not here
|
370
|
+
# ## next change should only happen if sc w < ...
|
371
|
+
# if @second_component.width < @width - (rc + @col_offset + @divider_offset + 1)
|
372
|
+
last = @components.last
|
373
|
+
last.width += delta
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
##
|
378
|
+
# resets divider location based on preferred size of first component
|
379
|
+
# @return :ERROR if min sizes failed
|
380
|
+
# You may want to check for ERROR and if so, resize_weight to 0.50
|
381
|
+
def reset_to_preferred_sizes
|
382
|
+
alert "TODO THIS reset_to "
|
383
|
+
return if @components.nil?
|
384
|
+
@repaint_required = true
|
385
|
+
end
|
386
|
+
# recalculates components and calls repaint
|
387
|
+
def update_components # #:nodoc:
|
388
|
+
@balance = 0
|
389
|
+
@max_visible ||= @split_count
|
390
|
+
@_first_column_print ||= 0
|
391
|
+
@_last_column_print = @_first_column_print + @max_visible - 1
|
392
|
+
$log.debug " XXXX #{@_first_column_print} , last print #{@_last_column_print} "
|
393
|
+
@components.each_with_index do |comp,index|
|
394
|
+
next if index < @_first_column_print
|
395
|
+
break if index > @_last_column_print
|
396
|
+
compute_component comp, index
|
397
|
+
comp.set_buffering(:target_window => @target_window || @form.window, :form => @form ) # 2011-09-29
|
398
|
+
#comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1, :right => comp.width-1, :form => @form )
|
399
|
+
comp.repaint
|
400
|
+
end
|
401
|
+
#@balance = 0
|
402
|
+
@recalc_required = false
|
403
|
+
end
|
404
|
+
def repaint # multisplitpane #:nodoc:
|
405
|
+
if @graphic.nil?
|
406
|
+
@graphic = @target_window || @form.window
|
407
|
+
raise "graphic nil in rsplitpane #{@name} " unless @graphic
|
408
|
+
end
|
409
|
+
|
410
|
+
if @repaint_required
|
411
|
+
# repaint all ?
|
412
|
+
@components.each { |e| e.repaint_all(true) }
|
413
|
+
end
|
414
|
+
if @repaint_required
|
415
|
+
## paint border and divider
|
416
|
+
$log.debug "MULTISPLP #{@name} repaint split H #{@height} W #{@width} "
|
417
|
+
bordercolor = @border_color || $datacolor
|
418
|
+
borderatt = @border_attrib || Ncurses::A_NORMAL
|
419
|
+
absrow = abscol = 0
|
420
|
+
if @use_absolute
|
421
|
+
absrow = @row
|
422
|
+
abscol = @col
|
423
|
+
end
|
424
|
+
if @use_absolute
|
425
|
+
$log.debug " #{@graphic} #{name} calling print_border #{@row} #{@col} #{@height}-1 #{@width}-1 "
|
426
|
+
@graphic.print_border(@row, @col, @height-1, @width-1, bordercolor, borderatt) if !@suppress_borders
|
427
|
+
else
|
428
|
+
$log.debug " #{@graphic} calling print_border 0,0"
|
429
|
+
@graphic.print_border(0, 0, @height-1, @width-1, bordercolor, borderatt) unless @suppress_borders
|
430
|
+
end
|
431
|
+
rc = -1
|
432
|
+
|
433
|
+
@graphic.attron(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
|
434
|
+
# 2010-02-14 18:23 - non buffered, have to make relative coords into absolute
|
435
|
+
#+ by adding row and col
|
436
|
+
count = @components.nil? ? @split_count : @components.size
|
437
|
+
count = @components.empty? ? @split_count : @components.size
|
438
|
+
if @orientation == :VERTICAL_SPLIT
|
439
|
+
@comp_height ||= @height
|
440
|
+
@comp_width ||= (@width / @split_count) - 0
|
441
|
+
$log.debug "SPLP #{@name} prtingign split vline divider 1, rc: #{rc}, h:#{@height} - 2 "
|
442
|
+
#@graphic.mvvline(absrow+1, rc+abscol, 0, @height-2)
|
443
|
+
# (1...count).each(){|i| @graphic.mvvline(absrow+1, (i*@comp_width)+abscol, 0, @height-2) }
|
444
|
+
# TODO put vlines here
|
445
|
+
# commented off since it uses fixed values and we are increaseing and dec
|
446
|
+
|
447
|
+
else
|
448
|
+
@comp_height ||= (@height / @split_count) - 1
|
449
|
+
@comp_width ||= @width
|
450
|
+
#$log.debug "SPLP #{@name} prtingign split hline divider rc: #{rc} , 1 , w:#{@width} - 2"
|
451
|
+
#@graphic.mvhline(rc+absrow, abscol+1, 0, @width-2)
|
452
|
+
# XXX in next line -2 at end was causing an overlap into final border col,
|
453
|
+
# this need correction in splitpane XXX
|
454
|
+
#(1...count).each(){|i| @graphic.mvhline((i*@comp_height)+absrow, abscol+1, 0, @width-3) }
|
455
|
+
# TODO put hlines here
|
456
|
+
end
|
457
|
+
@graphic.attroff(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
|
458
|
+
update_components
|
459
|
+
_print_more_columns_marker true
|
460
|
+
@graphic.wrefresh # 2010-02-14 20:18 SUBWIN ONLY ??? what is this doing here ? XXX
|
461
|
+
else
|
462
|
+
# repaint only those components that may have changed
|
463
|
+
@components.each { |e| e.repaint }
|
464
|
+
end
|
465
|
+
## XXX do not paint what is outside of bounds. See tabbedpane or scrollform
|
466
|
+
#paint
|
467
|
+
@repaint_required = false
|
468
|
+
end
|
469
|
+
def getvalue #:nodoc:
|
470
|
+
# TODO
|
471
|
+
end
|
472
|
+
# take focus to next pane (component in it)
|
473
|
+
# if its the last, return UNHANDLED so form can take to next field
|
474
|
+
# @return [0, :UNHANDLED] success, or last component
|
475
|
+
|
476
|
+
def goto_next_component
|
477
|
+
if @current_component != nil
|
478
|
+
@current_component.on_leave
|
479
|
+
if on_last_component?
|
480
|
+
return :UNHANDLED
|
481
|
+
end
|
482
|
+
@current_index += 1
|
483
|
+
@current_component = @components[@current_index]
|
484
|
+
# is it visible
|
485
|
+
#@current_index.between?(_first_column_print, _last_column_print)
|
486
|
+
if @current_index > @_last_column_print
|
487
|
+
# TODO need to check for exceeding
|
488
|
+
@_first_column_print += 1
|
489
|
+
@_last_column_print += 1
|
490
|
+
@repaint_required = true
|
491
|
+
end
|
492
|
+
# shoot if this this put on a form with other widgets
|
493
|
+
# we would never get out, should return nil -1 in handle key
|
494
|
+
unless @current_component
|
495
|
+
$log.debug " CAME HERE unless @current_component setting to first"
|
496
|
+
raise " CAME HERE unless @current_component setting to first"
|
497
|
+
@current_index = 0
|
498
|
+
@current_component = @components[@current_index]
|
499
|
+
end
|
500
|
+
else
|
501
|
+
# this happens in one_tab_expand
|
502
|
+
#@current_component = @second_component if @first_component.nil?
|
503
|
+
#@current_component = @first_component if @second_component.nil?
|
504
|
+
# XXX not sure what to do here, will it come
|
505
|
+
$log.debug " CAME HERE in else clause MSP setting to first"
|
506
|
+
raise" CAME HERE in else clause MSP setting to first"
|
507
|
+
@current_index = 0
|
508
|
+
@current_component = @components[@current_index]
|
509
|
+
end
|
510
|
+
return set_form_row
|
511
|
+
end
|
512
|
+
|
513
|
+
# take focus to prev pane (component in it)
|
514
|
+
# if its the first, return UNHANDLED so form can take to prev field
|
515
|
+
# @return [0, :UNHANDLED] success, or first component
|
516
|
+
def goto_prev_component
|
517
|
+
if @current_component != nil
|
518
|
+
@current_component.on_leave
|
519
|
+
if on_first_component?
|
520
|
+
return :UNHANDLED
|
521
|
+
end
|
522
|
+
@current_index -= 1
|
523
|
+
@current_component = @components[@current_index]
|
524
|
+
if @current_index < @_first_column_print
|
525
|
+
# TODO need to check for zero
|
526
|
+
@_first_column_print -= 1
|
527
|
+
@_last_column_print -= 1
|
528
|
+
@repaint_required = true
|
529
|
+
end
|
530
|
+
# shoot if this this put on a form with other widgets
|
531
|
+
# we would never get out, should return nil -1 in handle key
|
532
|
+
unless @current_component
|
533
|
+
@current_index = 0
|
534
|
+
@current_component = @components[@current_index]
|
535
|
+
end
|
536
|
+
else
|
537
|
+
# this happens in one_tab_expand
|
538
|
+
#@current_component = @second_component if @first_component.nil?
|
539
|
+
#@current_component = @first_component if @second_component.nil?
|
540
|
+
# XXX not sure what to do here, will it come
|
541
|
+
@current_index = 0
|
542
|
+
@current_component = @components[@current_index]
|
543
|
+
end
|
544
|
+
set_form_row
|
545
|
+
return 0
|
546
|
+
end
|
547
|
+
def on_first_component?
|
548
|
+
@current_component == @components.first
|
549
|
+
end
|
550
|
+
def on_last_component?
|
551
|
+
@current_component == @components.last
|
552
|
+
end
|
553
|
+
## Handles key for splitpanes
|
554
|
+
## By default, first component gets focus, not the SPL itself.
|
555
|
+
##+ Mostly passing to child, and handling child's left-overs.
|
556
|
+
# please use bind_key for all mappings.
|
557
|
+
# Avoid adding code in here. Let this be generic
|
558
|
+
def handle_key ch #:nodoc:
|
559
|
+
_multiplier = ($multiplier == 0 ? 1 : $multiplier )
|
560
|
+
@current_component ||= @first_component
|
561
|
+
@current_index ||= 0
|
562
|
+
## 2010-01-15 12:57 this helps me switch between highest level
|
563
|
+
## However, i should do as follows:
|
564
|
+
## If tab on second component, return UNHA so form can take to next field
|
565
|
+
## If B_tab on second comp, switch to first
|
566
|
+
## If B_tab on first comp, return UNHA so form can take to prev field
|
567
|
+
if ch == KEY_TAB
|
568
|
+
return goto_next_component
|
569
|
+
#return 0
|
570
|
+
elsif ch == KEY_BTAB
|
571
|
+
return goto_prev_component
|
572
|
+
end
|
573
|
+
|
574
|
+
if @current_component != nil
|
575
|
+
ret = @current_component.handle_key ch
|
576
|
+
return ret if ret != :UNHANDLED
|
577
|
+
else
|
578
|
+
## added 2010-01-07 18:59 in case nothing in there.
|
579
|
+
$log.debug " SPLP #{@name} - no component installed in splitpane"
|
580
|
+
#return :UNHANDLED
|
581
|
+
end
|
582
|
+
$log.debug " mmplitpane #{@name} gets KEY #{ch}"
|
583
|
+
case ch
|
584
|
+
when ?\C-c.getbyte(0)
|
585
|
+
$multiplier = 0
|
586
|
+
return 0
|
587
|
+
when ?0.getbyte(0)..?9.getbyte(0)
|
588
|
+
$multiplier *= 10 ; $multiplier += (ch-48)
|
589
|
+
return 0
|
590
|
+
end
|
591
|
+
ret = process_key ch, self
|
592
|
+
return :UNHANDLED if ret == :UNHANDLED
|
593
|
+
|
594
|
+
$multiplier = 0
|
595
|
+
return 0
|
596
|
+
end
|
597
|
+
def paint #:nodoc:
|
598
|
+
#@repaint_required = false
|
599
|
+
end
|
600
|
+
# this is executed when the component gets focus
|
601
|
+
# and will happen each time on traversal
|
602
|
+
# Used to place the focus on correct internal component
|
603
|
+
# and place cursor where component should have it.
|
604
|
+
# User can press tab, to come here, or it could be first field of form,
|
605
|
+
# or he could press a mnemonic.
|
606
|
+
def on_enter
|
607
|
+
return if @components.nil?
|
608
|
+
# cyclic means it always lands into first comp just as in rdoc
|
609
|
+
# otherwise it will always land in last visited component
|
610
|
+
if @cyclic_behavior
|
611
|
+
# if user backtabbed in place him on last comp
|
612
|
+
# else place him in first.
|
613
|
+
if $current_key == KEY_BTAB
|
614
|
+
@current_component = @components[@_last_column_print]
|
615
|
+
@current_index = @_last_column_print
|
616
|
+
else
|
617
|
+
@current_component = @components[@_first_column_print]
|
618
|
+
@current_index = @_first_column_print
|
619
|
+
end
|
620
|
+
end
|
621
|
+
@current_component ||= @components.first
|
622
|
+
set_form_row
|
623
|
+
end
|
624
|
+
# sets cursor on correct row, col
|
625
|
+
# should we raise error or throw exception if can;t enter
|
626
|
+
def set_form_row #:nodoc:
|
627
|
+
if !@current_component.nil?
|
628
|
+
c=@current_component
|
629
|
+
$log.debug "XXXXX #{@name} set_form_row calling sfr for #{@current_component.name}, #{c.row}, #{c.col} "
|
630
|
+
#@current_component.set_form_row
|
631
|
+
# trigger the on_enter handler
|
632
|
+
# my god XXX this assumes a listbox !! FIXME
|
633
|
+
# on enter should return a false or error so we don't proceed
|
634
|
+
# or throw exception
|
635
|
+
if @current_component.row_count > 0
|
636
|
+
@current_component.on_enter # typically on enter does a set_form_row
|
637
|
+
# XXX another assumption that is has this !!!
|
638
|
+
@current_component.set_form_col
|
639
|
+
return 0
|
640
|
+
end
|
641
|
+
#
|
642
|
+
end
|
643
|
+
return :UNHANDLED
|
644
|
+
end
|
645
|
+
# added 2010-02-09 10:10
|
646
|
+
# sets the forms cursor column correctly
|
647
|
+
# earlier the super was being called which missed out on child's column.
|
648
|
+
# Note: splitpane does not use the cursor, so it does not know where cursor should be displayed,
|
649
|
+
#+ the child has to decide where it should be displayed.
|
650
|
+
def set_form_col #:nodoc:
|
651
|
+
return if @current_component.nil?
|
652
|
+
#$log.debug " #{@name} set_form_col calling sfc for #{@current_component.name} "
|
653
|
+
@current_component.set_form_col
|
654
|
+
end
|
655
|
+
## expand a split to maximum. This is the one_touch_expandable feature
|
656
|
+
# Currently mapped to C-w 1 (mnemonic for one touch), or C-w o (vim's only)
|
657
|
+
# To revert, you have to unexpand
|
658
|
+
# Note: basically, i nil the component that we don't want to see
|
659
|
+
def expand
|
660
|
+
return unless @one_touch_expandable
|
661
|
+
# TODO
|
662
|
+
#@is_expanding = true # this is required so i don't check for min_width later
|
663
|
+
#$log.debug " callign expand "
|
664
|
+
#if @current_component == @first_component
|
665
|
+
#@saved_component = @second_component
|
666
|
+
#@second_component = nil
|
667
|
+
#if @orientation == :VERTICAL_SPLIT
|
668
|
+
#set_divider_location @width - 1
|
669
|
+
#else
|
670
|
+
#set_divider_location @height - 1
|
671
|
+
#end
|
672
|
+
#$log.debug " callign expand 2 nil #{@divider_location}, h:#{@height} w: #{@width} "
|
673
|
+
#else
|
674
|
+
#@saved_component = @first_component
|
675
|
+
#@first_component = nil
|
676
|
+
#set_divider_location 1
|
677
|
+
#$log.debug " callign expand 1 nil #{@divider_location}, h:#{@height} w: #{@width} "
|
678
|
+
#end
|
679
|
+
#@repaint_required = true
|
680
|
+
end
|
681
|
+
# after expanding one split, revert to original - actually i reset, rather than revert
|
682
|
+
# This only works after expand has been done
|
683
|
+
def unexpand
|
684
|
+
#$log.debug " inside unexpand "
|
685
|
+
#return unless @saved_component
|
686
|
+
#if @first_component.nil?
|
687
|
+
#@first_component = @saved_component
|
688
|
+
#else
|
689
|
+
#@second_component = @saved_component
|
690
|
+
#end
|
691
|
+
#@saved_component = nil
|
692
|
+
#@repaint_required = true
|
693
|
+
#reset_to_preferred_sizes
|
694
|
+
end
|
695
|
+
|
696
|
+
# exchange 2 splits, bound to C-w x
|
697
|
+
# TODO
|
698
|
+
def exchange
|
699
|
+
alert "TODO"
|
700
|
+
#tmp = @first_component
|
701
|
+
#@first_component = @second_component
|
702
|
+
#@second_component = tmp
|
703
|
+
#@repaint_required = true
|
704
|
+
#reset_to_preferred_sizes
|
705
|
+
end
|
706
|
+
def tile
|
707
|
+
return unless @tiling_allowed
|
708
|
+
# TODO
|
709
|
+
end
|
710
|
+
private
|
711
|
+
def _print_more_columns_marker tf
|
712
|
+
# this marker shows that there are more columns to right
|
713
|
+
tf = @_last_column_print < @components.size - 1
|
714
|
+
marker = tf ? Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
|
715
|
+
#@graphic.mvwaddch @row+@height-1, @col+@width-2, marker
|
716
|
+
@graphic.mvwaddch @row+@height-1, @col+@width-3, marker
|
717
|
+
# show if columns to left or not
|
718
|
+
marker = @_first_column_print > 0 ? Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
|
719
|
+
@graphic.mvwaddch @row+@height-1, @col+@_first_column_print+1, marker
|
720
|
+
end
|
721
|
+
end # class
|
722
|
+
end # module
|