cdk 0.9.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.
- checksums.yaml +7 -0
- data/lib/cdk.rb +916 -0
- data/lib/cdk/alphalist.rb +562 -0
- data/lib/cdk/buttonbox.rb +354 -0
- data/lib/cdk/calendar.rb +770 -0
- data/lib/cdk/cdk_objs.rb +463 -0
- data/lib/cdk/dialog.rb +727 -0
- data/lib/cdk/display.rb +63 -0
- data/lib/cdk/draw.rb +233 -0
- data/lib/cdk/dscale.rb +13 -0
- data/lib/cdk/entry.rb +556 -0
- data/lib/cdk/fscale.rb +44 -0
- data/lib/cdk/fselect.rb +940 -0
- data/lib/cdk/fslider.rb +61 -0
- data/lib/cdk/histogram.rb +410 -0
- data/lib/cdk/itemlist.rb +475 -0
- data/lib/cdk/label.rb +207 -0
- data/lib/cdk/marquee.rb +241 -0
- data/lib/cdk/matrix.rb +1176 -0
- data/lib/cdk/mentry.rb +614 -0
- data/lib/cdk/menu.rb +448 -0
- data/lib/cdk/radio.rb +533 -0
- data/lib/cdk/scale.rb +525 -0
- data/lib/cdk/screen.rb +280 -0
- data/lib/cdk/scroll.rb +994 -0
- data/lib/cdk/scroller.rb +183 -0
- data/lib/cdk/selection.rb +619 -0
- data/lib/cdk/slider.rb +541 -0
- data/lib/cdk/swindow.rb +762 -0
- data/lib/cdk/template.rb +562 -0
- data/lib/cdk/traverse.rb +289 -0
- data/lib/cdk/uscale.rb +14 -0
- data/lib/cdk/uslider.rb +14 -0
- data/lib/cdk/viewer.rb +812 -0
- metadata +91 -0
data/lib/cdk/fscale.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative 'scale'
|
2
|
+
|
3
|
+
module CDK
|
4
|
+
class FSCALE < CDK::SCALE
|
5
|
+
def initialize(cdkscreen, xplace, yplace, title, label, field_attr,
|
6
|
+
field_width, start, low, high, inc, fast_inc, digits, box, shadow)
|
7
|
+
@digits = digits
|
8
|
+
super(cdkscreen, xplace, yplace, title, label, field_attr, field_width,
|
9
|
+
start, low, high, inc, fast_inc, box, shadow)
|
10
|
+
end
|
11
|
+
|
12
|
+
def drawField
|
13
|
+
@field_win.werase
|
14
|
+
|
15
|
+
# Draw the value in the field.
|
16
|
+
digits = [@digits, 30].min
|
17
|
+
format = '%%.%if' % [digits]
|
18
|
+
temp = format % [@current]
|
19
|
+
|
20
|
+
Draw.writeCharAttrib(@field_win,
|
21
|
+
@field_width - temp.size - 1, 0, temp, @field_attr,
|
22
|
+
CDK::HORIZONTAL, 0, temp.size)
|
23
|
+
|
24
|
+
self.moveToEditPosition(@field_edit)
|
25
|
+
@field_win.wrefresh
|
26
|
+
end
|
27
|
+
|
28
|
+
def setDigits(digits)
|
29
|
+
@digits = [0, digits].max
|
30
|
+
end
|
31
|
+
|
32
|
+
def getDigits
|
33
|
+
return @digits
|
34
|
+
end
|
35
|
+
|
36
|
+
def SCAN_FMT
|
37
|
+
'%g%c'
|
38
|
+
end
|
39
|
+
|
40
|
+
def object_type
|
41
|
+
:FSCALE
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/cdk/fselect.rb
ADDED
@@ -0,0 +1,940 @@
|
|
1
|
+
require_relative 'cdk_objs'
|
2
|
+
|
3
|
+
module CDK
|
4
|
+
class FSELECT < CDK::CDKOBJS
|
5
|
+
attr_reader :scroll_field, :entry_field
|
6
|
+
attr_reader :dir_attribute, :file_attribute, :link_attribute, :highlight
|
7
|
+
attr_reader :sock_attribute, :field_attribute, :filler_character
|
8
|
+
attr_reader :dir_contents, :file_counter, :pwd, :pathname
|
9
|
+
|
10
|
+
def initialize(cdkscreen, xplace, yplace, height, width, title, label,
|
11
|
+
field_attribute, filler_char, highlight, d_attribute, f_attribute,
|
12
|
+
l_attribute, s_attribute, box, shadow)
|
13
|
+
super()
|
14
|
+
parent_width = cdkscreen.window.getmaxx
|
15
|
+
parent_height = cdkscreen.window.getmaxy
|
16
|
+
bindings = {
|
17
|
+
CDK::BACKCHAR => Ncurses::KEY_PPAGE,
|
18
|
+
CDK::FORCHAR => Ncurses::KEY_NPAGE,
|
19
|
+
}
|
20
|
+
|
21
|
+
self.setBox(box)
|
22
|
+
|
23
|
+
# If the height is a negative value the height will be ROWS-height,
|
24
|
+
# otherwise the height will be the given height
|
25
|
+
box_height = CDK.setWidgetDimension(parent_height, height, 0)
|
26
|
+
|
27
|
+
# If the width is a negative value, the width will be COLS-width,
|
28
|
+
# otherwise the width will be the given width.
|
29
|
+
box_width = CDK.setWidgetDimension(parent_width, width, 0)
|
30
|
+
|
31
|
+
# Rejustify the x and y positions if we need to.
|
32
|
+
xtmp = [xplace]
|
33
|
+
ytmp = [yplace]
|
34
|
+
CDK.alignxy(cdkscreen.window, xtmp, ytmp, box_width, box_height)
|
35
|
+
xpos = xtmp[0]
|
36
|
+
ypos = ytmp[0]
|
37
|
+
|
38
|
+
# Make sure the box isn't too small.
|
39
|
+
box_width = [box_width, 15].max
|
40
|
+
box_height = [box_height, 6].max
|
41
|
+
|
42
|
+
# Make the file selector window.
|
43
|
+
@win = Ncurses::WINDOW.new(box_height, box_width, ypos, xpos)
|
44
|
+
|
45
|
+
# is the window nil?
|
46
|
+
if @win.nil?
|
47
|
+
fselect.destroy
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
@win.keypad(true)
|
51
|
+
|
52
|
+
# Set some variables.
|
53
|
+
@screen = cdkscreen
|
54
|
+
@parent = cdkscreen.window
|
55
|
+
@dir_attribute = d_attribute.clone
|
56
|
+
@file_attribute = f_attribute.clone
|
57
|
+
@link_attribute = l_attribute.clone
|
58
|
+
@sock_attribute = s_attribute.clone
|
59
|
+
@highlight = highlight
|
60
|
+
@filler_character = filler_char
|
61
|
+
@field_attribute = field_attribute
|
62
|
+
@box_height = box_height
|
63
|
+
@box_width = box_width
|
64
|
+
@file_counter = 0
|
65
|
+
@pwd = ''
|
66
|
+
@input_window = @win
|
67
|
+
@shadow = shadow
|
68
|
+
@shadow_win = nil
|
69
|
+
|
70
|
+
# Get the present working directory.
|
71
|
+
# XXX need error handling (set to '.' on error)
|
72
|
+
@pwd = Dir.getwd
|
73
|
+
|
74
|
+
# Get the contents of the current directory
|
75
|
+
self.setDirContents
|
76
|
+
|
77
|
+
# Create the entry field in the selector
|
78
|
+
label_len = []
|
79
|
+
CDK.char2Chtype(label, label_len, [])
|
80
|
+
label_len = label_len[0]
|
81
|
+
|
82
|
+
temp_width = if CDK::FSELECT.isFullWidth(width)
|
83
|
+
then CDK::FULL
|
84
|
+
else box_width - 2 - label_len
|
85
|
+
end
|
86
|
+
@entry_field = CDK::ENTRY.new(cdkscreen, @win.getbegx, @win.getbegy,
|
87
|
+
title, label, field_attribute, filler_char, :MIXED, temp_width,
|
88
|
+
0, 512, box, false)
|
89
|
+
|
90
|
+
# Make sure the widget was created.
|
91
|
+
if @entry_field.nil?
|
92
|
+
self.destroy
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
|
96
|
+
# Set the lower left/right characters of the entry field.
|
97
|
+
@entry_field.setLLchar(Ncurses::ACS_LTEE)
|
98
|
+
@entry_field.setLRchar(Ncurses::ACS_RTEE)
|
99
|
+
|
100
|
+
# This is a callback to the scrolling list which displays information
|
101
|
+
# about the current file. (and the whole directory as well)
|
102
|
+
display_file_info_cb = lambda do |object_type, entry, fselect, key|
|
103
|
+
# Get the file name.
|
104
|
+
filename = fselect.entry_field.info
|
105
|
+
|
106
|
+
# Get specific information about the files.
|
107
|
+
# lstat (filename, &fileStat);
|
108
|
+
file_stat = File.stat(filename)
|
109
|
+
|
110
|
+
# Determine the file type
|
111
|
+
filetype = case
|
112
|
+
when file_stat.symlink?
|
113
|
+
'Symbolic Link'
|
114
|
+
when file_stat.socket?
|
115
|
+
'Socket'
|
116
|
+
when file_stat.file?
|
117
|
+
'Regular File'
|
118
|
+
when file_stat.directory?
|
119
|
+
'Directory'
|
120
|
+
when file_stat.chardev?
|
121
|
+
'Character Device'
|
122
|
+
when file_stat.blockdev?
|
123
|
+
'Block Device'
|
124
|
+
when file_stat.ftype == 'fif'
|
125
|
+
'FIFO Device'
|
126
|
+
else
|
127
|
+
'Unknown'
|
128
|
+
end
|
129
|
+
|
130
|
+
# Get the user name and group name.
|
131
|
+
pw_ent = Etc.getpwuid(file_stat.uid)
|
132
|
+
gr_ent = Etc.getgrgid(file_stat.gid)
|
133
|
+
|
134
|
+
# Convert the mode to both string and int
|
135
|
+
# intMode = mode2Char (stringMode, fileStat.st_mode);
|
136
|
+
|
137
|
+
# Create the message.
|
138
|
+
mesg = [
|
139
|
+
'Directory : </U>%s' % [fselect.pwd],
|
140
|
+
'Filename : </U>%s' % [filename],
|
141
|
+
'Owner : </U>%s<!U> (%d)' % [pw_ent.name, file_stat.uid],
|
142
|
+
'Group : </U>%s<!U> (%d)' % [gr_ent.name, file_stat.gid],
|
143
|
+
'Permissions: </U>%s<!U> (%o)' % [string_mode, int_mode],
|
144
|
+
'Size : </U>%ld<!U> bytes' % [file_stat.size],
|
145
|
+
'Last Access: </U>%s' % [file_stat.atime],
|
146
|
+
'Last Change: </U>%s' % [file_stat.ctime],
|
147
|
+
'File Type : </U>%s' % [filetype]
|
148
|
+
]
|
149
|
+
|
150
|
+
# Create the pop up label.
|
151
|
+
info_label = CDK::LABEL.new(entry.screen, CDK::CENTER, CDK::CENTER,
|
152
|
+
mesg, 9, true, false)
|
153
|
+
info_label.draw(true)
|
154
|
+
info_label.getch([])
|
155
|
+
|
156
|
+
info_label.destroy
|
157
|
+
|
158
|
+
# Redraw the file selector.
|
159
|
+
fselect.draw(fselect.box)
|
160
|
+
return true
|
161
|
+
end
|
162
|
+
|
163
|
+
# This tries to complete the filename
|
164
|
+
complete_filename_cb = lambda do |object_type, object, fselect, key|
|
165
|
+
scrollp = fselect.scroll_field
|
166
|
+
entry = fselect.entry_field
|
167
|
+
filename = entry.info.clone
|
168
|
+
mydirname = CDK.dirName(filename)
|
169
|
+
current_index = 0
|
170
|
+
|
171
|
+
# Make sure the filename is not nil/empty.
|
172
|
+
if filename.nil? || filename.size == 0
|
173
|
+
CDK.Beep
|
174
|
+
return true
|
175
|
+
end
|
176
|
+
|
177
|
+
# Try to expand the filename if it starts with a ~
|
178
|
+
unless (new_filename = CDK::FSELECT.expandTilde(filename)).nil?
|
179
|
+
filename = new_filename
|
180
|
+
entry.setValue(filename)
|
181
|
+
entry.draw(entry.box)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Make sure we can change into the directory.
|
185
|
+
is_directory = Dir.exists?(filename)
|
186
|
+
# if (chdir (fselect->pwd) != 0)
|
187
|
+
# return FALSE;
|
188
|
+
#Dir.chdir(fselect.pwd)
|
189
|
+
|
190
|
+
# XXX original: isDirectory ? mydirname : filename
|
191
|
+
fselect.set(if is_directory then filename else mydirname end,
|
192
|
+
fselect.field_attribute, fselect.filler_character,
|
193
|
+
fselect.highlight, fselect.dir_attribute, fselect.file_attribute,
|
194
|
+
fselect.link_attribute, fselect.sock_attribute, fselect.box)
|
195
|
+
|
196
|
+
# If we can, change into the directory.
|
197
|
+
# XXX original: if isDirectory (with 0 as success result)
|
198
|
+
if is_directory
|
199
|
+
entry.setValue(filename)
|
200
|
+
entry.draw(entry.box)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Create the file list.
|
204
|
+
list = []
|
205
|
+
(0...fselect.file_counter).each do |x|
|
206
|
+
list << fselect.contentToPath(fselect.dir_contents[x])
|
207
|
+
end
|
208
|
+
|
209
|
+
# Look for a unique filename match.
|
210
|
+
index = CDK.searchList(list, fselect.file_counter, filename)
|
211
|
+
|
212
|
+
# If the index is less than zero, return we didn't find a match.
|
213
|
+
if index < 0
|
214
|
+
CDK.Beep
|
215
|
+
else
|
216
|
+
# Move to the current item in the scrolling list.
|
217
|
+
# difference = Index - scrollp->currentItem;
|
218
|
+
# absoluteDifference = abs (difference);
|
219
|
+
# if (difference < 0)
|
220
|
+
# {
|
221
|
+
# for (x = 0; x < absoluteDifference; x++)
|
222
|
+
# {
|
223
|
+
# injectMyScroller (fselect, KEY_UP);
|
224
|
+
# }
|
225
|
+
# }
|
226
|
+
# else if (difference > 0)
|
227
|
+
# {
|
228
|
+
# for (x = 0; x < absoluteDifferene; x++)
|
229
|
+
# {
|
230
|
+
# injectMyScroller (fselect, KEY_DOWN);
|
231
|
+
# }
|
232
|
+
# }
|
233
|
+
scrollp.setPosition(index)
|
234
|
+
fselect.drawMyScroller
|
235
|
+
|
236
|
+
# Ok, we found a match, is the next item similar?
|
237
|
+
if index + 1 < fselect.file_counter && index + 1 < list.size &&
|
238
|
+
list[index + 1][0..([filename.size, list[index + 1].size].min)] ==
|
239
|
+
filename
|
240
|
+
current_index = index
|
241
|
+
base_chars = filename.size
|
242
|
+
matches = 0
|
243
|
+
|
244
|
+
# Determine the number of files which match.
|
245
|
+
while current_index < fselect.file_counter
|
246
|
+
if current_index + 1 < list.size
|
247
|
+
if list[current_index][0..(
|
248
|
+
[filename.size, list[current_index].size].max)] == filename
|
249
|
+
matches += 1
|
250
|
+
end
|
251
|
+
end
|
252
|
+
current_index += 1
|
253
|
+
end
|
254
|
+
|
255
|
+
# Start looking for the common base characters.
|
256
|
+
while true
|
257
|
+
secondary_matches = 0
|
258
|
+
(index...index + matches).each do |x|
|
259
|
+
if list[index][base_chars] == list[x][base_chars]
|
260
|
+
secondary_matches += 1
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
if secondary_matches != matches
|
265
|
+
CDK.Beep
|
266
|
+
break
|
267
|
+
end
|
268
|
+
|
269
|
+
# Inject the character into the entry field.
|
270
|
+
fselect.entry_field.inject(list[index][base_chars])
|
271
|
+
base_chars += 1
|
272
|
+
end
|
273
|
+
else
|
274
|
+
# Set the entry field with the found item.
|
275
|
+
entry.setValue(list[index])
|
276
|
+
entry.draw(entry.box)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
return true
|
281
|
+
end
|
282
|
+
|
283
|
+
# This allows the user to delete a file.
|
284
|
+
delete_file_cb = lambda do |object_type, fscroll, fselect|
|
285
|
+
buttons = ['No', 'Yes']
|
286
|
+
|
287
|
+
# Get the filename which is to be deleted.
|
288
|
+
filename = CDK.chtype2Char(fscroll.item[fscroll.current_item])
|
289
|
+
filename = filename[0...-1]
|
290
|
+
|
291
|
+
# Create the dialog message.
|
292
|
+
mesg = [
|
293
|
+
'<C>Are you sure you want to delete the file:',
|
294
|
+
'<C></U>"%s"?' % [filename]
|
295
|
+
]
|
296
|
+
|
297
|
+
# Create the dialog box.
|
298
|
+
question = CDK::DIALOG.new(fselect.screen, CDK::CENTER, CDK::CENTER,
|
299
|
+
mesg, 2, buttons, 2, Ncurses::A_REVERSE, true, true, false)
|
300
|
+
|
301
|
+
# If the said yes then try to nuke it.
|
302
|
+
if question.activate([]) == 1
|
303
|
+
# If we were successful, reload the scrolling list.
|
304
|
+
if File.unlink(filename) == 0
|
305
|
+
# Set the file selector information.
|
306
|
+
fselect.set(fselect.pwd, fselect.field_attribute,
|
307
|
+
fselect.filler_character, fselect.highlight,
|
308
|
+
fselect.dir_attribute, fselect.file_attribute,
|
309
|
+
fselect.link_attribute, fselect.sock_attribute, fselect.box)
|
310
|
+
else
|
311
|
+
# Pop up a message.
|
312
|
+
# mesg[0] = copyChar (errorMessage ("<C>Cannot delete file: %s"));
|
313
|
+
# mesg[1] = copyChar (" ");
|
314
|
+
# mesg[2] = copyChar("<C>Press any key to continue.");
|
315
|
+
# popupLabel(ScreenOf (fselect), (CDK_CSTRING2) mesg, 3);
|
316
|
+
# freeCharList (mesg, 3);
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
# Clean up.
|
321
|
+
question.destroy
|
322
|
+
|
323
|
+
# Redraw the file seoector.
|
324
|
+
fselect.draw(fselect.box)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Start of callback functions.
|
328
|
+
adjust_scroll_cb = lambda do |object_type, object, fselect, key|
|
329
|
+
scrollp = fselect.scroll_field
|
330
|
+
entry = fselect.entry_field
|
331
|
+
|
332
|
+
if scrollp.list_size > 0
|
333
|
+
# Move the scrolling list.
|
334
|
+
fselect.injectMyScroller(key)
|
335
|
+
|
336
|
+
# Get the currently highlighted filename.
|
337
|
+
current = CDK.chtype2Char(scrollp.item[scrollp.current_item])
|
338
|
+
#current = CDK.chtype2String(scrollp.item[scrollp.current_item])
|
339
|
+
current = current[0...-1]
|
340
|
+
|
341
|
+
temp = CDK::FSELECT.make_pathname(fselect.pwd, current)
|
342
|
+
|
343
|
+
# Set the value in the entry field.
|
344
|
+
entry.setValue(temp)
|
345
|
+
entry.draw(entry.box)
|
346
|
+
|
347
|
+
return true
|
348
|
+
end
|
349
|
+
CDK.Beep
|
350
|
+
return false
|
351
|
+
end
|
352
|
+
|
353
|
+
# Define the callbacks for the entry field.
|
354
|
+
@entry_field.bind(:ENTRY, Ncurses::KEY_UP, adjust_scroll_cb, self)
|
355
|
+
@entry_field.bind(:ENTRY, Ncurses::KEY_PPAGE, adjust_scroll_cb, self)
|
356
|
+
@entry_field.bind(:ENTRY, Ncurses::KEY_DOWN, adjust_scroll_cb, self)
|
357
|
+
@entry_field.bind(:ENTRY, Ncurses::KEY_NPAGE, adjust_scroll_cb, self)
|
358
|
+
@entry_field.bind(:ENTRY, CDK::KEY_TAB, complete_filename_cb, self)
|
359
|
+
@entry_field.bind(:ENTRY, CDK.CTRL('^'), display_file_info_cb, self)
|
360
|
+
|
361
|
+
# Put the current working directory in the entry field.
|
362
|
+
@entry_field.setValue(@pwd)
|
363
|
+
|
364
|
+
# Create the scrolling list in the selector.
|
365
|
+
temp_height = @entry_field.win.getmaxy - @border_size
|
366
|
+
temp_width = if CDK::FSELECT.isFullWidth(width)
|
367
|
+
then CDK::FULL
|
368
|
+
else box_width - 1
|
369
|
+
end
|
370
|
+
@scroll_field = CDK::SCROLL.new(cdkscreen,
|
371
|
+
@win.getbegx, @win.getbegy + temp_height, CDK::RIGHT,
|
372
|
+
box_height - temp_height, temp_width, '', @dir_contents,
|
373
|
+
@file_counter, false, @highlight, box, false)
|
374
|
+
|
375
|
+
# Set the lower left/right characters of the entry field.
|
376
|
+
@scroll_field.setULchar(Ncurses::ACS_LTEE)
|
377
|
+
@scroll_field.setURchar(Ncurses::ACS_RTEE)
|
378
|
+
|
379
|
+
# Do we want a shadow?
|
380
|
+
if shadow
|
381
|
+
@shadow_win = Ncurses::WINDOW.new(box_height, box_width,
|
382
|
+
ypos + 1, xpos + 1)
|
383
|
+
end
|
384
|
+
|
385
|
+
# Setup the key bindings
|
386
|
+
bindings.each do |from, to|
|
387
|
+
self.bind(:FSELECT, from, :getc, to)
|
388
|
+
end
|
389
|
+
|
390
|
+
cdkscreen.register(:FSELECT, self)
|
391
|
+
end
|
392
|
+
|
393
|
+
# This erases the file selector from the screen.
|
394
|
+
def erase
|
395
|
+
if self.validCDKObject
|
396
|
+
@scroll_field.erase
|
397
|
+
@entry_field.erase
|
398
|
+
CDK.eraseCursesWindow(@win)
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
# This moves the fselect field to the given location.
|
403
|
+
def move(xplace, yplace, relative, refresh_flag)
|
404
|
+
windows = [@win, @shadow_win]
|
405
|
+
subwidgets = [@entry_field, @scroll_field]
|
406
|
+
|
407
|
+
self.move_specific(xplace, yplace, relative, refresh_flag,
|
408
|
+
windows, subwidgets)
|
409
|
+
end
|
410
|
+
|
411
|
+
# The fselect's focus resides in the entry widget. But the scroll widget
|
412
|
+
# will not draw items highlighted unless it has focus. Temporarily adjust
|
413
|
+
# the focus of the scroll widget when drawing on it to get the right
|
414
|
+
# highlighting.
|
415
|
+
|
416
|
+
def saveFocus
|
417
|
+
@save = @scroll_field.has_focus
|
418
|
+
@scroll_field.has_focus = @entry_field.has_focus
|
419
|
+
end
|
420
|
+
|
421
|
+
def restoreFocus
|
422
|
+
@scroll_field.has_focus = @save
|
423
|
+
end
|
424
|
+
|
425
|
+
def drawMyScroller
|
426
|
+
self.saveFocus
|
427
|
+
@scroll_field.draw(@scroll_field.box)
|
428
|
+
self.restoreFocus
|
429
|
+
end
|
430
|
+
|
431
|
+
def injectMyScroller(key)
|
432
|
+
self.saveFocus
|
433
|
+
@scroll_field.inject(key)
|
434
|
+
self.restoreFocus
|
435
|
+
end
|
436
|
+
|
437
|
+
# This draws the file selector widget.
|
438
|
+
def draw(box)
|
439
|
+
# Draw in the shadow if we need to.
|
440
|
+
unless @shadow_win.nil?
|
441
|
+
Draw.drawShadow(@shadow_win)
|
442
|
+
end
|
443
|
+
|
444
|
+
# Draw in the entry field.
|
445
|
+
@entry_field.draw(@entry_field.box)
|
446
|
+
|
447
|
+
# Draw in the scroll field.
|
448
|
+
self.drawMyScroller
|
449
|
+
end
|
450
|
+
|
451
|
+
# This means you want to use the given file selector. It takes input
|
452
|
+
# from the keyboard and when it's done it fills the entry info element
|
453
|
+
# of the structure with what was typed.
|
454
|
+
def activate(actions)
|
455
|
+
input = 0
|
456
|
+
ret = 0
|
457
|
+
|
458
|
+
# Draw the widget.
|
459
|
+
self.draw(@box)
|
460
|
+
|
461
|
+
if actions.nil? || actions.size == 0
|
462
|
+
while true
|
463
|
+
input = @entry_field.getch([])
|
464
|
+
|
465
|
+
# Inject the character into the widget.
|
466
|
+
ret = self.inject(input)
|
467
|
+
if @exit_type != :EARLY_EXIT
|
468
|
+
return ret
|
469
|
+
end
|
470
|
+
end
|
471
|
+
else
|
472
|
+
# Inject each character one at a time.
|
473
|
+
actions.each do |action|
|
474
|
+
ret = self.inject(action)
|
475
|
+
if @exit_type != :EARLY_EXIT
|
476
|
+
return ret
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
# Set the exit type and exit.
|
482
|
+
self.setExitType(0)
|
483
|
+
return 0
|
484
|
+
end
|
485
|
+
|
486
|
+
# This injects a single character into the file selector.
|
487
|
+
def inject(input)
|
488
|
+
ret = -1
|
489
|
+
complete = false
|
490
|
+
|
491
|
+
# Let the user play.
|
492
|
+
filename = @entry_field.inject(input)
|
493
|
+
|
494
|
+
# Copy the entry field exit_type to the file selector.
|
495
|
+
@exit_type = @entry_field.exit_type
|
496
|
+
|
497
|
+
# If we exited early, make sure we don't interpret it as a file.
|
498
|
+
if @exit_type == :EARLY_EXIT
|
499
|
+
return 0
|
500
|
+
end
|
501
|
+
|
502
|
+
# Can we change into the directory
|
503
|
+
#file = Dir.chdir(filename)
|
504
|
+
#if Dir.chdir(@pwd) != 0
|
505
|
+
# return 0
|
506
|
+
#end
|
507
|
+
|
508
|
+
# If it's not a directory, return the filename.
|
509
|
+
if !Dir.exists?(filename)
|
510
|
+
# It's a regular file, create the full path
|
511
|
+
@pathname = filename.clone
|
512
|
+
|
513
|
+
# Return the complete pathname.
|
514
|
+
ret = @pathname
|
515
|
+
complete = true
|
516
|
+
else
|
517
|
+
# Set the file selector information.
|
518
|
+
self.set(filename, @field_attribute, @filler_character, @highlight,
|
519
|
+
@dir_attribute, @file_attribute, @link_attribute, @sock_attribute,
|
520
|
+
@box)
|
521
|
+
|
522
|
+
# Redraw the scrolling list.
|
523
|
+
self.drawMyScroller
|
524
|
+
end
|
525
|
+
|
526
|
+
if !complete
|
527
|
+
self.setExitType(0)
|
528
|
+
end
|
529
|
+
|
530
|
+
@result_data = ret
|
531
|
+
return ret
|
532
|
+
end
|
533
|
+
|
534
|
+
# This function sets the information inside the file selector.
|
535
|
+
def set(directory, field_attrib, filler, highlight, dir_attribute,
|
536
|
+
file_attribute, link_attribute, sock_attribute, box)
|
537
|
+
fscroll = @scroll_field
|
538
|
+
fentry = @entry_field
|
539
|
+
new_directory = ''
|
540
|
+
|
541
|
+
# keep the info sent to us.
|
542
|
+
@field_attribute = field_attrib
|
543
|
+
@filler_character = filler
|
544
|
+
@highlight = highlight
|
545
|
+
|
546
|
+
# Set the attributes of the entry field/scrolling list.
|
547
|
+
self.setFillerChar(filler)
|
548
|
+
self.setHighlight(highlight)
|
549
|
+
|
550
|
+
# Only do the directory stuff if the directory is not nil.
|
551
|
+
if !(directory.nil?) && directory.size > 0
|
552
|
+
# Try to expand the directory if it starts with a ~
|
553
|
+
if (temp_dir = CDK::FSELECT.expandTilde(directory)).size > 0
|
554
|
+
new_directory = temp_dir
|
555
|
+
else
|
556
|
+
new_directory = directory.clone
|
557
|
+
end
|
558
|
+
|
559
|
+
# Change directories.
|
560
|
+
if Dir.chdir(new_directory) != 0
|
561
|
+
CDK.Beep
|
562
|
+
|
563
|
+
# Could not get into the directory, pop up a little message.
|
564
|
+
mesg = [
|
565
|
+
'<C>Could not change into %s' % [new_directory],
|
566
|
+
'<C></U>%s' % ['Unknown reason.'], # errorMessage(format)
|
567
|
+
' ',
|
568
|
+
'<C>Press Any Key To Continue.'
|
569
|
+
]
|
570
|
+
|
571
|
+
# Pop up a message.
|
572
|
+
@screen.popupLabel(mesg, 4)
|
573
|
+
|
574
|
+
# Get out of here.
|
575
|
+
self.erase
|
576
|
+
self.draw(@box)
|
577
|
+
return
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
# if the information coming in is the same as the information
|
582
|
+
# that is already there, there is no need to destroy it.
|
583
|
+
if @pwd != directory
|
584
|
+
@pwd = Dir.getwd
|
585
|
+
end
|
586
|
+
|
587
|
+
@file_attribute = file_attribute.clone
|
588
|
+
@dir_attribute = dir_attribute.clone
|
589
|
+
@link_attribute = link_attribute.clone
|
590
|
+
@sock_attribute = sock_attribute.clone
|
591
|
+
|
592
|
+
# Set the contents of the entry field.
|
593
|
+
fentry.setValue(@pwd)
|
594
|
+
fentry.draw(fentry.box)
|
595
|
+
|
596
|
+
# Get the directory contents.
|
597
|
+
unless self.setDirContents
|
598
|
+
CDK.Beep
|
599
|
+
return
|
600
|
+
end
|
601
|
+
|
602
|
+
# Set the values in the scrolling list.
|
603
|
+
fscroll.setItems(@dir_contents, @file_counter, false)
|
604
|
+
end
|
605
|
+
|
606
|
+
# This creates a list of the files in the current directory.
|
607
|
+
def setDirContents
|
608
|
+
dir_list = []
|
609
|
+
|
610
|
+
# Get the directory contents
|
611
|
+
file_count = CDK.getDirectoryContents(@pwd, dir_list)
|
612
|
+
if file_count <= 0
|
613
|
+
# We couldn't read the directory. Return.
|
614
|
+
return false
|
615
|
+
end
|
616
|
+
|
617
|
+
@dir_contents = dir_list
|
618
|
+
@file_counter = file_count
|
619
|
+
|
620
|
+
# Set the properties of the files.
|
621
|
+
(0...@file_counter).each do |x|
|
622
|
+
attr = ''
|
623
|
+
mode = '?'
|
624
|
+
|
625
|
+
# FIXME(original): access() would give a more correct answer
|
626
|
+
# TODO: add error handling
|
627
|
+
file_stat = File.stat(dir_list[x])
|
628
|
+
if file_stat.executable?
|
629
|
+
mode = '*'
|
630
|
+
else
|
631
|
+
mode = ' '
|
632
|
+
end
|
633
|
+
|
634
|
+
case
|
635
|
+
when file_stat.symlink?
|
636
|
+
attr = @link_attribute
|
637
|
+
mode = '@'
|
638
|
+
when file_stat.socket?
|
639
|
+
attr = @sock_attribute
|
640
|
+
mode = '&'
|
641
|
+
when file_stat.file?
|
642
|
+
attr = @file_attribute
|
643
|
+
when file_stat.directory?
|
644
|
+
attr = @dir_attribute
|
645
|
+
mode = '/'
|
646
|
+
end
|
647
|
+
@dir_contents[x] = '%s%s%s' % [attr, dir_list[x], mode]
|
648
|
+
end
|
649
|
+
return true
|
650
|
+
end
|
651
|
+
|
652
|
+
def getDirContents(count)
|
653
|
+
count << @file_counter
|
654
|
+
return @dir_contents
|
655
|
+
end
|
656
|
+
|
657
|
+
# This sets the current directory of the file selector.
|
658
|
+
def setDirectory(directory)
|
659
|
+
fentry = @entry_field
|
660
|
+
fscroll = @scroll_field
|
661
|
+
result = 1
|
662
|
+
|
663
|
+
# If the directory supplied is the same as what is already there, return.
|
664
|
+
if @pwd != directory
|
665
|
+
# Try to chdir into the given directory.
|
666
|
+
if Dir.chdir(directory) != 0
|
667
|
+
result = 0
|
668
|
+
else
|
669
|
+
@pwd = Dir.getwd
|
670
|
+
|
671
|
+
# Set the contents of the entry field.
|
672
|
+
fentry.setValue(@pwd)
|
673
|
+
fentry.draw(fentry.box)
|
674
|
+
|
675
|
+
# Get the directory contents.
|
676
|
+
if self.setDirContents
|
677
|
+
# Set the values in the scrolling list.
|
678
|
+
fscroll.setItems(@dir_contents, @file_counter, false)
|
679
|
+
else
|
680
|
+
result = 0
|
681
|
+
end
|
682
|
+
end
|
683
|
+
end
|
684
|
+
return result
|
685
|
+
end
|
686
|
+
|
687
|
+
def getDirectory
|
688
|
+
return @pwd
|
689
|
+
end
|
690
|
+
|
691
|
+
# This sets the filler character of the entry field.
|
692
|
+
def setFillerChar(filler)
|
693
|
+
@filler_character = filler
|
694
|
+
@entry_field.setFillerChar(filler)
|
695
|
+
end
|
696
|
+
|
697
|
+
def getFillerChar
|
698
|
+
return @filler_character
|
699
|
+
end
|
700
|
+
|
701
|
+
# This sets the highlight bar of the scrolling list.
|
702
|
+
def setHighlight(highlight)
|
703
|
+
@highlight = highlight
|
704
|
+
@scroll_field.setHighlight(highlight)
|
705
|
+
end
|
706
|
+
|
707
|
+
def getHighlight
|
708
|
+
return @highlight
|
709
|
+
end
|
710
|
+
|
711
|
+
# This sets the attribute of the directory attribute in the
|
712
|
+
# scrolling list.
|
713
|
+
def setDirAttribute(attribute)
|
714
|
+
# Make sure they are not the same.
|
715
|
+
if @dir_attribute != attribute
|
716
|
+
@dir_attribute = attribute
|
717
|
+
self.setDirContents
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
def getDirAttribute
|
722
|
+
return @dir_attribute
|
723
|
+
end
|
724
|
+
|
725
|
+
# This sets the attribute of the link attribute in the scrolling list.
|
726
|
+
def setLinkAttribute(attribute)
|
727
|
+
# Make sure they are not the same.
|
728
|
+
if @link_attribute != attribute
|
729
|
+
@link_attribute = attribute
|
730
|
+
self.setDirContents
|
731
|
+
end
|
732
|
+
end
|
733
|
+
|
734
|
+
def getLinkAttribute
|
735
|
+
return @link_attribute
|
736
|
+
end
|
737
|
+
|
738
|
+
# This sets the attribute of the socket attribute in the scrolling list.
|
739
|
+
def setSocketAttribute(attribute)
|
740
|
+
# Make sure they are not the same.
|
741
|
+
if @sock_attribute != attribute
|
742
|
+
@sock_attribute = attribute
|
743
|
+
self.setDirContents
|
744
|
+
end
|
745
|
+
end
|
746
|
+
|
747
|
+
def getSocketAttribute
|
748
|
+
return @sock_attribute
|
749
|
+
end
|
750
|
+
|
751
|
+
# This sets the attribute of the file attribute in the scrolling list.
|
752
|
+
def setFileAttribute(attribute)
|
753
|
+
# Make sure they are not the same.
|
754
|
+
if @file_attribute != attribute
|
755
|
+
@file_attribute = attribute
|
756
|
+
self.setDirContents
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
def getFileAttribute
|
761
|
+
return @file_attribute
|
762
|
+
end
|
763
|
+
|
764
|
+
# this sets the contents of the widget
|
765
|
+
def setContents(list, list_size)
|
766
|
+
scrollp = @scroll_field
|
767
|
+
entry = @entry_field
|
768
|
+
|
769
|
+
if !self.createList(list, list_size)
|
770
|
+
return
|
771
|
+
end
|
772
|
+
|
773
|
+
# Set the information in the scrolling list.
|
774
|
+
scrollp.set(@dir_contents, @file_counter, false, scrollp.highlight,
|
775
|
+
scrollp.box)
|
776
|
+
|
777
|
+
# Clean out the entry field.
|
778
|
+
self.setCurrentItem(0)
|
779
|
+
entry.clean
|
780
|
+
|
781
|
+
# Redraw the widget.
|
782
|
+
self.erase
|
783
|
+
self.draw(@box)
|
784
|
+
end
|
785
|
+
|
786
|
+
def getContents(size)
|
787
|
+
size << @file_counter
|
788
|
+
return @dir_contents
|
789
|
+
end
|
790
|
+
|
791
|
+
# Get/set the current position in the scroll wiget.
|
792
|
+
def getCurrentItem
|
793
|
+
return @scroll_field.getCurrent
|
794
|
+
end
|
795
|
+
|
796
|
+
def setCurrentItem(item)
|
797
|
+
if @file_counter != 0
|
798
|
+
@scroll_field.setCurrent(item)
|
799
|
+
|
800
|
+
data = self.contentToPath(@dir_contents[@scroll_field.getCurrentItem])
|
801
|
+
@entry_field.setValue(data)
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
# These functions set the draw characters of the widget.
|
806
|
+
def setMyULchar(character)
|
807
|
+
@entry_field.setULchar(character)
|
808
|
+
end
|
809
|
+
|
810
|
+
def setMyURchar(character)
|
811
|
+
@entry_field.setURchar(character)
|
812
|
+
end
|
813
|
+
|
814
|
+
def setMyLLchar(character)
|
815
|
+
@scroll_field.setLLchar(character)
|
816
|
+
end
|
817
|
+
|
818
|
+
def setMyLRchar(character)
|
819
|
+
@scroll_field.setLRchar(character)
|
820
|
+
end
|
821
|
+
|
822
|
+
def setMyVTchar(character)
|
823
|
+
@entry_field.setVTchar(character)
|
824
|
+
@scroll_field.setVTchar(character)
|
825
|
+
end
|
826
|
+
|
827
|
+
def setMyHZchar(character)
|
828
|
+
@entry_field.setHZchar(character)
|
829
|
+
@scroll_field.setHZchar(character)
|
830
|
+
end
|
831
|
+
|
832
|
+
def setMyBXattr(character)
|
833
|
+
@entry_field.setBXattr(character)
|
834
|
+
@scroll_field.setBXattr(character)
|
835
|
+
end
|
836
|
+
|
837
|
+
# This sets the background attribute of the widget.
|
838
|
+
def setBKattr(attrib)
|
839
|
+
@entry_field.setBKattr(attrib)
|
840
|
+
@scroll_field.setBKattr(attrib)
|
841
|
+
end
|
842
|
+
|
843
|
+
# This destroys the file selector.
|
844
|
+
def destroy
|
845
|
+
self.cleanBindings(:FSELECT)
|
846
|
+
|
847
|
+
# Destroy the other CDK objects
|
848
|
+
@scroll_field.destroy
|
849
|
+
@entry_field.destroy
|
850
|
+
|
851
|
+
# Free up the windows
|
852
|
+
CDK.deleteCursesWindow(@shadow_win)
|
853
|
+
CDK.deleteCursesWindow(@win)
|
854
|
+
|
855
|
+
# Clean the key bindings.
|
856
|
+
# Unregister the object.
|
857
|
+
CDK::SCREEN.unregister(:FSELECT, self)
|
858
|
+
end
|
859
|
+
|
860
|
+
# Currently a wrapper for File.expand_path
|
861
|
+
def self.make_pathname(directory, filename)
|
862
|
+
if filename == '..'
|
863
|
+
return File.expand_path(directory) + '/..'
|
864
|
+
else
|
865
|
+
return File.expand_path(filename, directory)
|
866
|
+
end
|
867
|
+
end
|
868
|
+
|
869
|
+
# Return the plain string that corresponds to an item in dir_contents
|
870
|
+
def contentToPath(content)
|
871
|
+
# XXX direct translation of original but might be redundant
|
872
|
+
temp_chtype = CDK.char2Chtype(content, [], [])
|
873
|
+
temp_char = CDK.chtype2Char(temp_chtype)
|
874
|
+
temp_char = temp_char[0..-1]
|
875
|
+
|
876
|
+
# Create the pathname.
|
877
|
+
result = CDK::FSELECT.make_pathname(@pwd, temp_char)
|
878
|
+
|
879
|
+
return result
|
880
|
+
end
|
881
|
+
|
882
|
+
# Currently a wrapper for File.expand_path
|
883
|
+
def self.expandTilde(filename)
|
884
|
+
return File.expand_path(filename)
|
885
|
+
end
|
886
|
+
|
887
|
+
def destroyInfo
|
888
|
+
@dir_contents = []
|
889
|
+
@file_counter = 0
|
890
|
+
end
|
891
|
+
|
892
|
+
def createList(list, list_size)
|
893
|
+
status = false
|
894
|
+
|
895
|
+
if list_size >= 0
|
896
|
+
newlist = []
|
897
|
+
|
898
|
+
# Copy in the new information
|
899
|
+
status = true
|
900
|
+
(0...list_size).each do |x|
|
901
|
+
newlist << list[x]
|
902
|
+
if newlist[x] == 0
|
903
|
+
status = false
|
904
|
+
break
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
if status
|
909
|
+
self.destroyInfo
|
910
|
+
@file_counter = list_size
|
911
|
+
@dir_contents = newlist
|
912
|
+
end
|
913
|
+
else
|
914
|
+
self.destroyInfo
|
915
|
+
status = true
|
916
|
+
end
|
917
|
+
return status
|
918
|
+
end
|
919
|
+
|
920
|
+
def focus
|
921
|
+
@entry_field.focus
|
922
|
+
end
|
923
|
+
|
924
|
+
def unfocus
|
925
|
+
@entry_field.unfocus
|
926
|
+
end
|
927
|
+
|
928
|
+
def self.isFullWidth(width)
|
929
|
+
width == CDK::FULL || (Ncurses.COLS != 0 && width >= Ncurses.COLS)
|
930
|
+
end
|
931
|
+
|
932
|
+
def position
|
933
|
+
super(@win)
|
934
|
+
end
|
935
|
+
|
936
|
+
def object_type
|
937
|
+
:FSELECT
|
938
|
+
end
|
939
|
+
end
|
940
|
+
end
|