rbcurse-experimental 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.markdown +75 -0
- data/VERSION +1 -0
- data/examples/teststackflow.rb +113 -0
- data/lib/rbcurse/experimental/widgets/directorylist.rb +467 -0
- data/lib/rbcurse/experimental/widgets/directorytree.rb +69 -0
- data/lib/rbcurse/experimental/widgets/masterdetail.rb +166 -0
- data/lib/rbcurse/experimental/widgets/multiform.rb +330 -0
- data/lib/rbcurse/experimental/widgets/resultsetbrowser.rb +281 -0
- data/lib/rbcurse/experimental/widgets/resultsettextview.rb +586 -0
- data/lib/rbcurse/experimental/widgets/rscrollform.rb +418 -0
- data/lib/rbcurse/experimental/widgets/stackflow.rb +478 -0
- data/lib/rbcurse/experimental/widgets/undomanager.rb +188 -0
- metadata +89 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rbcurse/core/widgets/rtree'
|
2
|
+
#require 'forwardable'
|
3
|
+
# we can extend from Tree but lets just try forwarding
|
4
|
+
module RubyCurses
|
5
|
+
# this class shows a tree of directories. Pressing ENTER expands or collapses
|
6
|
+
# the node. Pressing ENTER selects a node.
|
7
|
+
# Should we give options for displaying filenames also ? TODO
|
8
|
+
class DirectoryTree < Tree
|
9
|
+
attr_reader :selected_path
|
10
|
+
#@t = tree :data => model, :height => ht, :border_attrib => borderattrib, :suppress_borders => true
|
11
|
+
def _directories wd
|
12
|
+
d = Dir.new(wd)
|
13
|
+
ent = d.entries.reject{|e| !File.directory? File.join(wd,e)}
|
14
|
+
ent.delete(".");ent.delete("..")
|
15
|
+
return ent
|
16
|
+
end
|
17
|
+
|
18
|
+
def init_vars
|
19
|
+
super
|
20
|
+
|
21
|
+
one_key_selection = false
|
22
|
+
bind :TREE_WILL_EXPAND_EVENT do |node|
|
23
|
+
will_expand_action node
|
24
|
+
end
|
25
|
+
|
26
|
+
bind :TREE_SELECTION_EVENT do |ev|
|
27
|
+
selection_event ev
|
28
|
+
end
|
29
|
+
end # init_v
|
30
|
+
|
31
|
+
# populate this node with child directories
|
32
|
+
# this gives user application a chance to override or extend this action
|
33
|
+
def will_expand_action node
|
34
|
+
path = File.join(*node.user_object_path)
|
35
|
+
dirs = _directories path
|
36
|
+
ch = node.children
|
37
|
+
# add only children that may not be there
|
38
|
+
ch.each do |e|
|
39
|
+
o = e.user_object
|
40
|
+
if dirs.include? o
|
41
|
+
dirs.delete o
|
42
|
+
else
|
43
|
+
# delete this child since its no longer present TODO
|
44
|
+
end
|
45
|
+
end
|
46
|
+
node.add dirs
|
47
|
+
path_expanded path
|
48
|
+
end
|
49
|
+
# notify applications of path expanded so they may do any
|
50
|
+
# related action
|
51
|
+
# # NOTE: this is not the cleanest way, since you will need objects from your app
|
52
|
+
# scope here. User will have to add objects into the config hash after object creation
|
53
|
+
# and access them here. (See appdirtree.rb in examples)
|
54
|
+
def path_expanded path
|
55
|
+
end
|
56
|
+
def selection_event ev
|
57
|
+
if ev.state == :SELECTED
|
58
|
+
node = ev.node
|
59
|
+
path = File.join(*node.user_object_path)
|
60
|
+
@selected_path = path
|
61
|
+
selected_path_changed path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
# inform applications that path has changed
|
65
|
+
# gives the user application a place to effect changes elsewhere in app
|
66
|
+
def selected_path_changed path
|
67
|
+
end
|
68
|
+
end # class
|
69
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'rbcurse/extras/widgets/rvimsplit'
|
2
|
+
require 'forwardable'
|
3
|
+
# A convenience class that implements a 3 way Master Detail like form
|
4
|
+
# as in some email clients. See appemail.rb for usage.
|
5
|
+
# You may use this class or extend it. It takes care of expanding,
|
6
|
+
# increasing etc the 3 splits.
|
7
|
+
# This class is not fully tested beyond appemail.rb, and can change
|
8
|
+
# quite a bit. Users may want to copy this to prevent from major changes
|
9
|
+
# that could take place.
|
10
|
+
class MasterDetail < Widget
|
11
|
+
dsl_property :weight
|
12
|
+
attr_reader :vim # the vimsplit for any further configuration such as min_weight etc
|
13
|
+
extend Forwardable
|
14
|
+
def_delegators :@vim, :on_enter, :on_leave, :handle_key, :current_component
|
15
|
+
def initialize form, config={}, &block
|
16
|
+
@focusable = true
|
17
|
+
@height = Ncurses.LINES-2
|
18
|
+
@weight = 0.25
|
19
|
+
super
|
20
|
+
_create_vimsplit
|
21
|
+
init_vars
|
22
|
+
end
|
23
|
+
def init_vars #:nodoc:
|
24
|
+
@first_time = true
|
25
|
+
@repaint_required = true
|
26
|
+
end
|
27
|
+
def repaint
|
28
|
+
if @first_time
|
29
|
+
@first_time = nil
|
30
|
+
[@vim, @left, @right1, @right2].each { |e|
|
31
|
+
e.set_buffering(:target_window => @target_window || @form.window, :form => @form) # removed on 2011-09-29
|
32
|
+
}
|
33
|
+
end
|
34
|
+
@vim.repaint
|
35
|
+
end
|
36
|
+
# set the single component on the left side/pane, typically a +Listbox+.
|
37
|
+
# If an array is passed, the Listbox created is returned for further
|
38
|
+
# manipulation.
|
39
|
+
# @param [Widget] component to set on left
|
40
|
+
# @return [Widget] component added
|
41
|
+
def set_left_component comp, weight=nil
|
42
|
+
@left = @vim.add comp, :FIRST, weight
|
43
|
+
_add_component comp
|
44
|
+
@left
|
45
|
+
end
|
46
|
+
# set the first component on the right side/pane, typically a +Listbox+.
|
47
|
+
# @param [Widget] component to set on right
|
48
|
+
# @return [Widget] component added
|
49
|
+
def set_right_top_component comp, weight=0.5
|
50
|
+
@added_top = true
|
51
|
+
@right1 = @vim.add comp, :SECOND, weight
|
52
|
+
_add_component comp
|
53
|
+
@right1
|
54
|
+
end
|
55
|
+
# set the second component on the right side/pane, typically a
|
56
|
+
# +TextView+
|
57
|
+
# @param [Widget] component to set on right
|
58
|
+
# @return [Widget] component added
|
59
|
+
def set_right_bottom_component comp, weight=nil
|
60
|
+
raise "Please add top component first!" unless @added_top
|
61
|
+
# what if user gives in wrong order !!
|
62
|
+
@gb = @vim.add :divider, :SECOND, 0
|
63
|
+
@right2 = @vim.add comp, :SECOND, weight
|
64
|
+
@gb.next_component(@right2)
|
65
|
+
_add_component comp
|
66
|
+
@right2
|
67
|
+
end
|
68
|
+
def focus comp
|
69
|
+
case comp
|
70
|
+
when :left
|
71
|
+
@vim.goto_component @left
|
72
|
+
when :top_right
|
73
|
+
@vim.goto_component @right1
|
74
|
+
when :bottom_right
|
75
|
+
@vim.goto_component @right2
|
76
|
+
else
|
77
|
+
@vim.goto_component comp
|
78
|
+
end
|
79
|
+
end
|
80
|
+
private
|
81
|
+
# does nothing at present
|
82
|
+
def _add_component comp #:nodoc:
|
83
|
+
end
|
84
|
+
# creates a Vimplit containing 3 panes. Sets events in order to
|
85
|
+
# increase and decrease panes/windows.
|
86
|
+
def _create_vimsplit #:nodoc:
|
87
|
+
@vim = VimSplit.new nil, :row => @row, :col => @col, :width => @width, :height => @height, :weight => @weight, :orientation => :VERTICAL, :suppress_borders => true do |s|
|
88
|
+
s.parent_component = self
|
89
|
+
#s.target_window = @form.window
|
90
|
+
#s.add @left, :FIRST
|
91
|
+
#s.add @right1, :SECOND
|
92
|
+
#s.add @right2, :SECOND
|
93
|
+
s.bind :COMPONENT_RESIZE_EVENT do |e|
|
94
|
+
alert "masterdetail got a resize event #{e.type}, #{e.source} "
|
95
|
+
case e.type
|
96
|
+
when :INCREASE
|
97
|
+
case e.source
|
98
|
+
when @right2
|
99
|
+
increase_body
|
100
|
+
when @right1
|
101
|
+
increase_headers
|
102
|
+
when @left
|
103
|
+
alert "masterdetail left increase - not handled"
|
104
|
+
|
105
|
+
end
|
106
|
+
when :DECREASE
|
107
|
+
case e.source
|
108
|
+
when @right2
|
109
|
+
increase_headers
|
110
|
+
when @right1
|
111
|
+
increase_body
|
112
|
+
when @left
|
113
|
+
@left.width -= 1
|
114
|
+
@right2.col -=1
|
115
|
+
@right1.col -=1
|
116
|
+
@right1.width +=1
|
117
|
+
@right2.width +=1
|
118
|
+
@right2.repaint_required true
|
119
|
+
@right1.repaint_required true
|
120
|
+
@left.repaint_required true
|
121
|
+
alert "masterdetail left decrease"
|
122
|
+
end
|
123
|
+
when :EXPAND
|
124
|
+
case e.source
|
125
|
+
when @right2
|
126
|
+
h = 3
|
127
|
+
@right2.row(@right1.row + h)
|
128
|
+
oldh = @right1.height
|
129
|
+
@right1.height = h
|
130
|
+
@right1.current_index = 0
|
131
|
+
@right2.height += (oldh - h)
|
132
|
+
@right2.repaint_required true
|
133
|
+
@right1.repaint_required true
|
134
|
+
when @right1
|
135
|
+
h = 3
|
136
|
+
@right2.row(@right2.row + (@right2.height - 3))
|
137
|
+
oldh = @right2.height
|
138
|
+
@right2.height = h
|
139
|
+
#@right1.current_index = 0
|
140
|
+
@right1.height += (oldh - h)
|
141
|
+
@right2.repaint_required true
|
142
|
+
@right1.repaint_required true
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end # bind
|
146
|
+
end
|
147
|
+
end # def
|
148
|
+
# increase the top right pane and reduces lower one
|
149
|
+
# TODO: to take into account multiplier
|
150
|
+
def increase_headers #:nodoc:
|
151
|
+
@right2.row @right2.row()+1
|
152
|
+
@right1.height +=1
|
153
|
+
@right2.height -=1
|
154
|
+
@right2.repaint_required true
|
155
|
+
@right1.repaint_required true
|
156
|
+
end
|
157
|
+
# decrease the top right pane and increase lower one
|
158
|
+
# TODO: to take into account multiplier
|
159
|
+
def increase_body #:nodoc:
|
160
|
+
@right2.row @right2.row()-1
|
161
|
+
@right1.height -=1
|
162
|
+
@right2.height +=1
|
163
|
+
@right2.repaint_required true
|
164
|
+
@right1.repaint_required true
|
165
|
+
end
|
166
|
+
end # class
|
@@ -0,0 +1,330 @@
|
|
1
|
+
=begin
|
2
|
+
* Name: Multiform.rb
|
3
|
+
* Description View (cycle) multiple forms
|
4
|
+
* Author: rkumar (arunachalesha)
|
5
|
+
* file created 2011-10-17 8:18 PM
|
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
|
+
# Trying to implement TabbedPanes using a multiform approach, but no more windows
|
18
|
+
# or pads. Try to keep it as simple as possible
|
19
|
+
class MultiForm < Widget
|
20
|
+
dsl_accessor :title
|
21
|
+
|
22
|
+
|
23
|
+
def initialize form = nil, config={}, &block
|
24
|
+
@focusable = true
|
25
|
+
@window = form.window
|
26
|
+
@row_offset = @col_offset = 1
|
27
|
+
@bmanager = BufferManager.new self
|
28
|
+
@forms = []
|
29
|
+
super
|
30
|
+
init_vars
|
31
|
+
|
32
|
+
end
|
33
|
+
def init_vars
|
34
|
+
super
|
35
|
+
# the following allows us to navigate buffers with :bn :bp etc (with Alt pressed)
|
36
|
+
bind_key(?\M-:, :buffer_menu)
|
37
|
+
bind_key(?\M-;, :buffer_menu)
|
38
|
+
# bind_key([?\C-x, ?f], :file_edit)
|
39
|
+
bind_key([?\C-x, ?k], :delete_component)
|
40
|
+
bind_key([?\C-x, ?\C-b], :list_components)
|
41
|
+
bind_key(?\M-n, :goto_next_component)
|
42
|
+
bind_key(?\M-p, :goto_prev_component)
|
43
|
+
bind_key(?\M-1, :goto_first_component)
|
44
|
+
# easily cycle using p. n is used for next search.
|
45
|
+
#bind_key(?p, :buffer_previous)
|
46
|
+
@suppress_borders = false
|
47
|
+
@repaint_all = true
|
48
|
+
@name ||= "multiform"
|
49
|
+
end
|
50
|
+
## returns current buffer
|
51
|
+
# @return [RBuffer] current buffer
|
52
|
+
def current_component
|
53
|
+
@bmanager.current
|
54
|
+
end
|
55
|
+
##
|
56
|
+
# multi-container
|
57
|
+
def handle_key ch #:nodoc:
|
58
|
+
@current_component.repaint
|
59
|
+
@current_component.window.wrefresh
|
60
|
+
$log.debug " MULTI handle_key #{ch}, #{@current_component}"
|
61
|
+
ret = :UNHANDLED
|
62
|
+
return :UNHANDLED unless @current_component
|
63
|
+
ret = @current_component.handle_key(ch)
|
64
|
+
$log.debug " MULTI comp #{@current_component} returned #{ret} "
|
65
|
+
if ret == :UNHANDLED
|
66
|
+
# check for bindings, these cannot override above keys since placed at end
|
67
|
+
begin
|
68
|
+
ret = process_key ch, self
|
69
|
+
$log.debug " MULTI = process_key returned #{ret} "
|
70
|
+
if ch > 177 && ch < 187
|
71
|
+
n = ch - 177
|
72
|
+
component_at(n)
|
73
|
+
# go to component n
|
74
|
+
end
|
75
|
+
rescue => err
|
76
|
+
# $error_message = err # changed 2010 dts
|
77
|
+
$error_message.value = err.to_s
|
78
|
+
#@form.window.print_error_message PLEASE CREATE LABEL
|
79
|
+
$log.error " Multicomponent process_key #{err} "
|
80
|
+
$log.debug(err.backtrace.join("\n"))
|
81
|
+
alert err.to_s
|
82
|
+
end
|
83
|
+
return :UNHANDLED if ret == :UNHANDLED
|
84
|
+
end
|
85
|
+
@current_component.repaint
|
86
|
+
@current_component.window.wrefresh
|
87
|
+
FFI::NCurses.update_panels
|
88
|
+
|
89
|
+
# check for any keys not handled and check our own ones
|
90
|
+
return ret #
|
91
|
+
end
|
92
|
+
def repaint
|
93
|
+
print_border if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
|
94
|
+
return unless @current_component
|
95
|
+
$log.debug " MULTIFORM REPAINT "
|
96
|
+
ret = @current_component.repaint
|
97
|
+
end
|
98
|
+
def print_border #:nodoc:
|
99
|
+
$log.debug " #{@name} print_borders, #{@graphic.name} "
|
100
|
+
color = $datacolor
|
101
|
+
@graphic.print_border_only @row, @col, @height-1, @width, color #, Ncurses::A_REVERSE
|
102
|
+
print_title
|
103
|
+
end
|
104
|
+
def print_title #:nodoc:
|
105
|
+
$log.debug " print_title #{@row}, #{@col}, #{@width} #{@title} "
|
106
|
+
@graphic.printstring( @row, @col+(@width-@title.length)/2, @title, $datacolor, @title_attrib) unless @title.nil?
|
107
|
+
end
|
108
|
+
# this is just a test of the simple "most" menu
|
109
|
+
# can use this for next, prev, first, last, new, delete, overwrite etc
|
110
|
+
def buffer_menu
|
111
|
+
menu = PromptMenu.new self
|
112
|
+
menu.add(menu.create_mitem( 'l', "list buffers", "list buffers ", :list_components ))
|
113
|
+
item = menu.create_mitem( 'b', "Buffer Options", "Buffer Options" )
|
114
|
+
menu1 = PromptMenu.new( self, "Buffer Options")
|
115
|
+
menu1.add(menu1.create_mitem( 'n', "Next", "Switched to next buffer", :goto_next_component ))
|
116
|
+
menu1.add(menu1.create_mitem( 'p', "Prev", "Switched to previous buffer", :goto_prev_component ))
|
117
|
+
menu1.add(menu1.create_mitem( 'f', "First", "Switched to first buffer", :goto_first_component ))
|
118
|
+
menu1.add(menu1.create_mitem( 'l', "Last", "Switched to last buffer", :goto_last_component ))
|
119
|
+
menu1.add(menu1.create_mitem( 'd', "Delete", "Deleted buffer", :delete_component ))
|
120
|
+
item.action = menu1
|
121
|
+
menu.add(item)
|
122
|
+
# how do i know what's available. the application or window should know where to place
|
123
|
+
menu.display @form.window, $error_message_row, $error_message_col, $datacolor #, menu
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def goto_next_component
|
128
|
+
perror "No other buffer" and return if @bmanager.size < 2
|
129
|
+
|
130
|
+
@current_component = @bmanager.next
|
131
|
+
set_current_component
|
132
|
+
# set_form_row and shit
|
133
|
+
end
|
134
|
+
|
135
|
+
def goto_prev_component
|
136
|
+
perror "No other buffer" and return if @bmanager.size < 2
|
137
|
+
|
138
|
+
@current_component = @bmanager.previous
|
139
|
+
$log.debug " buffer_prev got #{@current_component} "
|
140
|
+
set_current_component
|
141
|
+
end
|
142
|
+
def goto_first_component
|
143
|
+
@current_component = @bmanager.first
|
144
|
+
$log.debug " buffer_first got #{@current_component} "
|
145
|
+
set_current_component
|
146
|
+
end
|
147
|
+
def goto_last_component
|
148
|
+
@current_component = @bmanager.last
|
149
|
+
$log.debug " buffer_last got #{@current_component} "
|
150
|
+
set_current_component
|
151
|
+
end
|
152
|
+
def delete_component
|
153
|
+
if @bmanager.size > 1
|
154
|
+
@bmanager.delete_at
|
155
|
+
@current_component = @bmanager.previous
|
156
|
+
set_current_component
|
157
|
+
else
|
158
|
+
perror "Only one buffer. Cannot delete."
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def component_at index
|
163
|
+
cc = @bmanager.element_at index
|
164
|
+
return unless cc
|
165
|
+
@current_component = cc
|
166
|
+
#$log.debug " buffer_last got #{@current_component} "
|
167
|
+
set_current_component
|
168
|
+
end
|
169
|
+
def add_form title, config={}, &blk
|
170
|
+
$log.debug "XXX: add_form window coords were hwtl #{@height} , #{@width} , #{@top} , #{@left} "
|
171
|
+
#w = VER::Window.new 16, 30, 2, 2 #@height-1, @width-1, @top, @left
|
172
|
+
w = VER::Window.new @height-2, @width-2, @row+1, @col+1
|
173
|
+
#w.box(0,0)
|
174
|
+
frm = Form.new w
|
175
|
+
@forms << frm
|
176
|
+
frm.parent_form = @form
|
177
|
+
frm.add_cols=@col+@col_offset
|
178
|
+
frm.add_rows=@row+@row_offset
|
179
|
+
@current_component = @bmanager.add frm, title
|
180
|
+
set_current_component
|
181
|
+
yield frm if block_given?
|
182
|
+
return @current_component # not a form but a Rcomponent containing component and title
|
183
|
+
end
|
184
|
+
def _add_to(index, component)
|
185
|
+
raise ArgumentError, "index out of bounds" unless @forms[index]
|
186
|
+
component.set_form(@forms[index])
|
187
|
+
$log.debug "XXX: comp r c #{component.row} #{component.col} "
|
188
|
+
component.row += @row
|
189
|
+
component.col += @col
|
190
|
+
$log.debug "XXX: after comp r c #{component.row} #{component.col} "
|
191
|
+
end
|
192
|
+
##
|
193
|
+
# Add a component with a title
|
194
|
+
# @param [Widget] component
|
195
|
+
# @param [String] title
|
196
|
+
def add component, title
|
197
|
+
component.row = @row+@row_offset+0 # FFI changed 1 to 0 2011-09-12
|
198
|
+
component.col = @col+@col_offset+0 # FFI changed 1 to 0 2011-09-12
|
199
|
+
component.width = @width-2
|
200
|
+
component.height = @height-2
|
201
|
+
component.form = @form
|
202
|
+
component.override_graphic(@graphic)
|
203
|
+
@current_component = @bmanager.add component, title
|
204
|
+
set_current_component
|
205
|
+
set_form_row ## FFI added 2011-09-12 to get cursor at start when adding
|
206
|
+
$log.debug " ADD got cb : #{@current_component} "
|
207
|
+
end
|
208
|
+
def set_current_component
|
209
|
+
@title = @current_component.title
|
210
|
+
@current_component = @current_component.component
|
211
|
+
@current_component.repaint #2011-10-17 need to set all comps to repaint XXX
|
212
|
+
@current_component.window.wrefresh
|
213
|
+
@current_component.window.show
|
214
|
+
FFI::NCurses.update_panels
|
215
|
+
set_form_row
|
216
|
+
#@current_title = @current_component.title
|
217
|
+
#@current_component.repaint_all true 2011-10-17 need to set all comps to repaint XXX
|
218
|
+
end
|
219
|
+
def perror errmess
|
220
|
+
alert errmess
|
221
|
+
#@form.window.print_error_message errmess
|
222
|
+
end
|
223
|
+
def list_components
|
224
|
+
$log.debug " TODO buffers_list: #{@bmanager.size} "
|
225
|
+
menu = PromptMenu.new self
|
226
|
+
@bmanager.each_with_index{ |b, ix|
|
227
|
+
aproc = Proc.new { component_at(ix) }
|
228
|
+
name = b.title
|
229
|
+
num = ix + 1
|
230
|
+
menu.add(menu.create_mitem( num.to_s, name, "Switched to buffer #{ix}", aproc ))
|
231
|
+
}
|
232
|
+
menu.display @form.window, $error_message_row, $error_message_col, $datacolor
|
233
|
+
end
|
234
|
+
# required otherwise some components may not get correct cursor position on entry
|
235
|
+
# e.g. table
|
236
|
+
def on_enter
|
237
|
+
set_form_row # 2011-10-17
|
238
|
+
end
|
239
|
+
# nothing happening, the cursor goes to 1,1 and does not move
|
240
|
+
# alhough the fields can be edited XXX
|
241
|
+
def set_form_row #:nodoc:
|
242
|
+
if !@current_component.nil?
|
243
|
+
#$log.debug " #{@name} set_form_row calling sfr for #{@current_component.name} "
|
244
|
+
#fc = @current_component.widgets[0]
|
245
|
+
fc = @current_component.get_current_field
|
246
|
+
fc ||= @current_component.widgets[0]
|
247
|
+
fc.set_form_row if fc
|
248
|
+
#fc.set_form_col
|
249
|
+
end
|
250
|
+
end
|
251
|
+
# ADD HERE
|
252
|
+
end # class multicontainer
|
253
|
+
##
|
254
|
+
# Handles multiple buffers, navigation, maintenance etc
|
255
|
+
# Instantiated at startup of
|
256
|
+
#
|
257
|
+
class BufferManager
|
258
|
+
include Enumerable
|
259
|
+
def initialize source
|
260
|
+
@source = source
|
261
|
+
@buffers = [] # contains RBuffer
|
262
|
+
@counter = 0
|
263
|
+
# for each buffer i need to store data, current_index (row), curpos (col offset) and title (filename).
|
264
|
+
end
|
265
|
+
def element_at index
|
266
|
+
@buffers[index]
|
267
|
+
end
|
268
|
+
def each
|
269
|
+
@buffers.each {|k| yield(k)}
|
270
|
+
end
|
271
|
+
|
272
|
+
##
|
273
|
+
# @return [RBuffer] current buffer/file
|
274
|
+
##
|
275
|
+
def current
|
276
|
+
@buffers[@counter]
|
277
|
+
end
|
278
|
+
##
|
279
|
+
# Would have liked to just return next buffer and not get lost in details of caller
|
280
|
+
#
|
281
|
+
# @return [RBuffer] next buffer/file
|
282
|
+
##
|
283
|
+
def next
|
284
|
+
@counter += 1
|
285
|
+
@counter = 0 if @counter >= @buffers.size
|
286
|
+
@buffers[@counter]
|
287
|
+
end
|
288
|
+
##
|
289
|
+
# @return [RBuffer] previous buffer/file
|
290
|
+
##
|
291
|
+
def previous
|
292
|
+
$log.debug " previous bs: #{@buffers.size}, #{@counter} "
|
293
|
+
@counter -= 1
|
294
|
+
return last() if @counter < 0
|
295
|
+
$log.debug " previous ctr #{@counter} "
|
296
|
+
@buffers[@counter]
|
297
|
+
end
|
298
|
+
def first
|
299
|
+
@counter = 0
|
300
|
+
@buffers[@counter]
|
301
|
+
end
|
302
|
+
def last
|
303
|
+
@counter = @buffers.size - 1
|
304
|
+
@buffers[@counter]
|
305
|
+
end
|
306
|
+
##
|
307
|
+
def delete_at index=@counter
|
308
|
+
@buffers.delete_at index
|
309
|
+
end
|
310
|
+
def delete_by_name name
|
311
|
+
@buffers.delete_if {|b| b.filename == name }
|
312
|
+
end
|
313
|
+
def insert component, position, title=nil
|
314
|
+
anew = RComponents.new(component, title)
|
315
|
+
@buffers.insert position, anew
|
316
|
+
@counter = position
|
317
|
+
return anew
|
318
|
+
end
|
319
|
+
def add component, title=nil
|
320
|
+
#$log.debug " ADD H: #{component.height} C: #{component.width} "
|
321
|
+
insert component, @buffers.size, title
|
322
|
+
end
|
323
|
+
def size
|
324
|
+
@buffers.size
|
325
|
+
end
|
326
|
+
alias :count :size
|
327
|
+
end
|
328
|
+
RComponents = Struct.new(:component, :title)
|
329
|
+
|
330
|
+
end # modul
|