rndk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/COPYING +137 -0
- data/Gemfile +4 -0
- data/README.md +100 -0
- data/Rakefile +3 -0
- data/TODO +68 -0
- data/demos/appointment.rb +346 -0
- data/demos/clock.rb +56 -0
- data/examples/01-hello-world.rb +56 -0
- data/examples/05-position-widget.rb +108 -0
- data/lib/rndk.rb +912 -0
- data/lib/rndk/alphalist.rb +572 -0
- data/lib/rndk/button.rb +370 -0
- data/lib/rndk/buttonbox.rb +359 -0
- data/lib/rndk/calendar.rb +766 -0
- data/lib/rndk/core/display.rb +63 -0
- data/lib/rndk/core/draw.rb +238 -0
- data/lib/rndk/core/quick_widgets.rb +106 -0
- data/lib/rndk/core/screen.rb +269 -0
- data/lib/rndk/core/traverse.rb +289 -0
- data/lib/rndk/core/widget.rb +506 -0
- data/lib/rndk/dialog.rb +367 -0
- data/lib/rndk/dscale.rb +13 -0
- data/lib/rndk/entry.rb +575 -0
- data/lib/rndk/fscale.rb +61 -0
- data/lib/rndk/fselect.rb +940 -0
- data/lib/rndk/fslider.rb +80 -0
- data/lib/rndk/graph.rb +401 -0
- data/lib/rndk/histogram.rb +412 -0
- data/lib/rndk/itemlist.rb +474 -0
- data/lib/rndk/label.rb +218 -0
- data/lib/rndk/marquee.rb +244 -0
- data/lib/rndk/matrix.rb +1189 -0
- data/lib/rndk/mentry.rb +619 -0
- data/lib/rndk/menu.rb +478 -0
- data/lib/rndk/radio.rb +538 -0
- data/lib/rndk/scale.rb +538 -0
- data/lib/rndk/scroll.rb +633 -0
- data/lib/rndk/scroller.rb +183 -0
- data/lib/rndk/selection.rb +630 -0
- data/lib/rndk/slider.rb +545 -0
- data/lib/rndk/swindow.rb +766 -0
- data/lib/rndk/template.rb +560 -0
- data/lib/rndk/uscale.rb +14 -0
- data/lib/rndk/uslider.rb +14 -0
- data/lib/rndk/version.rb +6 -0
- data/lib/rndk/viewer.rb +825 -0
- data/rndk.gemspec +35 -0
- metadata +141 -0
data/lib/rndk/menu.rb
ADDED
@@ -0,0 +1,478 @@
|
|
1
|
+
require 'rndk'
|
2
|
+
|
3
|
+
module RNDK
|
4
|
+
class MENU < RNDK::Widget
|
5
|
+
TITLELINES = 1
|
6
|
+
MAX_MENU_ITEMS = 30
|
7
|
+
MAX_SUB_ITEMS = 98
|
8
|
+
|
9
|
+
attr_reader :current_title, :current_subtitle
|
10
|
+
attr_reader :sublist
|
11
|
+
|
12
|
+
def initialize(rndkscreen,
|
13
|
+
menu_list,
|
14
|
+
menu_items,
|
15
|
+
subsize,
|
16
|
+
menu_location,
|
17
|
+
menu_pos,
|
18
|
+
title_attr,
|
19
|
+
subtitle_attr)
|
20
|
+
super()
|
21
|
+
|
22
|
+
right_count = menu_items - 1
|
23
|
+
rightloc = Ncurses.getmaxx rndkscreen.window
|
24
|
+
leftloc = 0
|
25
|
+
xpos = Ncurses.getbegx rndkscreen.window
|
26
|
+
ypos = Ncurses.getbegy rndkscreen.window
|
27
|
+
ymax = Ncurses.getmaxy rndkscreen.window
|
28
|
+
|
29
|
+
# Start making a copy of the information.
|
30
|
+
@screen = rndkscreen
|
31
|
+
@box = false
|
32
|
+
@accepts_focus = false
|
33
|
+
rightcount = menu_items - 1
|
34
|
+
@parent = rndkscreen.window
|
35
|
+
@menu_items = menu_items
|
36
|
+
@title_attr = title_attr
|
37
|
+
@subtitle_attr = subtitle_attr
|
38
|
+
@current_title = 0
|
39
|
+
@current_subtitle = 0
|
40
|
+
@last_selection = -1
|
41
|
+
@menu_pos = menu_pos
|
42
|
+
|
43
|
+
@pull_win = [nil] * menu_items
|
44
|
+
@title_win = [nil] * menu_items
|
45
|
+
@title = [''] * menu_items
|
46
|
+
@title_len = [0] * menu_items
|
47
|
+
@sublist = (1..menu_items).map {[nil] * subsize.max}.compact
|
48
|
+
@sublist_len = (1..menu_items).map {
|
49
|
+
[0] * subsize.max}.compact
|
50
|
+
@subsize = [0] * menu_items
|
51
|
+
|
52
|
+
|
53
|
+
# Create the pull down menus.
|
54
|
+
(0...menu_items).each do |x|
|
55
|
+
x1 = if menu_location[x] == RNDK::LEFT
|
56
|
+
then x
|
57
|
+
else
|
58
|
+
rightcount -= 1
|
59
|
+
rightcount + 1
|
60
|
+
end
|
61
|
+
x2 = 0
|
62
|
+
y1 = if menu_pos == RNDK::BOTTOM then ymax - 1 else 0 end
|
63
|
+
y2 = if menu_pos == RNDK::BOTTOM
|
64
|
+
then ymax - subsize[x] - 2
|
65
|
+
else RNDK::MENU::TITLELINES
|
66
|
+
end
|
67
|
+
high = subsize[x] + RNDK::MENU::TITLELINES
|
68
|
+
|
69
|
+
# Limit the menu height to fit on the screen.
|
70
|
+
if high + y2 > ymax
|
71
|
+
high = ymax - RNDK::MENU::TITLELINES
|
72
|
+
end
|
73
|
+
|
74
|
+
max = -1
|
75
|
+
(RNDK::MENU::TITLELINES...subsize[x]).to_a.each do |y|
|
76
|
+
y0 = y - RNDK::MENU::TITLELINES
|
77
|
+
sublist_len = []
|
78
|
+
@sublist[x1][y0] = RNDK.char2Chtype(menu_list[x][y],
|
79
|
+
sublist_len, [])
|
80
|
+
@sublist_len[x1][y0] = sublist_len[0]
|
81
|
+
max = [max, sublist_len[0]].max
|
82
|
+
end
|
83
|
+
|
84
|
+
if menu_location[x] == RNDK::LEFT
|
85
|
+
x2 = leftloc
|
86
|
+
else
|
87
|
+
x2 = (rightloc -= max + 2)
|
88
|
+
end
|
89
|
+
|
90
|
+
title_len = []
|
91
|
+
@title[x1] = RNDK.char2Chtype(menu_list[x][0], title_len, [])
|
92
|
+
@title_len[x1] = title_len[0]
|
93
|
+
@subsize[x1] = subsize[x] - RNDK::MENU::TITLELINES
|
94
|
+
@title_win[x1] = Ncurses.subwin(rndkscreen.window,
|
95
|
+
RNDK::MENU::TITLELINES,
|
96
|
+
@title_len[x1] + 2,
|
97
|
+
ypos + y1,
|
98
|
+
xpos + x2)
|
99
|
+
|
100
|
+
@pull_win[x1] = Ncurses.subwin(rndkscreen.window,
|
101
|
+
high,
|
102
|
+
max + 2,
|
103
|
+
ypos + y2,
|
104
|
+
xpos + x2)
|
105
|
+
|
106
|
+
if @title_win[x1].nil? || @pull_win[x1].nil?
|
107
|
+
self.destroy
|
108
|
+
return nil
|
109
|
+
end
|
110
|
+
|
111
|
+
leftloc += @title_len[x] + 1
|
112
|
+
Ncurses.keypad(@title_win[x1], true)
|
113
|
+
Ncurses.keypad(@pull_win[x1], true)
|
114
|
+
end
|
115
|
+
@input_window = @title_win[@current_title]
|
116
|
+
|
117
|
+
# Register this baby.
|
118
|
+
rndkscreen.register(:MENU, self)
|
119
|
+
end
|
120
|
+
|
121
|
+
# This activates the RNDK Menu
|
122
|
+
def activate(actions)
|
123
|
+
ret = 0
|
124
|
+
|
125
|
+
# Draw in the screen.
|
126
|
+
@screen.refresh
|
127
|
+
|
128
|
+
# Display the menu titles.
|
129
|
+
self.draw(@box)
|
130
|
+
|
131
|
+
# Highlight the current title and window.
|
132
|
+
self.drawSubwin
|
133
|
+
|
134
|
+
# If the input string is empty this is an interactive activate.
|
135
|
+
if actions.nil? || actions.size == 0
|
136
|
+
@input_window = @title_win[@current_title]
|
137
|
+
|
138
|
+
# Start taking input from the keyboard.
|
139
|
+
while true
|
140
|
+
input = self.getch([])
|
141
|
+
|
142
|
+
# Inject the character into the widget.
|
143
|
+
ret = self.inject(input)
|
144
|
+
if @exit_type != :EARLY_EXIT
|
145
|
+
return ret
|
146
|
+
end
|
147
|
+
end
|
148
|
+
else
|
149
|
+
actions.each do |action|
|
150
|
+
if @exit_type != :EARLY_EXIT
|
151
|
+
return ret
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Set the exit type and return.
|
157
|
+
self.setExitType(0)
|
158
|
+
return -1
|
159
|
+
end
|
160
|
+
|
161
|
+
def drawTitle(item)
|
162
|
+
Draw.writeChtype(@title_win[item],
|
163
|
+
0,
|
164
|
+
0,
|
165
|
+
@title[item],
|
166
|
+
RNDK::HORIZONTAL,
|
167
|
+
0,
|
168
|
+
@title_len[item])
|
169
|
+
end
|
170
|
+
|
171
|
+
def drawItem(item, offset)
|
172
|
+
Draw.writeChtype(@pull_win[@current_title],
|
173
|
+
1,
|
174
|
+
item + RNDK::MENU::TITLELINES - offset,
|
175
|
+
@sublist[@current_title][item],
|
176
|
+
RNDK::HORIZONTAL,
|
177
|
+
0,
|
178
|
+
@sublist_len[@current_title][item])
|
179
|
+
end
|
180
|
+
|
181
|
+
# Highlight the current sub-menu item
|
182
|
+
def selectItem(item, offset)
|
183
|
+
Draw.writeChtypeAttrib(@pull_win[@current_title],
|
184
|
+
1,
|
185
|
+
item + RNDK::MENU::TITLELINES - offset,
|
186
|
+
@sublist[@current_title][item],
|
187
|
+
@subtitle_attr,
|
188
|
+
RNDK::HORIZONTAL,
|
189
|
+
0,
|
190
|
+
@sublist_len[@current_title][item])
|
191
|
+
end
|
192
|
+
|
193
|
+
def withinSubmenu(step)
|
194
|
+
next_item = RNDK::MENU.wrapped(@current_subtitle + step,
|
195
|
+
@subsize[@current_title])
|
196
|
+
|
197
|
+
if next_item != @current_subtitle
|
198
|
+
ymax = Ncurses.getmaxy(@screen.window)
|
199
|
+
|
200
|
+
if 1 + Ncurses.getbegy(@pull_win[@current_title]) + @subsize[@current_title] >= ymax
|
201
|
+
@current_subtitle = next_item
|
202
|
+
self.drawSubwin
|
203
|
+
else
|
204
|
+
# Erase the old subtitle.
|
205
|
+
self.drawItem(@current_subtitle, 0)
|
206
|
+
|
207
|
+
# Set the values
|
208
|
+
@current_subtitle = next_item
|
209
|
+
|
210
|
+
# Draw the new sub-title.
|
211
|
+
self.selectItem(@current_subtitle, 0)
|
212
|
+
|
213
|
+
Ncurses.wrefresh @pull_win[@current_title]
|
214
|
+
end
|
215
|
+
|
216
|
+
@input_window = @title_win[@current_title]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def acrossSubmenus(step)
|
221
|
+
next_item = RNDK::MENU.wrapped(@current_title + step, @menu_items)
|
222
|
+
|
223
|
+
if next_item != @current_title
|
224
|
+
# Erase the menu sub-window.
|
225
|
+
self.eraseSubwin
|
226
|
+
@screen.refresh
|
227
|
+
|
228
|
+
# Set the values.
|
229
|
+
@current_title = next_item
|
230
|
+
@current_subtitle = 0
|
231
|
+
|
232
|
+
# Draw the new menu sub-window.
|
233
|
+
self.drawSubwin
|
234
|
+
@input_window = @title_win[@current_title]
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# Inject a character into the menu widget.
|
239
|
+
def inject(input)
|
240
|
+
pp_return = 1
|
241
|
+
ret = -1
|
242
|
+
complete = false
|
243
|
+
|
244
|
+
# Set the exit type.
|
245
|
+
self.setExitType(0)
|
246
|
+
|
247
|
+
# Check if there is a pre-process function to be called.
|
248
|
+
unless @pre_process_func.nil?
|
249
|
+
# Call the pre-process function.
|
250
|
+
pp_return = @pre_process_func.call(:MENU, self,
|
251
|
+
@pre_process_data, input)
|
252
|
+
end
|
253
|
+
|
254
|
+
# Should we continue?
|
255
|
+
|
256
|
+
if pp_return != 0
|
257
|
+
# Check for key bindings.
|
258
|
+
if self.checkBind(:MENU, input)
|
259
|
+
complete = true
|
260
|
+
else
|
261
|
+
case input
|
262
|
+
when Ncurses::KEY_LEFT
|
263
|
+
self.acrossSubmenus(-1)
|
264
|
+
when Ncurses::KEY_RIGHT, RNDK::KEY_TAB
|
265
|
+
self.acrossSubmenus(1)
|
266
|
+
when Ncurses::KEY_UP
|
267
|
+
self.withinSubmenu(-1)
|
268
|
+
when Ncurses::KEY_DOWN, ' '.ord
|
269
|
+
self.withinSubmenu(1)
|
270
|
+
when Ncurses::KEY_ENTER, RNDK::KEY_RETURN
|
271
|
+
self.cleanUpMenu
|
272
|
+
self.setExitType(input)
|
273
|
+
@last_selection = @current_title * 100 + @current_subtitle
|
274
|
+
ret = @last_selection
|
275
|
+
complete = true
|
276
|
+
when RNDK::KEY_ESC
|
277
|
+
self.cleanUpMenu
|
278
|
+
self.setExitType(input)
|
279
|
+
@last_selection = -1
|
280
|
+
ret = @last_selection
|
281
|
+
complete = true
|
282
|
+
when Ncurses::ERR
|
283
|
+
self.setExitType(input)
|
284
|
+
complete = true
|
285
|
+
when RNDK::REFRESH
|
286
|
+
self.erase
|
287
|
+
self.refresh
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Should we call a post-process?
|
292
|
+
if !complete && !(@post_process_func.nil?)
|
293
|
+
@post_process_func.call(:MENU, self, @post_process_data, input)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
if !complete
|
298
|
+
self.setExitType(0)
|
299
|
+
end
|
300
|
+
|
301
|
+
@result_data = ret
|
302
|
+
return ret
|
303
|
+
end
|
304
|
+
|
305
|
+
# Draw a menu item subwindow
|
306
|
+
def drawSubwin
|
307
|
+
high = Ncurses.getmaxy(@pull_win[@current_title]) - 2
|
308
|
+
x0 = 0
|
309
|
+
x1 = @subsize[@current_title]
|
310
|
+
|
311
|
+
if x1 > high
|
312
|
+
x1 = high
|
313
|
+
end
|
314
|
+
|
315
|
+
if @current_subtitle >= x1
|
316
|
+
x0 = @current_subtitle - x1 + 1
|
317
|
+
x1 += x0
|
318
|
+
end
|
319
|
+
|
320
|
+
# Box the window
|
321
|
+
@pull_win[@current_title]
|
322
|
+
Ncurses.box(@pull_win[@current_title], Ncurses::ACS_VLINE, Ncurses::ACS_HLINE)
|
323
|
+
if @menu_pos == RNDK::BOTTOM
|
324
|
+
Ncurses.mvwaddch(@pull_win[@current_title],
|
325
|
+
@subsize[@current_title] + 1,
|
326
|
+
0,
|
327
|
+
Ncurses::ACS_LTEE)
|
328
|
+
else
|
329
|
+
Ncurses.mvwaddch(@pull_win[@current_title],
|
330
|
+
0,
|
331
|
+
0,
|
332
|
+
Ncurses::ACS_LTEE)
|
333
|
+
end
|
334
|
+
|
335
|
+
# Draw the items.
|
336
|
+
(x0...x1).each do |x|
|
337
|
+
self.drawItem(x, x0)
|
338
|
+
end
|
339
|
+
|
340
|
+
self.selectItem(@current_subtitle, x0)
|
341
|
+
Ncurses.wrefresh @pull_win[@current_title]
|
342
|
+
|
343
|
+
# Highlight the title.
|
344
|
+
Draw.writeChtypeAttrib(@title_win[@current_title], 0, 0,
|
345
|
+
@title[@current_title], @title_attr, RNDK::HORIZONTAL,
|
346
|
+
0, @title_len[@current_title])
|
347
|
+
Ncurses.wrefresh @title_win[@current_title]
|
348
|
+
end
|
349
|
+
|
350
|
+
# Erase a menu item subwindow
|
351
|
+
def eraseSubwin
|
352
|
+
RNDK.eraseCursesWindow(@pull_win[@current_title])
|
353
|
+
|
354
|
+
# Redraw the sub-menu title.
|
355
|
+
self.drawTitle(@current_title)
|
356
|
+
Ncurses.wrefresh @title_win[@current_title]
|
357
|
+
end
|
358
|
+
|
359
|
+
# Draw the menu.
|
360
|
+
def draw(box)
|
361
|
+
# Draw in the menu titles.
|
362
|
+
(0...@menu_items).each do |x|
|
363
|
+
self.drawTitle(x)
|
364
|
+
Ncurses.wrefresh @title_win[x]
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
# Move the menu to the given location.
|
369
|
+
def move(xplace, yplace, relative, refresh_flag)
|
370
|
+
windows = [@screen.window]
|
371
|
+
(0...@menu_items).each do |x|
|
372
|
+
windows << @title_win[x]
|
373
|
+
end
|
374
|
+
self.move_specific(xplace, yplace, relative, refresh_flag,
|
375
|
+
windows, [])
|
376
|
+
end
|
377
|
+
|
378
|
+
# Set the background attribute of the widget.
|
379
|
+
def setBKattr(attrib)
|
380
|
+
(0...@menu_items).each do |x|
|
381
|
+
@title_win[x].wbkgd(attrib)
|
382
|
+
@pull_win[x].wbkgd(attrib)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
# Destroy a menu widget.
|
387
|
+
def destroy
|
388
|
+
# Clean up the windows
|
389
|
+
(0...@menu_items).each do |x|
|
390
|
+
RNDK.deleteCursesWindow(@title_win[x])
|
391
|
+
RNDK.deleteCursesWindow(@pull_win[x])
|
392
|
+
end
|
393
|
+
|
394
|
+
# Clean the key bindings.
|
395
|
+
self.cleanBindings(:MENU)
|
396
|
+
|
397
|
+
# Unregister the object
|
398
|
+
RNDK::Screen.unregister(:MENU, self)
|
399
|
+
end
|
400
|
+
|
401
|
+
# Erase the menu widget from the screen.
|
402
|
+
def erase
|
403
|
+
if self.validRNDKObject
|
404
|
+
(0...@menu_items).each do |x|
|
405
|
+
Ncurses.werase @title_win[x]
|
406
|
+
Ncurses.wrefresh @title_win[x]
|
407
|
+
Ncurses.werase @pull_win[x]
|
408
|
+
Ncurses.wrefresh @pull_win[x]
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
def set(menu_item, submenu_item, title_highlight, subtitle_highlight)
|
414
|
+
self.setCurrentItem(menu_item, submenu_item)
|
415
|
+
self.setTitleHighlight(title_highlight)
|
416
|
+
self.setSubTitleHighlight(subtitle_highlight)
|
417
|
+
end
|
418
|
+
|
419
|
+
# Set the current menu item to highlight.
|
420
|
+
def setCurrentItem(menuitem, submenuitem)
|
421
|
+
@current_title = RNDK::MENU.wrapped(menuitem, @menu_items)
|
422
|
+
@current_subtitle = RNDK::MENU.wrapped(
|
423
|
+
submenuitem, @subsize[@current_title])
|
424
|
+
end
|
425
|
+
|
426
|
+
def getCurrentItem(menu_item, submenu_item)
|
427
|
+
menu_item << @current_title
|
428
|
+
submenu_item << @current_subtitle
|
429
|
+
end
|
430
|
+
|
431
|
+
# Set the attribute of the menu titles.
|
432
|
+
def setTitleHighlight(highlight)
|
433
|
+
@title_attr = highlight
|
434
|
+
end
|
435
|
+
|
436
|
+
def getTitleHighlight
|
437
|
+
return @title_attr
|
438
|
+
end
|
439
|
+
|
440
|
+
# Set the attribute of the sub-title.
|
441
|
+
def setSubTitleHighlight(highlight)
|
442
|
+
@subtitle_attr = highlight
|
443
|
+
end
|
444
|
+
|
445
|
+
def getSubTitleHighlight
|
446
|
+
return @subtitle_attr
|
447
|
+
end
|
448
|
+
|
449
|
+
# Exit the menu.
|
450
|
+
def cleanUpMenu
|
451
|
+
# Erase the sub-menu.
|
452
|
+
self.eraseSubwin
|
453
|
+
Ncurses.wrefresh @pull_win[@current_title]
|
454
|
+
|
455
|
+
# Refresh the screen.
|
456
|
+
@screen.refresh
|
457
|
+
end
|
458
|
+
|
459
|
+
def focus
|
460
|
+
self.drawSubwin
|
461
|
+
@input_window = @title_win[@current_title]
|
462
|
+
end
|
463
|
+
|
464
|
+
# The "%" operator is simpler but does not handle negative values
|
465
|
+
def self.wrapped(within, limit)
|
466
|
+
if within < 0
|
467
|
+
within = limit - 1
|
468
|
+
elsif within >= limit
|
469
|
+
within = 0
|
470
|
+
end
|
471
|
+
return within
|
472
|
+
end
|
473
|
+
|
474
|
+
def object_type
|
475
|
+
:MENU
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|