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