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,800 @@
|
|
1
|
+
# This is a new kind of splitpane, inspired by the vim editor.
|
2
|
+
# I was deeply frustrated with the Java kind of splitpane,
|
3
|
+
# which requires splitpanes within splitpanes to get several split.
|
4
|
+
# This is an attempt at getting many splits, keeping them at one level
|
5
|
+
# and keeping the interface as simple as possible, with minimal input
|
6
|
+
# from user.
|
7
|
+
# It usually takes a listbox or textview or textarea.
|
8
|
+
# It can also take an array, or string or hash.
|
9
|
+
# It supports moving the split, and increasing or decreasing the current box to some extent.
|
10
|
+
# Typically if the split is vertical, add stacks the components, one below the other.
|
11
|
+
# If horizontal, if will flow the components, to the right of previous. This can be overriden by passing
|
12
|
+
# type as :STACK or :FLOW.
|
13
|
+
# See examples/testvimsplit.rb
|
14
|
+
#
|
15
|
+
# This does not support changing the orientation at run time, that's nice for demos, but a pain
|
16
|
+
# to get right, and results in a lot of extra code, meaning more bugs.
|
17
|
+
# TODO: create a class that contains component array and a pointer so it can give next/prev
|
18
|
+
# i am tired of maintaining this everywhere.
|
19
|
+
require 'rbcurse'
|
20
|
+
require 'rbcurse/extras/widgets/rlistbox'
|
21
|
+
require 'rbcurse/core/widgets/divider'
|
22
|
+
require 'rbcurse/core/util/focusmanager'
|
23
|
+
|
24
|
+
include RubyCurses
|
25
|
+
module RubyCurses
|
26
|
+
extend self
|
27
|
+
class Coord < Struct.new(:row, :col, :h, :w); end
|
28
|
+
# Split contains info for a component added. weight is preferred weight
|
29
|
+
# and can contain value :AUTO. act_weight has the weight calculated.
|
30
|
+
# Often, last component can be nil, remainder will be assigned to it.
|
31
|
+
class Split < Struct.new(:which, :type, :weight, :act_weight); end
|
32
|
+
class ResizeEvent < Struct.new(:source, :type); end
|
33
|
+
|
34
|
+
# A simpler replacement for the java-esque SplitPane. This can take multiple splits
|
35
|
+
# and does not require splits within splits as SplitPane does.
|
36
|
+
# This is less functional, but should be easier to use, setup and hack.
|
37
|
+
class VimSplit < Widget
|
38
|
+
|
39
|
+
# split orientation :V or :H
|
40
|
+
dsl_accessor :orientation
|
41
|
+
# min and max weight of main split. do not allow user to exceed these
|
42
|
+
dsl_accessor :min_weight, :max_weight
|
43
|
+
dsl_accessor :suppress_borders #to_print_borders
|
44
|
+
dsl_accessor :border_attrib, :border_color
|
45
|
+
attr_reader :current_component
|
46
|
+
def initialize form, config={}, &block
|
47
|
+
if config[:width] == :EXPAND
|
48
|
+
config[:width] = Ncurses.COLS - config[:col]
|
49
|
+
end
|
50
|
+
if config[:orientation] == nil
|
51
|
+
config[:orientation] = :HORIZONTAL_SPLIT
|
52
|
+
else
|
53
|
+
# if first char is V or H then fill it in.
|
54
|
+
char = config[:orientation].to_s[0,1].upcase
|
55
|
+
if char == "V"
|
56
|
+
config[:orientation] = :VERTICAL_SPLIT
|
57
|
+
else
|
58
|
+
config[:orientation] = :HORIZONTAL_SPLIT
|
59
|
+
end
|
60
|
+
end
|
61
|
+
@max_weight ||= 0.8
|
62
|
+
@min_weight ||= 0.1 # earlier 0.2 but i wanted 0.15, someone may want 0.05 ??
|
63
|
+
@suppress_borders = false
|
64
|
+
@_use_preferred_sizes = true
|
65
|
+
@row_offset = @col_offset = 1
|
66
|
+
# type can be :INCREASE, :DECREASE, :EXPAND, :UNEXPAND :EQUAL
|
67
|
+
@_events ||= []
|
68
|
+
@_events.push :COMPONENT_RESIZE_EVENT
|
69
|
+
@_events.push :DRAG_EVENT
|
70
|
+
super
|
71
|
+
@focusable = true
|
72
|
+
@editable = false
|
73
|
+
@components = [] # all components
|
74
|
+
@c1 =[] # first split's comps
|
75
|
+
@c2 =[] # second split's comps
|
76
|
+
# coordinates of a split, i calculate and increment row col as i go.
|
77
|
+
@c1rc = nil # TODO create once only
|
78
|
+
@c2rc = nil
|
79
|
+
|
80
|
+
# hash, keyed on component, contains Split (which side, flow or stack, weight)
|
81
|
+
@ch = {}
|
82
|
+
@weight ||= 0.50
|
83
|
+
|
84
|
+
init_vars
|
85
|
+
bind_key([?\C-w,?o], :expand)
|
86
|
+
bind_key([?\C-w,?1], :expand)
|
87
|
+
bind_key([?\C-w,?2], :unexpand)
|
88
|
+
bind_key([?\C-w,?\C-w], :goto_other_split)
|
89
|
+
bind_key([?\C-w,?-], :decrease_height)
|
90
|
+
bind_key([?\C-w,?+], :increase_height)
|
91
|
+
bind_key([?\C-w,?<], :decrease_width)
|
92
|
+
bind_key([?\C-w,?>], :increase_width)
|
93
|
+
bind_key([?\C-w,?i], :increase_weight)
|
94
|
+
bind_key([?\C-w,?d], :decrease_weight)
|
95
|
+
bind_key([?\C-w,?6], :increase_current_component)
|
96
|
+
bind_key([?\C-w,?5], :decrease_current_component)
|
97
|
+
# this needs to be set at application level
|
98
|
+
bind_key(FFI::NCurses::KEY_F3) {RubyCurses::FocusManager.toggle_focusable}
|
99
|
+
end
|
100
|
+
def init_vars
|
101
|
+
@repaint_required = true
|
102
|
+
@recalculate_splits = true # convert weight to size
|
103
|
+
@row_offset = @col_offset = 0 if @suppress_borders # FIXME supposed to use this !!
|
104
|
+
|
105
|
+
@internal_width = 2
|
106
|
+
@internal_width = 1 if @suppress_borders
|
107
|
+
|
108
|
+
end
|
109
|
+
# uses intelligent default a vertical split would prefer stacks and
|
110
|
+
# a horizontal split would go with flows
|
111
|
+
# @param [Widget, Array, String, Hash, Variable] to add
|
112
|
+
# @param [:FIRST, :SECOND]
|
113
|
+
def add c, which, weight=:AUTO, type=:AUTO
|
114
|
+
if type == :AUTO
|
115
|
+
if v?
|
116
|
+
type = :STACK
|
117
|
+
else
|
118
|
+
type = :FLOW
|
119
|
+
end
|
120
|
+
end
|
121
|
+
_add type, c, which, weight
|
122
|
+
#return self # lets return component created for christ's sake and keep it simple
|
123
|
+
end
|
124
|
+
# set the weight of outer split
|
125
|
+
def weight(*val)
|
126
|
+
if val.empty?
|
127
|
+
return @weight
|
128
|
+
else
|
129
|
+
# raise ArgumentError
|
130
|
+
newval = val[0]
|
131
|
+
# this is since, using numeric multipliers he can go beyond, so lets give him the best
|
132
|
+
if val[0] < @min_weight
|
133
|
+
newval = @min_weight
|
134
|
+
elsif val[0] > @max_weight
|
135
|
+
newval = @max_weight
|
136
|
+
end
|
137
|
+
oldvalue = @weight
|
138
|
+
@weight = newval
|
139
|
+
# orientation can be nil, so we cannot calculate rc here
|
140
|
+
#if v?
|
141
|
+
#@rc = (@width * @weight).to_i
|
142
|
+
#else
|
143
|
+
#@rc = (@height * @weight).to_i
|
144
|
+
#end
|
145
|
+
@rc = nil # so recalculated in repaint
|
146
|
+
fire_property_change(:weight, oldvalue, @weight)
|
147
|
+
end
|
148
|
+
self
|
149
|
+
end
|
150
|
+
# stack components, one over another, useful in a vertical split
|
151
|
+
# @param [Widget] component
|
152
|
+
# @param [:FIRST :SECOND] first or second split
|
153
|
+
# @param [Float, nil, :AUTO] weight of object, nil for last will expand it to full
|
154
|
+
# :AUTO will give equal weight to all
|
155
|
+
def stack c, which, weight
|
156
|
+
_add :STACK, c, which, weight
|
157
|
+
#return self # lets return component created for christ's sake and keep it simple
|
158
|
+
end
|
159
|
+
# place components on right of previous. Useful in horizontal split
|
160
|
+
def flow c, which, weight
|
161
|
+
_add :FLOW, c, which, weight
|
162
|
+
#return self # lets return component created for christ's sake and keep it simple
|
163
|
+
end
|
164
|
+
private
|
165
|
+
def _add type, c, which, weight
|
166
|
+
raise ArgumentError, "Nil component passed to add" unless c
|
167
|
+
raise ArgumentError, "which must be :FIRST or :SECOND" if which != :FIRST && which != :SECOND
|
168
|
+
# trying out wt of 0 means it will see height of object and use that.
|
169
|
+
if weight.nil? || weight == :AUTO || (weight >= 0 && weight <= 1.0)
|
170
|
+
else
|
171
|
+
raise ArgumentError, "weight must be >0 and <=1.0 or nil or :AUTO"
|
172
|
+
end
|
173
|
+
if c.is_a? Widget
|
174
|
+
if c.form && c.form != @form
|
175
|
+
$log.debug " removing widget VIMSPLIT #{c.class} "
|
176
|
+
c.form.remove_widget c
|
177
|
+
c.form = nil
|
178
|
+
end
|
179
|
+
#$log.debug " XXXX VIM is a widget"
|
180
|
+
else
|
181
|
+
case c
|
182
|
+
when Array
|
183
|
+
lb = Listbox.new nil, :list => c , :name => "list#{@components.size}"
|
184
|
+
c = lb
|
185
|
+
when String
|
186
|
+
require 'rbcurse/core/widgets/rtextview'
|
187
|
+
lb = TextView.new nil, :name => "text#{@components.size}"
|
188
|
+
lb.set_content c
|
189
|
+
c = lb
|
190
|
+
when Hash
|
191
|
+
lb = Listbox.new nil, :list => c.keys , :name => "list#{@components.size}"
|
192
|
+
c = lb
|
193
|
+
when Variable
|
194
|
+
# TODO
|
195
|
+
else
|
196
|
+
if c == :grabbar || c == :divider
|
197
|
+
side = :bottom
|
198
|
+
case type
|
199
|
+
when :STACK
|
200
|
+
side = :bottom
|
201
|
+
when :FLOW
|
202
|
+
side = :left
|
203
|
+
end
|
204
|
+
c = Divider.new nil, :parent => @components.last, :side => side
|
205
|
+
c.focusable(false)
|
206
|
+
RubyCurses::FocusManager.add c
|
207
|
+
c.bind :DRAG_EVENT do |ev|
|
208
|
+
source = ev.source
|
209
|
+
case ev.type
|
210
|
+
when KEY_UP
|
211
|
+
# CHECK BOUNDS TODO
|
212
|
+
# TODO what about KEY_LEFT and RIGHT ?
|
213
|
+
if source.next_component && source.next_component.row > 1 && source.parent.height > 1
|
214
|
+
source.parent.height -= 1
|
215
|
+
source.next_component.height +=1
|
216
|
+
source.next_component.row -= 1
|
217
|
+
source.parent.repaint_required
|
218
|
+
source.next_component.repaint_required
|
219
|
+
source.parent.repaint
|
220
|
+
source.next_component.repaint
|
221
|
+
end
|
222
|
+
when KEY_DOWN
|
223
|
+
# CHECK BOUNDS TODO check with appemail.rb
|
224
|
+
if source.next_component && source.next_component.height > 1
|
225
|
+
source.parent.height += 1
|
226
|
+
source.next_component.height -=1
|
227
|
+
source.next_component.row += 1
|
228
|
+
source.parent.repaint_required
|
229
|
+
source.next_component.repaint_required
|
230
|
+
source.parent.repaint
|
231
|
+
source.next_component.repaint
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
c.parent_component = self
|
239
|
+
|
240
|
+
@components << c
|
241
|
+
if which == :FIRST
|
242
|
+
@c1 << c
|
243
|
+
else
|
244
|
+
@c2 << c
|
245
|
+
end
|
246
|
+
#@ch[c] = [which, type, weight]
|
247
|
+
@ch[c] = Split.new(which, type, weight)
|
248
|
+
@repaint_required = true
|
249
|
+
return c
|
250
|
+
end
|
251
|
+
public
|
252
|
+
def split_info_for(c = @current_component)
|
253
|
+
@ch[c]
|
254
|
+
end
|
255
|
+
# get the current split focus is on
|
256
|
+
# @return [:FIRST, :SECOND] which split are we on
|
257
|
+
def current_split
|
258
|
+
split_info_for(@current_component).which
|
259
|
+
end
|
260
|
+
# returns the other split.
|
261
|
+
def other_split
|
262
|
+
which = current_split
|
263
|
+
return which == :FIRST ? :SECOND : :FIRST
|
264
|
+
end
|
265
|
+
# returns list of components for FIRST or SECOND split
|
266
|
+
def components_for which
|
267
|
+
return which == :FIRST ? @c1 : @c2
|
268
|
+
end
|
269
|
+
|
270
|
+
public
|
271
|
+
# repaint object
|
272
|
+
# called by Form, and sometimes parent component (if not form).
|
273
|
+
def repaint
|
274
|
+
my_win = @form ? @form.window : @target_window
|
275
|
+
@graphic = my_win unless @graphic
|
276
|
+
raise " #{@name} NO GRAPHIC set as yet VIMSPLIT paint " unless @graphic
|
277
|
+
|
278
|
+
#return unless @repaint_required
|
279
|
+
@recalculate_splits = true if @rc.nil?
|
280
|
+
|
281
|
+
# if some major change has happened then repaint everything
|
282
|
+
if @repaint_required
|
283
|
+
$log.debug " VIM repaint graphic #{@graphic} "
|
284
|
+
print_borders unless @suppress_borders # do this once only, unless everything changes
|
285
|
+
r,c = rowcol
|
286
|
+
|
287
|
+
bordercolor = @border_color || $datacolor
|
288
|
+
borderatt = @border_attrib || Ncurses::A_NORMAL
|
289
|
+
|
290
|
+
|
291
|
+
@graphic.attron(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
|
292
|
+
|
293
|
+
## The following calculations are only calcing the 2 split areas
|
294
|
+
## and divider locations based on V or H and weight.
|
295
|
+
|
296
|
+
@gbwid ||= 0 # grabbar width
|
297
|
+
roffset = 1
|
298
|
+
loffset = 2
|
299
|
+
if @suppress_borders
|
300
|
+
loffset = roffset = 0
|
301
|
+
end
|
302
|
+
# vertical split
|
303
|
+
if v?
|
304
|
+
@rc ||= (@width * @weight).to_i
|
305
|
+
rc = @rc # divider location
|
306
|
+
$log.debug "SPLP #{@name} prtingign split vline divider 1, rc: #{rc}, h:#{@height} - 2 "
|
307
|
+
unless @vb # if grabbar not created
|
308
|
+
@gbwid = 1
|
309
|
+
_create_divider
|
310
|
+
else # created, so set it
|
311
|
+
@vb.row @row+roffset
|
312
|
+
@vb.col rc+@col
|
313
|
+
#@vb.repaint
|
314
|
+
end
|
315
|
+
#@graphic.mvvline(@row+1, rc+@col, 0, @height-2)
|
316
|
+
# TODO don;t keep recreating, if present, reset values
|
317
|
+
## calculate cordinated of both split areas/boxes
|
318
|
+
@c1rc = Coord.new(@row,@col, @height -0, rc-@gbwid)
|
319
|
+
@c2rc = Coord.new(@row,rc+@col+@gbwid,@height-0, @width - rc-@gbwid)
|
320
|
+
else # horizontal split
|
321
|
+
@rc ||= (@height * @weight).to_i
|
322
|
+
rc = @rc # dividers row col location
|
323
|
+
$log.debug "SPLP #{@name} prtingign split hline divider rc: #{rc} , 1 , w:#{@width} - 2"
|
324
|
+
unless @vb
|
325
|
+
@gbwid = 1
|
326
|
+
_create_divider
|
327
|
+
else
|
328
|
+
#@vb = Divider.new nil, :row => @row+rc-1, :col => @col+1, :length => @width-loffset, :side => :bottom
|
329
|
+
@vb.row @row+@rc-1
|
330
|
+
@vb.col @col+roffset
|
331
|
+
#@vb.repaint # getting wiped out by vimsplit ?
|
332
|
+
end
|
333
|
+
#@graphic.mvhline(rc+@row, @col+1, 0, @width-@internal_width)
|
334
|
+
#@neat = true
|
335
|
+
if @neat
|
336
|
+
a = 1
|
337
|
+
@c1rc = Coord.new(@row+a,@col+a, rc-a, @width-@internal_width)
|
338
|
+
@c2rc = Coord.new(@row+rc+a,@col+a, @height-rc-2, @width - @internal_width)
|
339
|
+
else
|
340
|
+
# flush against border
|
341
|
+
#@c1rc = Coord.new(@row,@col, @height -0, rc-@gbwid)
|
342
|
+
#@c2rc = Coord.new(@row,rc+@col+@gbwid,@height-0, @width - rc-@gbwid)
|
343
|
+
a = 0
|
344
|
+
@c1rc = Coord.new(@row,@col, rc-@gbwid, @width)
|
345
|
+
@c2rc = Coord.new(@row+rc, @col, @height-rc-@gbwid, @width)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
@graphic.attroff(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
|
349
|
+
@components.each { |e| e.repaint_all(true) }
|
350
|
+
$log.debug " XXX VIM REPAINT ALL "
|
351
|
+
# FIXME do this only once, or when major change happends, otherwise
|
352
|
+
# i cannot increase decrease size on user request.
|
353
|
+
recalculate_splits @_use_preferred_sizes if @recalculate_splits
|
354
|
+
# vimsplit often overwrites this while divider is being moved so we must
|
355
|
+
# again call it.
|
356
|
+
@vb.repaint if @vb
|
357
|
+
else
|
358
|
+
# only repaint those that are needing repaint
|
359
|
+
# 2010-09-22 18:09 its possible somenoe has updated an internal
|
360
|
+
# component, but this container does not know. So we've got to call
|
361
|
+
# repaint on all components, only those which are changed will
|
362
|
+
# actually be repainted
|
363
|
+
@components.each { |e| e.repaint }
|
364
|
+
end # if repaint_required
|
365
|
+
# NOTE: at present one cannot change from flow to stack inside a pane
|
366
|
+
|
367
|
+
@repaint_required = false
|
368
|
+
end
|
369
|
+
def v?
|
370
|
+
@orientation == :VERTICAL_SPLIT
|
371
|
+
end
|
372
|
+
def h?
|
373
|
+
!@orientation == :VERTICAL_SPLIT
|
374
|
+
end
|
375
|
+
# convert weight to height and length
|
376
|
+
# we should only do this once, or if major change
|
377
|
+
# otherwise changes that user may have effected in size will be lost
|
378
|
+
# NOTE: this resets all components to preferred weights (given when component was added.
|
379
|
+
# If user has resized components
|
380
|
+
# then those changes in size will be lost.
|
381
|
+
def reset_to_preferred_size
|
382
|
+
recalculate_splits use_preferred_sizes=true
|
383
|
+
end
|
384
|
+
def recalculate_splits use_preferred_sizes=false
|
385
|
+
# i've made it true so that moving the divider can recalculate all, otherwise
|
386
|
+
# testvimsplit was failing to recalc 2 lists. 2011-12-29
|
387
|
+
use_preferred_sizes=true
|
388
|
+
@recalculate_splits = false
|
389
|
+
[@c1,@c2].each_with_index do |c,i|
|
390
|
+
rca = @c1rc
|
391
|
+
if i == 1
|
392
|
+
#$log.debug " XXX VIM moving to second"
|
393
|
+
rca = @c2rc
|
394
|
+
end
|
395
|
+
totalw = 0 # accumulative weight
|
396
|
+
totalwd = 0 # accumulative weight for width (in case someone switches)
|
397
|
+
totalht = 0 # accumulative weight for height (in case someone switches)
|
398
|
+
sz = c.size
|
399
|
+
auto = 1.0/sz # even this is wrong since we have stacks and flows mixed
|
400
|
+
# calculate a more accurate auto than just an average
|
401
|
+
# SHIT this won't work since c contains flow and stacks, all objects
|
402
|
+
#used = 0.0
|
403
|
+
#usedct = 0
|
404
|
+
#c.each {|e| info = @ch[e]; wt = info.weight;
|
405
|
+
#if wt && wt != :AUTO
|
406
|
+
#used += wt
|
407
|
+
#usedct += 1
|
408
|
+
#end
|
409
|
+
#}
|
410
|
+
#if usedct > 0
|
411
|
+
#$log.debug "XXX: COMES HERE 1.0 - #{used} / #{sz} - #{usedct} "
|
412
|
+
#auto = (1.0 - used) / (sz - usedct)
|
413
|
+
#end
|
414
|
+
frem = srem = 0
|
415
|
+
c.each do |e|
|
416
|
+
r = rca.row
|
417
|
+
c = rca.col
|
418
|
+
info = @ch[e]
|
419
|
+
type = info.type
|
420
|
+
wt = info.weight
|
421
|
+
wt = auto if wt == :AUTO
|
422
|
+
e.row = r
|
423
|
+
if e.row <= @row
|
424
|
+
# TODO do something here !!
|
425
|
+
$log.warn "XXX: WARN VIMPSPLIT row #{e.row} going less than #{@row} "
|
426
|
+
end
|
427
|
+
e.col = c
|
428
|
+
if type == :STACK
|
429
|
+
# store actual weight that was calculated, so if user reduces or increases
|
430
|
+
# we can use this, although ... we have no method that uses actual weights
|
431
|
+
# NOTE: If calling program increases one comp's weight, will have to reduce other.
|
432
|
+
info.act_weight = wt
|
433
|
+
|
434
|
+
e.width = (rca.w * (1 - totalwd)).to_i
|
435
|
+
# recaclulate height only in this case, otherwise we will overwrite changes
|
436
|
+
# made by user
|
437
|
+
if use_preferred_sizes
|
438
|
+
if wt != 0
|
439
|
+
if wt
|
440
|
+
m = rca.h * wt
|
441
|
+
mf = m.floor
|
442
|
+
srem += (m - mf)
|
443
|
+
if srem >= 1
|
444
|
+
mf += 1
|
445
|
+
srem = 0
|
446
|
+
end
|
447
|
+
e.height = mf #((rca.h * wt).to_i)
|
448
|
+
else
|
449
|
+
a = 0
|
450
|
+
a = 1 if @suppress_borders
|
451
|
+
e.height = rca.h - rca.row + a # take exactly rows left
|
452
|
+
end
|
453
|
+
# else use its own height
|
454
|
+
end
|
455
|
+
end
|
456
|
+
$log.warn "XXX: WARN VIMSPLIT height = 0 " if e.height == 0
|
457
|
+
rca.row += e.height
|
458
|
+
totalht += wt if wt
|
459
|
+
else # FLOW
|
460
|
+
# TODO THIS PART AS PER ABOVE CASE , TO TEST
|
461
|
+
# this is a horizontal split or flow
|
462
|
+
info.act_weight = wt
|
463
|
+
#e.height = rca.h
|
464
|
+
e.height = (rca.h * (1- totalht)).to_i
|
465
|
+
if use_preferred_sizes
|
466
|
+
if wt != 0
|
467
|
+
if wt
|
468
|
+
m = rca.w * wt
|
469
|
+
mf = m.floor
|
470
|
+
frem += (m - mf)
|
471
|
+
if frem >= 1
|
472
|
+
mf += 1
|
473
|
+
frem = 0
|
474
|
+
end
|
475
|
+
e.width = mf # ((rca.w * wt).to_i)
|
476
|
+
else
|
477
|
+
a = 0
|
478
|
+
a = 1 if @suppress_borders
|
479
|
+
e.width = rca.w - rca.col + a # take exactly rows left
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
rca.col += e.width
|
484
|
+
totalwd += wt if wt
|
485
|
+
end
|
486
|
+
e.set_buffering(:target_window => @target_window || @form.window, :bottom => e.height-1, :right => e.width-1, :form => @form ) # removed on 2011-09-29
|
487
|
+
#$log.debug " XXXXX VIMS R #{@row} : #{e.row} C #{e.col} H #{e.height} W #{e.width} "
|
488
|
+
e.repaint
|
489
|
+
e._object_created = true # added 2010-09-16 13:02 now prop handlers can be fired
|
490
|
+
end
|
491
|
+
end
|
492
|
+
@_use_preferred_sizes = false
|
493
|
+
end
|
494
|
+
|
495
|
+
private
|
496
|
+
def print_borders
|
497
|
+
width = @width
|
498
|
+
height = @height-1 # 2010-01-04 15:30 BUFFERED HEIGHT
|
499
|
+
window = @graphic # 2010-01-04 12:37 BUFFERED
|
500
|
+
startcol = @col
|
501
|
+
startrow = @row
|
502
|
+
@color_pair = get_color($datacolor)
|
503
|
+
#$log.debug "rlistb #{name}: window.print_border #{startrow}, #{startcol} , h:#{height}, w:#{width} , @color_pair, @attr "
|
504
|
+
window.print_border startrow, startcol, height, width, @color_pair, @attr
|
505
|
+
print_title
|
506
|
+
end
|
507
|
+
def print_title
|
508
|
+
@graphic.printstring( @row, @col+(@width-@title.length)/2, @title, @color_pair, @title_attrib) unless @title.nil?
|
509
|
+
end
|
510
|
+
|
511
|
+
public
|
512
|
+
# called by parent or form, otherwise its private
|
513
|
+
def handle_key ch
|
514
|
+
$log.debug " VIMSPLIT handle_key #{ch} "
|
515
|
+
_multiplier = ($multiplier == 0 ? 1 : $multiplier )
|
516
|
+
if ch == KEY_TAB
|
517
|
+
#$log.debug " GOTO NEXT"
|
518
|
+
return goto_next_component
|
519
|
+
elsif ch == KEY_BTAB
|
520
|
+
return goto_prev_component
|
521
|
+
end
|
522
|
+
comp = @current_component
|
523
|
+
$log.debug " VIMSPL handle_k #{ch}: #{comp}"
|
524
|
+
if comp
|
525
|
+
ret = comp.handle_key(ch)
|
526
|
+
if ret != :UNHANDLED
|
527
|
+
comp.repaint # NOTE: if we don;t do this, then it won't get repainted. I will have to repaint ALL
|
528
|
+
# in repaint of this.
|
529
|
+
return ret
|
530
|
+
end
|
531
|
+
end
|
532
|
+
$log.debug "XXX VIM key unhandled by comp #{comp.name} "
|
533
|
+
case ch
|
534
|
+
when ?\C-c.getbyte(0)
|
535
|
+
$multiplier = 0
|
536
|
+
return 0
|
537
|
+
when ?0.getbyte(0)..?9.getbyte(0)
|
538
|
+
$log.debug " VIM coming here to set multiplier #{$multiplier} "
|
539
|
+
$multiplier *= 10 ; $multiplier += (ch-48)
|
540
|
+
return 0
|
541
|
+
end
|
542
|
+
ret = process_key ch, self
|
543
|
+
# allow user to map left and right if he wants
|
544
|
+
if ret == :UNHANDLED
|
545
|
+
case ch
|
546
|
+
when KEY_UP
|
547
|
+
# form will pick this up and do needful
|
548
|
+
return goto_prev_component #unless on_first_component?
|
549
|
+
when KEY_LEFT
|
550
|
+
# if i don't check for first component, key will go back to form,
|
551
|
+
# but not be processes. so focussed remain here, but be false.
|
552
|
+
# In case of returnign an unhandled TAB, on_leave will happen and cursor will move to
|
553
|
+
# previous component outside of this.
|
554
|
+
return goto_prev_component unless on_first_component?
|
555
|
+
when KEY_RIGHT
|
556
|
+
return goto_next_component #unless on_last_component?
|
557
|
+
when KEY_DOWN
|
558
|
+
return goto_next_component #unless on_last_component?
|
559
|
+
else
|
560
|
+
return :UNHANDLED
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
$multiplier = 0
|
565
|
+
return 0
|
566
|
+
end
|
567
|
+
# private
|
568
|
+
def on_enter
|
569
|
+
# TODO if BTAB the last comp
|
570
|
+
if $current_key == KEY_BTAB
|
571
|
+
# FIXME last is not focusable, then ??
|
572
|
+
@current_component = @components.last
|
573
|
+
else
|
574
|
+
@current_component = @components.first
|
575
|
+
end
|
576
|
+
$log.debug " VIM came to on_enter #{@current_component} "
|
577
|
+
set_form_row
|
578
|
+
end
|
579
|
+
def on_leave
|
580
|
+
super
|
581
|
+
end
|
582
|
+
def goto_next_component
|
583
|
+
if @current_component != nil
|
584
|
+
leave_current_component
|
585
|
+
if on_last_component?
|
586
|
+
return :UNHANDLED
|
587
|
+
end
|
588
|
+
@current_index = @components.index(@current_component)
|
589
|
+
index = @current_index + 1
|
590
|
+
index.upto(@components.length-1) do |i|
|
591
|
+
f = @components[i]
|
592
|
+
if f.focusable
|
593
|
+
@current_index = i
|
594
|
+
@current_component = f
|
595
|
+
return set_form_row
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
return :UNHANDLED
|
600
|
+
end
|
601
|
+
def goto_prev_component
|
602
|
+
if @current_component != nil
|
603
|
+
leave_current_component
|
604
|
+
if on_first_component?
|
605
|
+
return :UNHANDLED
|
606
|
+
end
|
607
|
+
@current_index = @components.index(@current_component)
|
608
|
+
index = @current_index -= 1
|
609
|
+
index.downto(0) do |i|
|
610
|
+
f = @components[i]
|
611
|
+
if f.focusable
|
612
|
+
@current_index = i
|
613
|
+
@current_component = f
|
614
|
+
return set_form_row
|
615
|
+
end
|
616
|
+
end
|
617
|
+
end
|
618
|
+
return :UNHANDLED
|
619
|
+
end
|
620
|
+
# private
|
621
|
+
def set_form_row
|
622
|
+
#return :UNHANDLED if @current_component.nil?
|
623
|
+
$log.debug " VIM on enter sfr #{@current_component} "
|
624
|
+
@current_component.on_enter
|
625
|
+
@current_component.set_form_col # XXX
|
626
|
+
@current_component.repaint
|
627
|
+
# XXX compo should do set_form_row and col if it has that
|
628
|
+
end
|
629
|
+
# private
|
630
|
+
def set_form_col
|
631
|
+
return if @current_component.nil?
|
632
|
+
$log.debug " #{@name} set_form_col calling sfc for #{@current_component.name} "
|
633
|
+
@current_component.set_form_col
|
634
|
+
end
|
635
|
+
# leave the component we are on.
|
636
|
+
# This should be followed by all containers, so that the on_leave action
|
637
|
+
# of earlier comp can be displayed, such as dimming components selections
|
638
|
+
def leave_current_component
|
639
|
+
@current_component.on_leave
|
640
|
+
# NOTE this is required, since repaint will just not happen otherwise
|
641
|
+
# Some components are erroneously repainting all, after setting this to true so it is
|
642
|
+
# working there.
|
643
|
+
@current_component.repaint_required true
|
644
|
+
$log.debug " after on_leave VIMS XXX #{@current_component.focussed} #{@current_component.name}"
|
645
|
+
@current_component.repaint
|
646
|
+
end
|
647
|
+
|
648
|
+
# is focus on first component
|
649
|
+
def on_first_component?
|
650
|
+
@current_component == @components.first
|
651
|
+
end
|
652
|
+
# is focus on last component
|
653
|
+
def on_last_component?
|
654
|
+
@current_component == @components.last
|
655
|
+
end
|
656
|
+
def goto_other_split
|
657
|
+
c = components_for(other_split)
|
658
|
+
leave_current_component
|
659
|
+
@current_component = c.first
|
660
|
+
set_form_row
|
661
|
+
end
|
662
|
+
# set focus on given component
|
663
|
+
# Sometimes you have the handle to component, and you want to move focus to it
|
664
|
+
def goto_component comp
|
665
|
+
return if comp == @current_component
|
666
|
+
leave_current_component
|
667
|
+
@current_component = comp
|
668
|
+
set_form_row
|
669
|
+
end
|
670
|
+
# decrease the weight of the split
|
671
|
+
def decrease_weight
|
672
|
+
_multiplier = ($multiplier == 0 ? 1 : $multiplier )
|
673
|
+
weight(weight - 0.05*_multiplier)
|
674
|
+
end
|
675
|
+
# increase the weight of the split
|
676
|
+
def increase_weight
|
677
|
+
_multiplier = ($multiplier == 0 ? 1 : $multiplier )
|
678
|
+
weight(weight + 0.05*_multiplier)
|
679
|
+
end
|
680
|
+
# FIXME - i can only reduce if i've increased
|
681
|
+
def decrease_current_component
|
682
|
+
info = split_info_for
|
683
|
+
#info.add_weight = 0 if info.add_weight.nil?
|
684
|
+
#if info.add_weight > 0.0
|
685
|
+
#info.add_weight = info.add_weight - 0.05
|
686
|
+
#end
|
687
|
+
e = ResizeEvent.new @current_component, :DECREASE
|
688
|
+
fire_handler :COMPONENT_RESIZE_EVENT, e
|
689
|
+
#@repaint_required = true
|
690
|
+
end
|
691
|
+
# fires handler to request app to resize component
|
692
|
+
# @param [:INCREASE, :DECREASE]
|
693
|
+
# @param [:HEIGHT, :WIDTH]
|
694
|
+
def resize_component incdec, hw #:nodoc:
|
695
|
+
type = incdec.to_s + '_' + hw.to_s
|
696
|
+
#info = split_info_for
|
697
|
+
#info.add_weight = 0 if info.add_weight.nil?
|
698
|
+
e = ResizeEvent.new @current_component, type.to_sym
|
699
|
+
fire_handler :COMPONENT_RESIZE_EVENT, e
|
700
|
+
#@repaint_required = true
|
701
|
+
end
|
702
|
+
# fires handler to request app to resize current component
|
703
|
+
#
|
704
|
+
def decrease_height
|
705
|
+
resize_component :DECREASE, :HEIGHT
|
706
|
+
end
|
707
|
+
# fires handler to request app to resize current component
|
708
|
+
def decrease_width
|
709
|
+
resize_component :DECREASE, :WIDTH
|
710
|
+
end
|
711
|
+
# fires handler to request app to resize current component
|
712
|
+
def increase_width
|
713
|
+
resize_component :INCREASE, :WIDTH
|
714
|
+
end
|
715
|
+
# fires handler to request app to resize current component
|
716
|
+
def increase_height
|
717
|
+
resize_component :INCREASE, :HEIGHT
|
718
|
+
end
|
719
|
+
def increase_current_component
|
720
|
+
info = split_info_for
|
721
|
+
#info.add_weight = 0 if info.add_weight.nil?
|
722
|
+
#if info.add_weight < 0.3
|
723
|
+
#info.add_weight = info.add_weight + 0.05
|
724
|
+
#end
|
725
|
+
e = ResizeEvent.new @current_component, :INCREASE
|
726
|
+
fire_handler :COMPONENT_RESIZE_EVENT, e
|
727
|
+
#@repaint_required = true
|
728
|
+
end
|
729
|
+
# calling application need to handle this, since it knows
|
730
|
+
# how many windows its has and what the user would mean
|
731
|
+
def expand # maximize
|
732
|
+
e = ResizeEvent.new @current_component, :EXPAND
|
733
|
+
fire_handler :COMPONENT_RESIZE_EVENT, e
|
734
|
+
end
|
735
|
+
# calling application need to handle this, since it knows
|
736
|
+
# how many windows its has and what the user would mean
|
737
|
+
def unexpand
|
738
|
+
e = ResizeEvent.new @current_component, :UNEXPAND
|
739
|
+
fire_handler :COMPONENT_RESIZE_EVENT, e
|
740
|
+
end
|
741
|
+
|
742
|
+
private
|
743
|
+
def _create_divider
|
744
|
+
return if @vb
|
745
|
+
roffset = 1
|
746
|
+
loffset = 2
|
747
|
+
if @suppress_borders
|
748
|
+
loffset = roffset = 0
|
749
|
+
end
|
750
|
+
rc = @rc
|
751
|
+
if v?
|
752
|
+
@vb = Divider.new nil, :row => @row+roffset, :col => rc+@col-1, :length => @height-loffset, :side => :right
|
753
|
+
else
|
754
|
+
@vb = Divider.new nil, :row => @row+rc-1, :col => @col+1, :length => @width-loffset, :side => :bottom
|
755
|
+
end
|
756
|
+
@vb.focusable(false)
|
757
|
+
RubyCurses::FocusManager.add @vb
|
758
|
+
@vb.parent_component = self
|
759
|
+
@components << @vb
|
760
|
+
@vb.set_buffering(:target_window => @target_window || @form.window, :form => @form ) # removed on 2011-09-29
|
761
|
+
@vb.bind :DRAG_EVENT do |ev|
|
762
|
+
if v?
|
763
|
+
case ev.type
|
764
|
+
when KEY_RIGHT
|
765
|
+
$log.debug "VIMSPLIT RIGHT "
|
766
|
+
if @rc < @width - 3
|
767
|
+
@recalculate_splits = true
|
768
|
+
@rc += 1
|
769
|
+
@repaint_required = true # WHY ! Did prop handler not fire ?
|
770
|
+
end
|
771
|
+
when KEY_LEFT
|
772
|
+
if @rc > 3
|
773
|
+
@recalculate_splits = true
|
774
|
+
@repaint_required = true
|
775
|
+
@rc -= 1
|
776
|
+
end
|
777
|
+
end
|
778
|
+
else
|
779
|
+
# horizontal
|
780
|
+
case ev.type
|
781
|
+
when KEY_DOWN
|
782
|
+
if @rc < @height - 3
|
783
|
+
@recalculate_splits = true
|
784
|
+
@rc += 1
|
785
|
+
@repaint_required = true # WHY ! Did prop handler not fire ?
|
786
|
+
end
|
787
|
+
when KEY_UP
|
788
|
+
if @rc > 3
|
789
|
+
@recalculate_splits = true
|
790
|
+
@repaint_required = true
|
791
|
+
@rc -= 1
|
792
|
+
end
|
793
|
+
end
|
794
|
+
end # v?
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
# ADD HERE ABOVe
|
799
|
+
end # class
|
800
|
+
end # module
|