rndk 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -4
  3. data/TODO +21 -1
  4. data/demos/appointment.rb +279 -299
  5. data/demos/clock.rb +13 -8
  6. data/demos/rss-reader.rb +84 -0
  7. data/examples/01-hello-world.rb +13 -11
  8. data/examples/02-colors.rb +14 -21
  9. data/examples/03-markup.rb +7 -7
  10. data/examples/04-quick-widgets.rb +2 -2
  11. data/examples/05-position-widget.rb +50 -31
  12. data/examples/06-callbacks.rb +77 -0
  13. data/examples/07-traverse.rb +90 -0
  14. data/examples/10-all-widgets.rb +165 -0
  15. data/examples/calendar.rb +20 -32
  16. data/examples/entry.rb +15 -20
  17. data/examples/label.rb +11 -11
  18. data/examples/scroll.rb +16 -60
  19. data/examples/slider.rb +18 -19
  20. data/examples/viewer.rb +65 -0
  21. data/lib/rndk.rb +28 -7
  22. data/lib/rndk/alphalist.rb +309 -313
  23. data/lib/rndk/button.rb +239 -157
  24. data/lib/rndk/buttonbox.rb +136 -103
  25. data/lib/rndk/calendar.rb +246 -203
  26. data/lib/rndk/core/color.rb +63 -13
  27. data/lib/rndk/core/display.rb +1 -1
  28. data/lib/rndk/core/draw.rb +11 -11
  29. data/lib/rndk/core/markup.rb +21 -21
  30. data/lib/rndk/core/quick_widgets.rb +75 -96
  31. data/lib/rndk/core/screen.rb +145 -102
  32. data/lib/rndk/core/traverse.rb +150 -136
  33. data/lib/rndk/core/utils.rb +5 -6
  34. data/lib/rndk/core/widget.rb +207 -191
  35. data/lib/rndk/core/widget_bind.rb +108 -0
  36. data/lib/rndk/dialog.rb +88 -56
  37. data/lib/rndk/entry.rb +79 -64
  38. data/lib/rndk/fscale.rb +38 -20
  39. data/lib/rndk/fslider.rb +38 -23
  40. data/lib/rndk/graph.rb +92 -53
  41. data/lib/rndk/itemlist.rb +80 -62
  42. data/lib/rndk/label.rb +111 -77
  43. data/lib/rndk/radio.rb +138 -128
  44. data/lib/rndk/scale.rb +123 -122
  45. data/lib/rndk/scroll.rb +444 -391
  46. data/lib/rndk/scroller.rb +21 -21
  47. data/lib/rndk/slider.rb +149 -140
  48. data/lib/rndk/template.rb +74 -61
  49. data/lib/rndk/version.rb +1 -1
  50. data/lib/rndk/viewer.rb +499 -298
  51. metadata +8 -14
  52. data/demos/fileview.rb +0 -141
  53. data/lib/rndk/dscale.rb +0 -13
  54. data/lib/rndk/fselect.rb +0 -938
  55. data/lib/rndk/histogram.rb +0 -412
  56. data/lib/rndk/marquee.rb +0 -244
  57. data/lib/rndk/matrix.rb +0 -1189
  58. data/lib/rndk/mentry.rb +0 -619
  59. data/lib/rndk/menu.rb +0 -478
  60. data/lib/rndk/selection.rb +0 -630
  61. data/lib/rndk/swindow.rb +0 -766
  62. data/lib/rndk/uscale.rb +0 -14
  63. data/lib/rndk/uslider.rb +0 -14
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rndk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Dantas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-14 00:00:00.000000000 Z
11
+ date: 2013-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi-ncurses
@@ -74,17 +74,21 @@ files:
74
74
  - TODO
75
75
  - demos/appointment.rb
76
76
  - demos/clock.rb
77
- - demos/fileview.rb
77
+ - demos/rss-reader.rb
78
78
  - examples/01-hello-world.rb
79
79
  - examples/02-colors.rb
80
80
  - examples/03-markup.rb
81
81
  - examples/04-quick-widgets.rb
82
82
  - examples/05-position-widget.rb
83
+ - examples/06-callbacks.rb
84
+ - examples/07-traverse.rb
85
+ - examples/10-all-widgets.rb
83
86
  - examples/calendar.rb
84
87
  - examples/entry.rb
85
88
  - examples/label.rb
86
89
  - examples/scroll.rb
87
90
  - examples/slider.rb
91
+ - examples/viewer.rb
88
92
  - lib/rndk.rb
89
93
  - lib/rndk/alphalist.rb
90
94
  - lib/rndk/button.rb
@@ -99,30 +103,20 @@ files:
99
103
  - lib/rndk/core/traverse.rb
100
104
  - lib/rndk/core/utils.rb
101
105
  - lib/rndk/core/widget.rb
106
+ - lib/rndk/core/widget_bind.rb
102
107
  - lib/rndk/dialog.rb
103
- - lib/rndk/dscale.rb
104
108
  - lib/rndk/entry.rb
105
109
  - lib/rndk/fscale.rb
106
- - lib/rndk/fselect.rb
107
110
  - lib/rndk/fslider.rb
108
111
  - lib/rndk/graph.rb
109
- - lib/rndk/histogram.rb
110
112
  - lib/rndk/itemlist.rb
111
113
  - lib/rndk/label.rb
112
- - lib/rndk/marquee.rb
113
- - lib/rndk/matrix.rb
114
- - lib/rndk/mentry.rb
115
- - lib/rndk/menu.rb
116
114
  - lib/rndk/radio.rb
117
115
  - lib/rndk/scale.rb
118
116
  - lib/rndk/scroll.rb
119
117
  - lib/rndk/scroller.rb
120
- - lib/rndk/selection.rb
121
118
  - lib/rndk/slider.rb
122
- - lib/rndk/swindow.rb
123
119
  - lib/rndk/template.rb
124
- - lib/rndk/uscale.rb
125
- - lib/rndk/uslider.rb
126
120
  - lib/rndk/version.rb
127
121
  - lib/rndk/viewer.rb
128
122
  - rndk.gemspec
@@ -1,141 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Note: This is not for beginners! Check out the examples/
4
- # before adventuring into the demos/ realm!
5
- #
6
- # Shows a FSelect Widget, asking you to pick a file.
7
- # Then, a Viewer Widget, showing that file's contents.
8
- #
9
- require 'optparse'
10
- require 'rndk/fselect'
11
-
12
- begin
13
- filename = ''
14
- directory = '.'
15
-
16
- # Create the viewer buttons.
17
- button = [
18
- '</5><OK><!5>',
19
- '</5><Cancel><!5>',
20
- ]
21
-
22
- # Set up RNDK and Colors
23
- rndkscreen = RNDK::Screen.new
24
- RNDK::Color.init
25
-
26
- # Get the filename
27
- if filename == ''
28
- title = '<C>Pick a file.'
29
- label = 'File: '
30
- fselect = RNDK::FSELECT.new(rndkscreen,
31
- RNDK::CENTER,
32
- RNDK::CENTER,
33
- 20,
34
- 65,
35
- title,
36
- label,
37
- Ncurses::A_NORMAL,
38
- '_',
39
- Ncurses::A_REVERSE,
40
- '</5>', '</48>', '</N>', '</N>',
41
- true,
42
- false)
43
-
44
- # Set the starting directory. This is not necessary because when
45
- # the file selector starts it uses the present directory as a default.
46
- fselect.set(directory,
47
- Ncurses::A_NORMAL,
48
- '.',
49
- Ncurses::A_REVERSE,
50
- '</5>', '</48>',
51
- '</N>', '</N>',
52
- fselect.box)
53
-
54
- # Activate the file selector.
55
- filename = fselect.activate([])
56
-
57
- # Check how the person exited from the widget.
58
- if fselect.exit_type == :ESCAPE_HIT
59
- # pop up a message for the user.
60
- mesg = [
61
- '<C>Escape hit. No file selected.',
62
- '',
63
- '<C>Press any key to continue.',
64
- ]
65
- rndkscreen.popup_label(mesg, 3)
66
-
67
- fselect.destroy
68
-
69
- RNDK::Screen.end_rndk
70
- exit
71
- end
72
- fselect.destroy
73
- end
74
-
75
- # Create the file viewer to view the file selected.
76
- example = RNDK::VIEWER.new(rndkscreen,
77
- RNDK::CENTER,
78
- RNDK::CENTER,
79
- 20,
80
- -2,
81
- button,
82
- 2,
83
- Ncurses::A_REVERSE,
84
- true,
85
- false)
86
-
87
- # Could we create the viewer widget?
88
- if example.nil?
89
- RNDK::Screen.end_rndk
90
-
91
- puts "Cannot create viewer. Is the window too small?"
92
- exit 1
93
- end
94
-
95
- # Open the file and read the contents.
96
-
97
- info = []
98
- lines = RNDK.read_file(filename, info)
99
- if lines == -1
100
- puts "Could not open %s" % [filename]
101
- exit 1
102
- end
103
-
104
- # Set up the viewer title and the contents to the widget.
105
- title = '<C></B/22>%20s<!22!B> (If screen is messed up, press Ctrl+L)' % filename
106
- example.set(title, info, lines, Ncurses::A_REVERSE, true, true, true)
107
-
108
- # Activate the viewer widget.
109
- selected = example.activate([])
110
-
111
- # Check how the person exited from the widget.
112
- if example.exit_type == :ESCAPE_HIT
113
- mesg = [
114
- '<C>Escape hit. No Button selected.',
115
- '',
116
- '<C>Press any key to continue.',
117
- ]
118
- rndkscreen.popup_label mesg
119
-
120
- elsif example.exit_type == :NORMAL
121
- mesg = [
122
- '<C>You selected button %d' % [selected],
123
- '',
124
- '<C>Press any key to continue.',
125
- ]
126
- rndkscreen.popup_label mesg
127
- end
128
-
129
- # Clean up
130
- RNDK::Screen.end_rndk
131
-
132
- # In case something goes wrong
133
- rescue Exception => e
134
- RNDK::Screen.end_rndk
135
-
136
- puts e
137
- puts e.inspect
138
- puts e.backtrace
139
- end
140
-
141
-
@@ -1,13 +0,0 @@
1
- require 'rndk/fscale'
2
-
3
- module RNDK
4
- class DSCALE < FSCALE
5
- # The original DScale handled unsigned values.
6
- # Since Ruby's typing is different this is really just FSCALE
7
- # but is nice it's nice to have this for compatibility/completeness
8
- # sake.
9
- def object_type
10
- :DSCALE
11
- end
12
- end
13
- end
@@ -1,938 +0,0 @@
1
- require 'rndk'
2
-
3
- module RNDK
4
- class FSELECT < Widget
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(rndkscreen, 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 = Ncurses.getmaxx(rndkscreen.window)
15
- parent_height = Ncurses.getmaxy(rndkscreen.window)
16
- bindings = {
17
- RNDK::BACKCHAR => Ncurses::KEY_PPAGE,
18
- RNDK::FORCHAR => Ncurses::KEY_NPAGE,
19
- }
20
-
21
- self.set_box(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 = RNDK.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 = RNDK.setWidgetDimension(parent_width, width, 0)
30
-
31
- # Rejustify the x and y positions if we need to.
32
- xtmp = [xplace]
33
- ytmp = [yplace]
34
- RNDK.alignxy(rndkscreen.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.newwin(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
- Ncurses.keypad(@win, true)
51
-
52
- # Set some variables.
53
- @screen = rndkscreen
54
- @parent = rndkscreen.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
- RNDK.char2Chtype(label, label_len, [])
80
- label_len = label_len[0]
81
-
82
- temp_width = if RNDK::FSELECT.isFullWidth(width)
83
- then RNDK::FULL
84
- else box_width - 2 - label_len
85
- end
86
- @entry_field = RNDK::Entry.new(rndkscreen, Ncurses.getbegx(@win), Ncurses.getbegy(@win),
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 = RNDK::Label.new(entry.screen, RNDK::CENTER, RNDK::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 = RNDK.dirName(filename)
169
- current_index = 0
170
-
171
- # Make sure the filename is not nil/empty.
172
- if filename.nil? || filename.size == 0
173
- RNDK.beep
174
- return true
175
- end
176
-
177
- # Try to expand the filename if it starts with a ~
178
- unless (new_filename = RNDK::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 = RNDK.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
- RNDK.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
- RNDK.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 = RNDK.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 = RNDK::DIALOG.new(fselect.screen, RNDK::CENTER, RNDK::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
- # popup_label(ScreenOf (fselect), (RNDK_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 = RNDK.chtype2Char(scrollp.item[scrollp.current_item])
338
- #current = RNDK.chtype2String(scrollp.item[scrollp.current_item])
339
- current = current[0...-1]
340
-
341
- temp = RNDK::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
- RNDK.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, RNDK::KEY_TAB, complete_filename_cb, self)
359
- @entry_field.bind(:entry, RNDK.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 = Ncurses.getmaxy(@entry_field.win) - @border_size
366
- temp_width = if RNDK::FSELECT.isFullWidth(width)
367
- then RNDK::FULL
368
- else box_width - 1
369
- end
370
- @scroll_field = RNDK::Scroll.new(rndkscreen,
371
- Ncurses.getbegx(@win), Ncurses.getbegy(@win) + temp_height, RNDK::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.newwin(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
- rndkscreen.register(:FSELECT, self)
391
- end
392
-
393
- # This erases the file selector from the screen.
394
- def erase
395
- if self.valid_widget?
396
- @scroll_field.erase
397
- @entry_field.erase
398
- RNDK.window_erase(@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.set_exit_type(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.set_exit_type(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.set_highlight(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 = RNDK::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
- RNDK.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.popup_label(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
- RNDK.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
- dir_list = RNDK.get_directory_contents @pwd
612
-
613
- return false if dir_list.size <= 0
614
-
615
- @dir_contents = dir_list
616
- @file_counter = file_count
617
-
618
- # Set the properties of the files.
619
- (0...@file_counter).each do |x|
620
- attr = ''
621
- mode = '?'
622
-
623
- # FIXME(original): access() would give a more correct answer
624
- # TODO: add error handling
625
- file_stat = File.stat(dir_list[x])
626
- if file_stat.executable?
627
- mode = '*'
628
- else
629
- mode = ' '
630
- end
631
-
632
- case
633
- when file_stat.symlink?
634
- attr = @link_attribute
635
- mode = '@'
636
- when file_stat.socket?
637
- attr = @sock_attribute
638
- mode = '&'
639
- when file_stat.file?
640
- attr = @file_attribute
641
- when file_stat.directory?
642
- attr = @dir_attribute
643
- mode = '/'
644
- end
645
- @dir_contents[x] = '%s%s%s' % [attr, dir_list[x], mode]
646
- end
647
- return true
648
- end
649
-
650
- def getDirContents(count)
651
- count << @file_counter
652
- return @dir_contents
653
- end
654
-
655
- # This sets the current directory of the file selector.
656
- def setDirectory(directory)
657
- fentry = @entry_field
658
- fscroll = @scroll_field
659
- result = 1
660
-
661
- # If the directory supplied is the same as what is already there, return.
662
- if @pwd != directory
663
- # Try to chdir into the given directory.
664
- if Dir.chdir(directory) != 0
665
- result = 0
666
- else
667
- @pwd = Dir.getwd
668
-
669
- # Set the contents of the entry field.
670
- fentry.setValue(@pwd)
671
- fentry.draw(fentry.box)
672
-
673
- # Get the directory contents.
674
- if self.setDirContents
675
- # Set the values in the scrolling list.
676
- fscroll.setItems(@dir_contents, @file_counter, false)
677
- else
678
- result = 0
679
- end
680
- end
681
- end
682
- return result
683
- end
684
-
685
- def getDirectory
686
- return @pwd
687
- end
688
-
689
- # This sets the filler character of the entry field.
690
- def setFillerChar(filler)
691
- @filler_character = filler
692
- @entry_field.setFillerChar(filler)
693
- end
694
-
695
- def getFillerChar
696
- return @filler_character
697
- end
698
-
699
- # This sets the highlight bar of the scrolling list.
700
- def set_highlight(highlight)
701
- @highlight = highlight
702
- @scroll_field.set_highlight(highlight)
703
- end
704
-
705
- def getHighlight
706
- return @highlight
707
- end
708
-
709
- # This sets the attribute of the directory attribute in the
710
- # scrolling list.
711
- def setDirAttribute(attribute)
712
- # Make sure they are not the same.
713
- if @dir_attribute != attribute
714
- @dir_attribute = attribute
715
- self.setDirContents
716
- end
717
- end
718
-
719
- def getDirAttribute
720
- return @dir_attribute
721
- end
722
-
723
- # This sets the attribute of the link attribute in the scrolling list.
724
- def setLinkAttribute(attribute)
725
- # Make sure they are not the same.
726
- if @link_attribute != attribute
727
- @link_attribute = attribute
728
- self.setDirContents
729
- end
730
- end
731
-
732
- def getLinkAttribute
733
- return @link_attribute
734
- end
735
-
736
- # This sets the attribute of the socket attribute in the scrolling list.
737
- def setSocketAttribute(attribute)
738
- # Make sure they are not the same.
739
- if @sock_attribute != attribute
740
- @sock_attribute = attribute
741
- self.setDirContents
742
- end
743
- end
744
-
745
- def getSocketAttribute
746
- return @sock_attribute
747
- end
748
-
749
- # This sets the attribute of the file attribute in the scrolling list.
750
- def setFileAttribute(attribute)
751
- # Make sure they are not the same.
752
- if @file_attribute != attribute
753
- @file_attribute = attribute
754
- self.setDirContents
755
- end
756
- end
757
-
758
- def getFileAttribute
759
- return @file_attribute
760
- end
761
-
762
- # this sets the contents of the widget
763
- def setContents(list, list_size)
764
- scrollp = @scroll_field
765
- entry = @entry_field
766
-
767
- if !self.createList(list, list_size)
768
- return
769
- end
770
-
771
- # Set the information in the scrolling list.
772
- scrollp.set(@dir_contents, @file_counter, false, scrollp.highlight,
773
- scrollp.box)
774
-
775
- # Clean out the entry field.
776
- self.setCurrentItem(0)
777
- entry.clean
778
-
779
- # Redraw the widget.
780
- self.erase
781
- self.draw(@box)
782
- end
783
-
784
- def getContents(size)
785
- size << @file_counter
786
- return @dir_contents
787
- end
788
-
789
- # Get/set the current position in the scroll wiget.
790
- def getCurrentItem
791
- return @scroll_field.getCurrent
792
- end
793
-
794
- def setCurrentItem(item)
795
- if @file_counter != 0
796
- @scroll_field.setCurrent(item)
797
-
798
- data = self.contentToPath(@dir_contents[@scroll_field.getCurrentItem])
799
- @entry_field.setValue(data)
800
- end
801
- end
802
-
803
- # These functions set the draw characters of the widget.
804
- def setMyULchar(character)
805
- @entry_field.setULchar(character)
806
- end
807
-
808
- def setMyURchar(character)
809
- @entry_field.setURchar(character)
810
- end
811
-
812
- def setMyLLchar(character)
813
- @scroll_field.setLLchar(character)
814
- end
815
-
816
- def setMyLRchar(character)
817
- @scroll_field.setLRchar(character)
818
- end
819
-
820
- def setMyVTchar(character)
821
- @entry_field.setVTchar(character)
822
- @scroll_field.setVTchar(character)
823
- end
824
-
825
- def setMyHZchar(character)
826
- @entry_field.setHZchar(character)
827
- @scroll_field.setHZchar(character)
828
- end
829
-
830
- def setMyBXattr(character)
831
- @entry_field.setBXattr(character)
832
- @scroll_field.setBXattr(character)
833
- end
834
-
835
- # This sets the background attribute of the widget.
836
- def set_bg_attrib(attrib)
837
- @entry_field.set_bg_attrib(attrib)
838
- @scroll_field.set_bg_attrib(attrib)
839
- end
840
-
841
- # This destroys the file selector.
842
- def destroy
843
- self.clean_bindings(:FSELECT)
844
-
845
- # Destroy the other RNDK objects
846
- @scroll_field.destroy
847
- @entry_field.destroy
848
-
849
- # Free up the windows
850
- RNDK.window_delete(@shadow_win)
851
- RNDK.window_delete(@win)
852
-
853
- # Clean the key bindings.
854
- # Unregister the object.
855
- RNDK::Screen.unregister(:FSELECT, self)
856
- end
857
-
858
- # Currently a wrapper for File.expand_path
859
- def self.make_pathname(directory, filename)
860
- if filename == '..'
861
- return File.expand_path(directory) + '/..'
862
- else
863
- return File.expand_path(filename, directory)
864
- end
865
- end
866
-
867
- # Return the plain string that corresponds to an item in dir_contents
868
- def contentToPath(content)
869
- # XXX direct translation of original but might be redundant
870
- temp_chtype = RNDK.char2Chtype(content, [], [])
871
- temp_char = RNDK.chtype2Char(temp_chtype)
872
- temp_char = temp_char[0..-1]
873
-
874
- # Create the pathname.
875
- result = RNDK::FSELECT.make_pathname(@pwd, temp_char)
876
-
877
- return result
878
- end
879
-
880
- # Currently a wrapper for File.expand_path
881
- def self.expandTilde(filename)
882
- return File.expand_path(filename)
883
- end
884
-
885
- def destroyInfo
886
- @dir_contents = []
887
- @file_counter = 0
888
- end
889
-
890
- def createList(list, list_size)
891
- status = false
892
-
893
- if list_size >= 0
894
- newlist = []
895
-
896
- # Copy in the new information
897
- status = true
898
- (0...list_size).each do |x|
899
- newlist << list[x]
900
- if newlist[x] == 0
901
- status = false
902
- break
903
- end
904
- end
905
-
906
- if status
907
- self.destroyInfo
908
- @file_counter = list_size
909
- @dir_contents = newlist
910
- end
911
- else
912
- self.destroyInfo
913
- status = true
914
- end
915
- return status
916
- end
917
-
918
- def focus
919
- @entry_field.focus
920
- end
921
-
922
- def unfocus
923
- @entry_field.unfocus
924
- end
925
-
926
- def self.isFullWidth(width)
927
- width == RNDK::FULL || (Ncurses.COLS != 0 && width >= Ncurses.COLS)
928
- end
929
-
930
- def position
931
- super(@win)
932
- end
933
-
934
- def object_type
935
- :FSELECT
936
- end
937
- end
938
- end