rbcurse-experimental 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|