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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/COPYING +137 -0
  4. data/Gemfile +4 -0
  5. data/README.md +100 -0
  6. data/Rakefile +3 -0
  7. data/TODO +68 -0
  8. data/demos/appointment.rb +346 -0
  9. data/demos/clock.rb +56 -0
  10. data/examples/01-hello-world.rb +56 -0
  11. data/examples/05-position-widget.rb +108 -0
  12. data/lib/rndk.rb +912 -0
  13. data/lib/rndk/alphalist.rb +572 -0
  14. data/lib/rndk/button.rb +370 -0
  15. data/lib/rndk/buttonbox.rb +359 -0
  16. data/lib/rndk/calendar.rb +766 -0
  17. data/lib/rndk/core/display.rb +63 -0
  18. data/lib/rndk/core/draw.rb +238 -0
  19. data/lib/rndk/core/quick_widgets.rb +106 -0
  20. data/lib/rndk/core/screen.rb +269 -0
  21. data/lib/rndk/core/traverse.rb +289 -0
  22. data/lib/rndk/core/widget.rb +506 -0
  23. data/lib/rndk/dialog.rb +367 -0
  24. data/lib/rndk/dscale.rb +13 -0
  25. data/lib/rndk/entry.rb +575 -0
  26. data/lib/rndk/fscale.rb +61 -0
  27. data/lib/rndk/fselect.rb +940 -0
  28. data/lib/rndk/fslider.rb +80 -0
  29. data/lib/rndk/graph.rb +401 -0
  30. data/lib/rndk/histogram.rb +412 -0
  31. data/lib/rndk/itemlist.rb +474 -0
  32. data/lib/rndk/label.rb +218 -0
  33. data/lib/rndk/marquee.rb +244 -0
  34. data/lib/rndk/matrix.rb +1189 -0
  35. data/lib/rndk/mentry.rb +619 -0
  36. data/lib/rndk/menu.rb +478 -0
  37. data/lib/rndk/radio.rb +538 -0
  38. data/lib/rndk/scale.rb +538 -0
  39. data/lib/rndk/scroll.rb +633 -0
  40. data/lib/rndk/scroller.rb +183 -0
  41. data/lib/rndk/selection.rb +630 -0
  42. data/lib/rndk/slider.rb +545 -0
  43. data/lib/rndk/swindow.rb +766 -0
  44. data/lib/rndk/template.rb +560 -0
  45. data/lib/rndk/uscale.rb +14 -0
  46. data/lib/rndk/uslider.rb +14 -0
  47. data/lib/rndk/version.rb +6 -0
  48. data/lib/rndk/viewer.rb +825 -0
  49. data/rndk.gemspec +35 -0
  50. 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