rbcurse 1.1.5 → 1.2.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +45 -0
- data/Makefile +1 -1
- data/Manifest.txt +91 -0
- data/NOTES +349 -2
- data/README.markdown +12 -0
- data/VERSION +1 -1
- data/examples/abasiclist.rb +25 -0
- data/examples/alpmenu.rb +42 -0
- data/examples/app.rb +883 -0
- data/examples/appcombo.rb +17 -0
- data/examples/appdirtree.rb +73 -0
- data/examples/appemail.rb +164 -0
- data/examples/appemaillb.rb +308 -0
- data/examples/appgcompose.rb +303 -0
- data/examples/appgmail.rb +951 -0
- data/examples/atree.rb +56 -0
- data/examples/dirtree.rb +78 -0
- data/examples/focusmanager.rb +31 -0
- data/examples/imap.rb +48 -0
- data/examples/menu1.rb +79 -0
- data/examples/multispl.rb +86 -0
- data/examples/rfe.rb +3 -4
- data/examples/rmail.rb +188 -0
- data/examples/s.rb +10 -0
- data/examples/scrollbar.rb +104 -0
- data/examples/splitp.rb +56 -0
- data/examples/table1.rb +30 -0
- data/examples/term.rb +48 -0
- data/examples/term2.rb +54 -0
- data/examples/test1.rb +4 -2
- data/examples/test2.rb +9 -9
- data/examples/testapp.rb +44 -0
- data/examples/testapp2.rb +51 -0
- data/examples/testcombo.rb +2 -2
- data/examples/testgmail.rb +46 -0
- data/examples/testlistbox.rb +0 -1
- data/examples/testmultispl.rb +199 -0
- data/examples/testree.rb +127 -0
- data/examples/testscroller.rb +0 -1
- data/examples/testscrolllb.rb +1 -1
- data/examples/testscrollp.rb +2 -1
- data/examples/testscrollta.rb +1 -1
- data/examples/testscrolltable.rb +1 -2
- data/examples/testsplit.rb +1 -1
- data/examples/testsplit2.rb +1 -1
- data/examples/testsplit3.rb +1 -1
- data/examples/testsplit3_1.rb +1 -1
- data/examples/testsplit3a.rb +1 -1
- data/examples/testsplit3b.rb +1 -1
- data/examples/testsplitta.rb +1 -1
- data/examples/testsplittv.rb +1 -1
- data/examples/testsplittvv.rb +1 -1
- data/examples/testtodo.rb +491 -488
- data/examples/testvimsplit.rb +111 -0
- data/examples/todo.db +0 -0
- data/examples/todocsv.csv +28 -0
- data/examples/viewtodo.rb +408 -403
- data/lib/rbcurse/action.rb +1 -0
- data/lib/rbcurse/app.rb +1294 -0
- data/lib/rbcurse/applicationheader.rb +7 -2
- data/lib/rbcurse/checkboxcellrenderer.rb +0 -12
- data/lib/rbcurse/colormap.rb +34 -8
- data/lib/rbcurse/comboboxcellrenderer.rb +0 -11
- data/lib/rbcurse/defaultlistselectionmodel.rb +23 -7
- data/lib/rbcurse/extras/bottomline.rb +1681 -0
- data/lib/rbcurse/extras/directorylist.rb +445 -0
- data/lib/rbcurse/extras/directorytree.rb +69 -0
- data/lib/rbcurse/extras/divider.rb +310 -0
- data/lib/rbcurse/extras/focusmanager.rb +31 -0
- data/lib/rbcurse/extras/listselectable.rb +222 -0
- data/lib/rbcurse/extras/masterdetail.rb +164 -0
- data/lib/rbcurse/extras/menutree.rb +63 -0
- data/lib/rbcurse/extras/rlink.rb +27 -0
- data/lib/rbcurse/extras/rmenulink.rb +21 -0
- data/lib/rbcurse/extras/scrollbar.rb +134 -0
- data/lib/rbcurse/extras/stdscrwindow.rb +247 -0
- data/lib/rbcurse/extras/tabular.rb +258 -0
- data/lib/rbcurse/extras/tabularwidget.rb +1070 -0
- data/lib/rbcurse/extras/viewer.rb +106 -0
- data/lib/rbcurse/io.rb +137 -80
- data/lib/rbcurse/keylabelprinter.rb +4 -0
- data/lib/rbcurse/listcellrenderer.rb +91 -59
- data/lib/rbcurse/listscrollable.rb +93 -95
- data/lib/rbcurse/listselectable.rb +60 -7
- data/lib/rbcurse/ractionevent.rb +67 -0
- data/lib/rbcurse/rbasiclistbox.rb +688 -0
- data/lib/rbcurse/rcombo.rb +5 -5
- data/lib/rbcurse/rcommandwindow.rb +555 -0
- data/lib/rbcurse/rinputdataevent.rb +12 -0
- data/lib/rbcurse/rlistbox.rb +305 -124
- data/lib/rbcurse/rmenu.rb +99 -46
- data/lib/rbcurse/rmessagebox.rb +13 -6
- data/lib/rbcurse/rmulticontainer.rb +54 -93
- data/lib/rbcurse/rmultisplit.rb +731 -0
- data/lib/rbcurse/rmultitextview.rb +3 -2
- data/lib/rbcurse/rpopupmenu.rb +0 -1
- data/lib/rbcurse/rprogress.rb +117 -0
- data/lib/rbcurse/rscrollpane.rb +2 -1
- data/lib/rbcurse/rsplitpane.rb +94 -20
- data/lib/rbcurse/rsplitpane2.rb +1009 -0
- data/lib/rbcurse/rtabbedpane.rb +3 -2
- data/lib/rbcurse/rtabbedwindow.rb +0 -1
- data/lib/rbcurse/rtable.rb +92 -64
- data/lib/rbcurse/rtextarea.rb +91 -57
- data/lib/rbcurse/rtextview.rb +223 -70
- data/lib/rbcurse/rtree.rb +723 -0
- data/lib/rbcurse/rviewport.rb +2 -1
- data/lib/rbcurse/rvimsplit.rb +768 -0
- data/lib/rbcurse/rwidget.rb +524 -325
- data/lib/rbcurse/table/tablecellrenderer.rb +1 -1
- data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -1
- data/lib/rbcurse/tree/treecellrenderer.rb +137 -0
- data/lib/rbcurse/tree/treemodel.rb +428 -0
- data/lib/rbcurse/vieditable.rb +14 -13
- data/lib/ver/ncurses.rb +6 -0
- data/lib/ver/window.rb +67 -32
- metadata +99 -23
- data/bin/rbcurse +0 -0
- data/examples/rvimsplit.rb +0 -376
- data/examples/todo.rb +0 -1
- data/lib/rbcurse/rform.rb +0 -845
- data/lib/rbcurse/selectable.rb +0 -94
- data/rbcurse.gemspec +0 -188
@@ -0,0 +1,445 @@
|
|
1
|
+
require 'rbcurse'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'rbcurse/rlistbox'
|
4
|
+
require 'rbcurse/vieditable'
|
5
|
+
require 'rbcurse/undomanager'
|
6
|
+
##
|
7
|
+
# Created on : Wed Sep 22 22:30:13 IST 2010
|
8
|
+
# (c) rkumar (arunachalesha)
|
9
|
+
#
|
10
|
+
module RubyCurses
|
11
|
+
# Display a directory listing, allowing user to drill down on pressing Enter
|
12
|
+
# on a directory, or sort when pressing enter on header row.
|
13
|
+
class DirectoryList < Listbox
|
14
|
+
|
15
|
+
include ViEditable
|
16
|
+
|
17
|
+
def initialize form, config={}, &block
|
18
|
+
@hide_dot_files = false
|
19
|
+
@hide_others = false
|
20
|
+
@curpos = 0
|
21
|
+
super
|
22
|
+
|
23
|
+
#@current_path ||= Dir.getwd # setting it causes selection not to fire if same one
|
24
|
+
# is selected first
|
25
|
+
@_header_array = [ "Attr", "Size", "Modified" , "Name" , "<Order_by_Extension>" ]
|
26
|
+
@_header = " %s %8s %19s %s %s " % @_header_array
|
27
|
+
end
|
28
|
+
def init_vars
|
29
|
+
# which rows are not data, thus don't fire, or give error
|
30
|
+
@_non_data_indices = []
|
31
|
+
@_header_row_index = 0
|
32
|
+
@_first_data_index = 1
|
33
|
+
@one_key_selection = false # this allows us to map keys to methods
|
34
|
+
vieditable_init_listbox
|
35
|
+
undom = SimpleUndo.new self
|
36
|
+
bind_key(?\M-h, :scroll_left)
|
37
|
+
bind_key(?\M-l, :scroll_right)
|
38
|
+
bind_key(KEY_RIGHT, :cursor_forward)
|
39
|
+
bind_key(KEY_LEFT, :cursor_backward)
|
40
|
+
bind_key(?$, :end_of_line)
|
41
|
+
bind_key(?\C-e, :end_of_line)
|
42
|
+
bind_key(?\C-a, :start_of_line)
|
43
|
+
bind_key(?a, :select_all)
|
44
|
+
bind_key(?*, :invert_selection)
|
45
|
+
bind_key(?u, :clear_selection)
|
46
|
+
bind_key(?+, :ask_select)
|
47
|
+
bind_key(?-, :ask_unselect)
|
48
|
+
bind_key(?I) { @hide_dot_files = !@hide_dot_files; prune_entries; }
|
49
|
+
super
|
50
|
+
end
|
51
|
+
# changing the current path, refreshes files
|
52
|
+
def current_path(*val)
|
53
|
+
if val.empty?
|
54
|
+
return @current_path
|
55
|
+
else
|
56
|
+
raise ArgumentError, "current_path should be a directory:#{val[0]}." unless File.directory? val[0]
|
57
|
+
oldvalue = @current_path
|
58
|
+
if oldvalue != val[0]
|
59
|
+
@current_path = val[0]
|
60
|
+
populate @current_path
|
61
|
+
fire_property_change(:current_path, oldvalue, @current_path)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
# populate the list with file names
|
67
|
+
# @param [String, Array] string is the path name to populate with
|
68
|
+
# Array is a list of files
|
69
|
+
def populate path
|
70
|
+
case path
|
71
|
+
when String
|
72
|
+
@current_path = path
|
73
|
+
@entries = Dir.new(path).entries
|
74
|
+
@entries.delete(".")
|
75
|
+
# isn;t it a bit late here. it needs to happen to what's already there
|
76
|
+
@entries.delete_if {|x| x =~ /^\./} if @hide_dot_files
|
77
|
+
@entries.delete_if {|x| x =~ /\.bak$/ || x=~/\.swp$/} if @hide_others
|
78
|
+
when Array
|
79
|
+
path = @current_path
|
80
|
+
# we've been passed @entries so we don't need to put it again ??? XXX
|
81
|
+
end
|
82
|
+
# TODO K M etc
|
83
|
+
list @entries
|
84
|
+
@list.insert 0, @_header
|
85
|
+
@title = @current_path
|
86
|
+
@current_index = @_first_data_index
|
87
|
+
end
|
88
|
+
# called by parent's repaint
|
89
|
+
def convert_value_to_text file, crow
|
90
|
+
if @short
|
91
|
+
file
|
92
|
+
else
|
93
|
+
if crow == @_header_row_index
|
94
|
+
return file
|
95
|
+
else
|
96
|
+
# OUCH i don't know if its a header !!
|
97
|
+
fullname = File.join(@current_path, file)
|
98
|
+
fname = file
|
99
|
+
stat = File::Stat.new fullname
|
100
|
+
time = stat.mtime.to_s[0..18]
|
101
|
+
attr = stat.directory? ? "d" : "-"
|
102
|
+
attr << (stat.writable? ? "w" : "-")
|
103
|
+
attr << (stat.readable? ? "r" : "-")
|
104
|
+
attr << (stat.executable? ? "x" : "-")
|
105
|
+
fname << "/" if stat.directory? && fname[-1] != "/"
|
106
|
+
value = " %s %8d %s %s" % [attr, stat.size, time, fname]
|
107
|
+
return value
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def ___create_default_cell_renderer
|
113
|
+
cell_renderer( RubyCurses::DirectoryListCellRenderer.new "", {:color=>@color, :bgcolor=>@bgcolor, :parent => self, :display_length=> @width-2-@left_margin})
|
114
|
+
end
|
115
|
+
def _get_word_under_cursor line=@_header, pos=@curpos
|
116
|
+
finish = line.index(" ", pos)
|
117
|
+
start = line.rindex(" ",pos)
|
118
|
+
finish = -1 if finish.nil?
|
119
|
+
start = 0 if start.nil?
|
120
|
+
return line[start..finish]
|
121
|
+
end
|
122
|
+
# sorts entries by various parameters.
|
123
|
+
# Not optimal since it creates file stat objects each time rather than cacheing, but this is a demo of widgets
|
124
|
+
# not a real directory lister!
|
125
|
+
def sort_by key, reverse=false
|
126
|
+
# remove parent before sorting, keep at top
|
127
|
+
first = @entries.delete_at(0) if @entries[0]==".."
|
128
|
+
#key ||= @sort_key
|
129
|
+
sort_keys = { 'Name' => :name, 'Modified' => :mtime, "Size" => :size, "<Order_by_Extension>" => :ext, 'Attr' => :attr, "Accessed" => :atime }
|
130
|
+
key = sort_keys[key] if sort_keys.has_key? key
|
131
|
+
#if key == @sort_key
|
132
|
+
#reverse = true
|
133
|
+
#end
|
134
|
+
cdir=@current_path+"/"
|
135
|
+
case key
|
136
|
+
when :size
|
137
|
+
@entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
|
138
|
+
if reverse
|
139
|
+
xs.size <=> ys.size
|
140
|
+
else
|
141
|
+
ys.size <=> xs.size
|
142
|
+
end
|
143
|
+
}
|
144
|
+
when :mtime
|
145
|
+
@entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
|
146
|
+
if reverse
|
147
|
+
xs.mtime <=> ys.mtime
|
148
|
+
else
|
149
|
+
ys.mtime <=> xs.mtime
|
150
|
+
end
|
151
|
+
}
|
152
|
+
when :atime
|
153
|
+
@entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
|
154
|
+
if reverse
|
155
|
+
xs.atime <=> ys.atime
|
156
|
+
else
|
157
|
+
ys.atime <=> xs.atime
|
158
|
+
end
|
159
|
+
}
|
160
|
+
when :name
|
161
|
+
@entries.sort! {|x,y| x <=> y
|
162
|
+
if reverse
|
163
|
+
x <=> y
|
164
|
+
else
|
165
|
+
y <=> x
|
166
|
+
end
|
167
|
+
}
|
168
|
+
when :ext
|
169
|
+
@entries.sort! {|x,y|
|
170
|
+
if reverse
|
171
|
+
File.extname(cdir+x) <=> File.extname(cdir+y)
|
172
|
+
else
|
173
|
+
File.extname(cdir+y) <=> File.extname(cdir+x)
|
174
|
+
end
|
175
|
+
}
|
176
|
+
when :attr
|
177
|
+
@entries.sort! {|x,y| xs = File.stat(cdir+x); ys = File.stat(cdir+y);
|
178
|
+
x = xs.directory? ? "d" : "D"
|
179
|
+
y = ys.directory? ? "d" : "D"
|
180
|
+
if reverse
|
181
|
+
x <=> y
|
182
|
+
else
|
183
|
+
y <=> x
|
184
|
+
end
|
185
|
+
}
|
186
|
+
end
|
187
|
+
@sort_key = key
|
188
|
+
@entries.insert 0, first unless first.nil? # keep parent on top
|
189
|
+
populate @entries
|
190
|
+
end
|
191
|
+
GIGA_SIZE = 1073741824.0
|
192
|
+
MEGA_SIZE = 1048576.0
|
193
|
+
KILO_SIZE = 1024.0
|
194
|
+
|
195
|
+
# Return the file size with a readable style.
|
196
|
+
def readable_file_size(size, precision)
|
197
|
+
case
|
198
|
+
#when size == 1 : "1 B"
|
199
|
+
when size < KILO_SIZE then "%d B" % size
|
200
|
+
when size < MEGA_SIZE then "%.#{precision}f K" % (size / KILO_SIZE)
|
201
|
+
when size < GIGA_SIZE then "%.#{precision}f M" % (size / MEGA_SIZE)
|
202
|
+
else "%.#{precision}f G" % (size / GIGA_SIZE)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
def date_format t
|
206
|
+
t.strftime "%Y/%m/%d"
|
207
|
+
end
|
208
|
+
|
209
|
+
# on pressing Enter, execute this action.
|
210
|
+
# Here we take the current file and if its a directory, we step into it.
|
211
|
+
def fire_action_event
|
212
|
+
if @_non_data_indices.include? @current_index
|
213
|
+
Ncurses.error
|
214
|
+
return
|
215
|
+
end
|
216
|
+
if @_header_row_index == @current_index
|
217
|
+
# user hit enter on the header row. we determine column and sort.
|
218
|
+
header = _get_word_under_cursor
|
219
|
+
#@reverse = false
|
220
|
+
if header == @_last_header_sorted
|
221
|
+
@reverse = !@reverse # clicking 2 times won't reverse again
|
222
|
+
else
|
223
|
+
@reverse = false
|
224
|
+
end
|
225
|
+
sort_by header.strip, @reverse
|
226
|
+
@_last_header_sorted = header
|
227
|
+
return
|
228
|
+
end
|
229
|
+
value = current_value
|
230
|
+
value = value.split.last
|
231
|
+
if value == ".."
|
232
|
+
_path = File.dirname(@current_path)
|
233
|
+
else
|
234
|
+
_path = File.join(@current_path, value)
|
235
|
+
end
|
236
|
+
if File.directory? _path
|
237
|
+
populate _path
|
238
|
+
end
|
239
|
+
|
240
|
+
super
|
241
|
+
end
|
242
|
+
def addcol num
|
243
|
+
#@repaint_required = true
|
244
|
+
@repaint_footer_required = true # 2010-01-23 22:41
|
245
|
+
if @form
|
246
|
+
@form.addcol num
|
247
|
+
else
|
248
|
+
@parent_component.form.addcol num
|
249
|
+
end
|
250
|
+
end
|
251
|
+
# set cursor column position
|
252
|
+
# if i set col1 to @curpos, i can move around left right if key mapped
|
253
|
+
def set_form_col col1=@curpos
|
254
|
+
col1 ||= 0
|
255
|
+
@cols_panned ||= 0 # RFED16 2010-02-17 23:40
|
256
|
+
win_col = 0 # 2010-02-17 23:19 RFED16
|
257
|
+
col2 = win_col + @col + @col_offset + col1 + @cols_panned + @left_margin
|
258
|
+
setrowcol nil, col2 # 2010-02-17 23:19 RFED16
|
259
|
+
end
|
260
|
+
def start_of_line
|
261
|
+
@repaint_required = true if @pcol > 0 # tried other things but did not work
|
262
|
+
set_form_col 0
|
263
|
+
@pcol = 0
|
264
|
+
end
|
265
|
+
# this does not work, since the value in list is not the printed value
|
266
|
+
def end_of_line
|
267
|
+
blen = current_value.rstrip.length
|
268
|
+
set_form_col blen
|
269
|
+
end
|
270
|
+
|
271
|
+
def cursor_backward
|
272
|
+
repeatm {
|
273
|
+
if @curpos > 0
|
274
|
+
@curpos -= 1
|
275
|
+
set_form_col
|
276
|
+
#addcol -1
|
277
|
+
elsif @pcol > 0
|
278
|
+
@pcol -= 1
|
279
|
+
end
|
280
|
+
}
|
281
|
+
#@repaint_required = true
|
282
|
+
@repaint_footer_required = true # 2010-01-23 22:41
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
def cursor_forward
|
287
|
+
@curpos ||= 0
|
288
|
+
maxlen = @maxlen || @width-2
|
289
|
+
repeatm {
|
290
|
+
if @curpos < @width and @curpos < maxlen-1 # else it will do out of box
|
291
|
+
@curpos += 1
|
292
|
+
addcol 1
|
293
|
+
else
|
294
|
+
#@pcol += 1 if @pcol <= @buffer.length
|
295
|
+
# buffer not eixstent FIXME
|
296
|
+
end
|
297
|
+
}
|
298
|
+
set_form_col
|
299
|
+
#@repaint_required = true
|
300
|
+
@repaint_footer_required = true # 2010-01-23 22:41
|
301
|
+
end
|
302
|
+
def [](index)
|
303
|
+
@entries[index]
|
304
|
+
end
|
305
|
+
|
306
|
+
@private
|
307
|
+
def longest_line=(l)
|
308
|
+
@longest_line = l
|
309
|
+
end
|
310
|
+
def longest_line
|
311
|
+
@longest_line
|
312
|
+
end
|
313
|
+
# modify a file name.
|
314
|
+
# call using 'C'
|
315
|
+
def edit_line lineno=@current_index
|
316
|
+
line = @list[lineno]
|
317
|
+
fullname = File.join(@current_path, line)
|
318
|
+
prompt = "Rename file [#{line}] to: "
|
319
|
+
maxlen = 80
|
320
|
+
config={};
|
321
|
+
oldline = line.dup
|
322
|
+
config[:default] = line
|
323
|
+
ret, str = rbgetstr(@form.window, $error_message_row, $error_message_col, prompt, maxlen, config)
|
324
|
+
$log.debug " rbgetstr returned #{ret} , #{str} "
|
325
|
+
return if ret != 0
|
326
|
+
@list[lineno].replace(str)
|
327
|
+
FileUtils.mv fullname, File.join(@current_path, str)
|
328
|
+
fire_handler :CHANGE, InputDataEvent.new(0,oldline.length, self, :DELETE_LINE, lineno, oldline)
|
329
|
+
fire_handler :CHANGE, InputDataEvent.new(0,str.length, self, :INSERT_LINE, lineno, str)
|
330
|
+
@repaint_required = true
|
331
|
+
end
|
332
|
+
def ask_select
|
333
|
+
prompt = "Select Files: "
|
334
|
+
maxlen = 80
|
335
|
+
config={}
|
336
|
+
config[:default] = @file_pattern if @file_pattern
|
337
|
+
ret, str = rbgetstr(@form.window, $error_message_row, $error_message_col, prompt, maxlen, config)
|
338
|
+
return if ret != 0
|
339
|
+
@file_pattern = str
|
340
|
+
values = Dir.glob(str)
|
341
|
+
select_values values unless values.empty?
|
342
|
+
@repaint_required = true
|
343
|
+
end
|
344
|
+
def ask_unselect
|
345
|
+
prompt = "Unselect Files: "
|
346
|
+
maxlen = 80
|
347
|
+
config={}
|
348
|
+
config[:default] = @file_pattern if @file_pattern
|
349
|
+
ret, str = rbgetstr(@form.window, $error_message_row, $error_message_col, prompt, maxlen, config)
|
350
|
+
return if ret != 0
|
351
|
+
@file_pattern = str
|
352
|
+
values = Dir.glob(str)
|
353
|
+
unselect_values values unless values.empty?
|
354
|
+
@repaint_required = true
|
355
|
+
end
|
356
|
+
def select_all
|
357
|
+
# don't select header row
|
358
|
+
add_row_selection_interval 1, row_count()
|
359
|
+
end
|
360
|
+
def invert_selection
|
361
|
+
1.upto(row_count()){|i| toggle_row_selection i }
|
362
|
+
end
|
363
|
+
# selects all rows with the values given, leaving existing selections
|
364
|
+
# intact
|
365
|
+
def select_values values
|
366
|
+
return unless values
|
367
|
+
values.each do |val|
|
368
|
+
row = @list.index val
|
369
|
+
add_row_selection_interval row, row unless row.nil?
|
370
|
+
end
|
371
|
+
end
|
372
|
+
# unselects all rows with the values given, leaving all other rows intact
|
373
|
+
def unselect_values values
|
374
|
+
return unless values
|
375
|
+
values.each do |val|
|
376
|
+
row = @list.index val
|
377
|
+
remove_row_selection_interval row, row unless row.nil?
|
378
|
+
end
|
379
|
+
end
|
380
|
+
private
|
381
|
+
# was meant to filter rows, but no point. since we can't undo the delete
|
382
|
+
# so we just call populate again. this method could get axed
|
383
|
+
def prune_entries
|
384
|
+
#@entries.delete_if {|x| x =~ /^\./} if @hide_dot_files
|
385
|
+
#@entries.delete_if {|x| x =~ /\.bak$/ || x=~/\.swp$/} if @hide_others
|
386
|
+
populate @current_path
|
387
|
+
set_form_row
|
388
|
+
end
|
389
|
+
##
|
390
|
+
end # class
|
391
|
+
|
392
|
+
##
|
393
|
+
# A cell renderer should not changed the length of a line otherwise scrolling etc goes for a toss.
|
394
|
+
# The calling repaint method does trimming.
|
395
|
+
#
|
396
|
+
# A cell renderer can do small modifications, or color changing to data.
|
397
|
+
# Here we should color directories or bak files or hidden files, swap files etc differently
|
398
|
+
# Should this class do the trimming of data, else its hard to figure out what the extension
|
399
|
+
# is if its trimeed out. But then it would have to handle the panning too.
|
400
|
+
require 'rbcurse/listcellrenderer'
|
401
|
+
class DirectoryListCellRenderer < ListCellRenderer
|
402
|
+
#def initialize text="", config={}, &block
|
403
|
+
#super
|
404
|
+
#end
|
405
|
+
# sets @color_pair and @attr
|
406
|
+
|
407
|
+
##
|
408
|
+
# paint a list box cell
|
409
|
+
# 2010-09-02 15:38 changed focussed to take true, false and :SOFT_FOCUS
|
410
|
+
# SOFT_FOCUS means the form focus is no longer on this field, but this row
|
411
|
+
# was focussed when use was last on this field. This row will take focus
|
412
|
+
# when field is focussed again
|
413
|
+
#
|
414
|
+
# @param [Buffer] window or buffer object used for printing
|
415
|
+
# @param [Fixnum] row
|
416
|
+
# @param [Fixnum] column
|
417
|
+
# @param [Fixnum] actual index into data, some lists may have actual data elsewhere and
|
418
|
+
# display data separate. e.g. rfe_renderer (directory listing)
|
419
|
+
# @param [String] text to print in cell
|
420
|
+
# @param [Boolean, :SOFT_FOCUS] cell focussed, not focussed, cell focussed but field is not focussed
|
421
|
+
# @param [Boolean] cell selected or not
|
422
|
+
def repaint graphic, r=@row,c=@col, row_index=-1,value=@text, focussed=false, selected=false
|
423
|
+
|
424
|
+
prepare_default_colors focussed, selected
|
425
|
+
if row_index == 0
|
426
|
+
#nvalue = " %s %8s %19s %s %s " % value.split(",")
|
427
|
+
graphic.printstring r, c, "%-s" % value, @color_pair,@attr
|
428
|
+
else
|
429
|
+
$log.debug " CELL XXX GTETING #{row_index} ,#{value}"
|
430
|
+
|
431
|
+
|
432
|
+
# ensure we do not exceed
|
433
|
+
if !@display_length.nil?
|
434
|
+
if value.length > @display_length
|
435
|
+
value = value[0..@display_length-1]
|
436
|
+
end
|
437
|
+
end
|
438
|
+
len = @display_length || value.length
|
439
|
+
graphic.printstring r, c, "%-*s" % [len, value], @color_pair,@attr
|
440
|
+
end
|
441
|
+
end
|
442
|
+
# ADD HERE
|
443
|
+
end
|
444
|
+
end # module
|
445
|
+
# set filetype=ruby
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rbcurse/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
|