rndk 0.2.0 → 1.0.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.
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