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
@@ -0,0 +1,633 @@
1
+ require 'rndk/scroller'
2
+
3
+ module RNDK
4
+ class SCROLL < RNDK::SCROLLER
5
+ attr_reader :item, :list_size, :current_item, :highlight
6
+
7
+ def initialize (rndkscreen, xplace, yplace, splace, height, width, title,
8
+ list, list_size, numbers, highlight, box, shadow)
9
+ super()
10
+ parent_width = Ncurses.getmaxx(rndkscreen.window)
11
+ parent_height = Ncurses.getmaxy(rndkscreen.window)
12
+ box_width = width
13
+ box_height = height
14
+ xpos = xplace
15
+ ypos = yplace
16
+ scroll_adjust = 0
17
+ bindings = {
18
+ RNDK::BACKCHAR => Ncurses::KEY_PPAGE,
19
+ RNDK::FORCHAR => Ncurses::KEY_NPAGE,
20
+ 'g' => Ncurses::KEY_HOME,
21
+ '1' => Ncurses::KEY_HOME,
22
+ 'G' => Ncurses::KEY_END,
23
+ '<' => Ncurses::KEY_HOME,
24
+ '>' => Ncurses::KEY_END
25
+ }
26
+
27
+ self.setBox(box)
28
+
29
+ # If the height is a negative value, the height will be ROWS-height,
30
+ # otherwise the height will be the given height
31
+ box_height = RNDK.setWidgetDimension(parent_height, height, 0)
32
+
33
+ # If the width is a negative value, the width will be COLS-width,
34
+ # otherwise the width will be the given width
35
+ box_width = RNDK.setWidgetDimension(parent_width, width, 0)
36
+
37
+ box_width = self.setTitle(title, box_width)
38
+
39
+ # Set the box height.
40
+ if @title_lines > box_height
41
+ box_height = @title_lines + [list_size, 8].min + 2 * @border_size
42
+ end
43
+
44
+ # Adjust the box width if there is a scroll bar
45
+ if splace == RNDK::LEFT || splace == RNDK::RIGHT
46
+ @scrollbar = true
47
+ box_width += 1
48
+ else
49
+ @scrollbar = false
50
+ end
51
+
52
+ # Make sure we didn't extend beyond the dimensions of the window.
53
+ @box_width = if box_width > parent_width
54
+ then parent_width - scroll_adjust
55
+ else box_width
56
+ end
57
+ @box_height = if box_height > parent_height
58
+ then parent_height
59
+ else box_height
60
+ end
61
+
62
+ self.setViewSize(list_size)
63
+
64
+ # Rejustify the x and y positions if we need to.
65
+ xtmp = [xpos]
66
+ ytmp = [ypos]
67
+ RNDK.alignxy(rndkscreen.window, xtmp, ytmp, @box_width, @box_height)
68
+ xpos = xtmp[0]
69
+ ypos = ytmp[0]
70
+
71
+ # Make the scrolling window
72
+ @win = Ncurses.newwin(@box_height, @box_width, ypos, xpos)
73
+
74
+ # Is the scrolling window null?
75
+ if @win.nil?
76
+ return nil
77
+ end
78
+
79
+ # Turn the keypad on for the window
80
+ Ncurses.keypad(@win, true)
81
+
82
+ # Create the scrollbar window.
83
+ if splace == RNDK::RIGHT
84
+ @scrollbar_win = Ncurses.subwin(@win, self.maxViewSize, 1,
85
+ self.Screen_YPOS(ypos), xpos + box_width - @border_size - 1)
86
+ elsif splace == RNDK::LEFT
87
+ @scrollbar_win = Ncurses.subwin(@win, self.maxViewSize, 1,
88
+ self.Screen_YPOS(ypos), self.Screen_XPOS(xpos))
89
+ else
90
+ @scrollbar_win = nil
91
+ end
92
+
93
+ # create the list window
94
+ @list_win = Ncurses.subwin(@win, self.maxViewSize,
95
+ box_width - (2 * @border_size) - scroll_adjust,
96
+ self.Screen_YPOS(ypos),
97
+ self.Screen_XPOS(xpos) + (if splace == RNDK::LEFT then 1 else 0 end))
98
+
99
+ # Set the rest of the variables
100
+ @screen = rndkscreen
101
+ @parent = rndkscreen.window
102
+ @shadow_win = nil
103
+ @scrollbar_placement = splace
104
+ @max_left_char = 0
105
+ @left_char = 0
106
+ @highlight = highlight
107
+ # initExitType (scrollp);
108
+ @accepts_focus = true
109
+ @input_window = @win
110
+ @shadow = shadow
111
+
112
+ self.setPosition(0);
113
+
114
+ # Create the scrolling list item list and needed variables.
115
+ if self.createItemList(numbers, list, list_size) <= 0
116
+ return nil
117
+ end
118
+
119
+ # Do we need to create a shadow?
120
+ if shadow
121
+ @shadow_win = Ncurses.newwin(@box_height, box_width,
122
+ ypos + 1, xpos + 1)
123
+ end
124
+
125
+ # Set up the key bindings.
126
+ bindings.each do |from, to|
127
+ #self.bind(:SCROLL, from, getc_lambda, to)
128
+ self.bind(:SCROLL, from, :getc, to)
129
+ end
130
+
131
+ rndkscreen.register(:SCROLL, self);
132
+
133
+ return self
134
+ end
135
+
136
+ def object_type
137
+ :SCROLL
138
+ end
139
+
140
+ def position
141
+ super(@win)
142
+ end
143
+
144
+ # Put the cursor on the currently-selected item's row.
145
+ def fixCursorPosition
146
+ scrollbar_adj = if @scrollbar_placement == LEFT then 1 else 0 end
147
+ ypos = self.Screen_YPOS(@current_item - @current_top)
148
+ xpos = self.Screen_XPOS(0) + scrollbar_adj
149
+
150
+ Ncurses.wmove(@input_window, ypos, xpos)
151
+ Ncurses.wrefresh(@input_window)
152
+ end
153
+
154
+ # This actually does all the 'real' work of managing the scrolling list.
155
+ def activate(actions)
156
+ # Draw the scrolling list
157
+ self.draw(@box)
158
+
159
+ if actions.nil? || actions.size == 0
160
+ while true
161
+ self.fixCursorPosition
162
+ input = self.getch([])
163
+
164
+ # Inject the character into the widget.
165
+ ret = self.inject(input)
166
+ if @exit_type != :EARLY_EXIT
167
+ return ret
168
+ end
169
+ end
170
+ else
171
+ # Inject each character one at a time.
172
+ actions.each do |action|
173
+ ret = self.inject(action)
174
+ if @exit_type != :EARLY_EXIT
175
+ return ret
176
+ end
177
+ end
178
+ end
179
+
180
+ # Set the exit type for the widget and return
181
+ self.setExitType(0)
182
+ return -1
183
+ end
184
+
185
+ # This injects a single character into the widget.
186
+ def inject(input)
187
+ pp_return = 1
188
+ ret = -1
189
+ complete = false
190
+
191
+ # Set the exit type for the widget.
192
+ self.setExitType(0)
193
+
194
+ # Draw the scrolling list
195
+ self.drawList(@box)
196
+
197
+ #Check if there is a pre-process function to be called.
198
+ unless @pre_process_func.nil?
199
+ pp_return = @pre_process_func.call(:SCROLL, self,
200
+ @pre_process_data, input)
201
+ end
202
+
203
+ # Should we continue?
204
+ if pp_return != 0
205
+ # Check for a predefined key binding.
206
+ if self.checkBind(:SCROLL, input) != false
207
+ #self.checkEarlyExit
208
+ complete = true
209
+ else
210
+ case input
211
+ when Ncurses::KEY_UP
212
+ self.KEY_UP
213
+ when Ncurses::KEY_DOWN
214
+ self.KEY_DOWN
215
+ when Ncurses::KEY_RIGHT
216
+ self.KEY_RIGHT
217
+ when Ncurses::KEY_LEFT
218
+ self.KEY_LEFT
219
+ when Ncurses::KEY_PPAGE
220
+ self.KEY_PPAGE
221
+ when Ncurses::KEY_NPAGE
222
+ self.KEY_NPAGE
223
+ when Ncurses::KEY_HOME
224
+ self.KEY_HOME
225
+ when Ncurses::KEY_END
226
+ self.KEY_END
227
+ when '$'
228
+ @left_char = @max_left_char
229
+ when '|'
230
+ @left_char = 0
231
+ when RNDK::KEY_ESC
232
+ self.setExitType(input)
233
+ complete = true
234
+ when Ncurses::ERR
235
+ self.setExitType(input)
236
+ complete = true
237
+ when RNDK::REFRESH
238
+ @screen.erase
239
+ @screen.refresh
240
+ when RNDK::KEY_TAB, Ncurses::KEY_ENTER, RNDK::KEY_RETURN
241
+ self.setExitType(input)
242
+ ret = @current_item
243
+ complete = true
244
+ end
245
+ end
246
+
247
+ if !complete && !(@post_process_func.nil?)
248
+ @post_process_func.call(:SCROLL, self, @post_process_data, input)
249
+ end
250
+ end
251
+
252
+ if !complete
253
+ self.drawList(@box)
254
+ self.setExitType(0)
255
+ end
256
+
257
+ self.fixCursorPosition
258
+ @result_data = ret
259
+
260
+ #return ret != -1
261
+ return ret
262
+ end
263
+
264
+ def getCurrentTop
265
+ return @current_top
266
+ end
267
+
268
+ def setCurrentTop(item)
269
+ if item < 0
270
+ item = 0
271
+ elsif item > @max_top_item
272
+ item = @max_top_item
273
+ end
274
+ @current_top = item
275
+
276
+ self.setPosition(item);
277
+ end
278
+
279
+ # This moves the scroll field to the given location.
280
+ def move(xplace, yplace, relative, refresh_flag)
281
+ windows = [@win, @list_win, @shadow_win, @scrollbar_win]
282
+ self.move_specific(xplace, yplace, relative, refresh_flag,
283
+ windows, [])
284
+ end
285
+
286
+ # This function draws the scrolling list widget.
287
+ def draw(box)
288
+ # Draw in the shadow if we need to.
289
+ unless @shadow_win.nil?
290
+ Draw.drawShadow(@shadow_win)
291
+ end
292
+
293
+ self.drawTitle(@win)
294
+
295
+ # Draw in the scrolling list items.
296
+ self.drawList(box)
297
+ end
298
+
299
+ def drawCurrent
300
+ # Rehighlight the current menu item.
301
+ screen_pos = @item_pos[@current_item] - @left_char
302
+ highlight = if self.has_focus
303
+ then @highlight
304
+ else Ncurses::A_NORMAL
305
+ end
306
+
307
+ Draw.writeChtypeAttrib(@list_win,
308
+ if screen_pos >= 0 then screen_pos else 0 end,
309
+ @current_high, @item[@current_item], highlight, RNDK::HORIZONTAL,
310
+ if screen_pos >= 0 then 0 else 1 - screen_pos end,
311
+ @item_len[@current_item])
312
+ end
313
+
314
+ def drawList(box)
315
+ # If the list is empty, don't draw anything.
316
+ if @list_size > 0
317
+ # Redraw the list
318
+ (0...@view_size).each do |j|
319
+ k = j + @current_top
320
+
321
+ Draw.writeBlanks(@list_win, 0, j, RNDK::HORIZONTAL, 0,
322
+ @box_width - (2 * @border_size))
323
+
324
+ # Draw the elements in the scrolling list.
325
+ if k < @list_size
326
+ screen_pos = @item_pos[k] - @left_char
327
+ ypos = j
328
+
329
+ # Write in the correct line.
330
+ Draw.writeChtype(@list_win,
331
+ if screen_pos >= 0 then screen_pos else 1 end,
332
+ ypos, @item[k], RNDK::HORIZONTAL,
333
+ if screen_pos >= 0 then 0 else 1 - screen_pos end,
334
+ @item_len[k])
335
+ end
336
+ end
337
+
338
+ self.drawCurrent
339
+
340
+ # Determine where the toggle is supposed to be.
341
+ unless @scrollbar_win.nil?
342
+ @toggle_pos = (@current_item * @step).floor
343
+
344
+ # Make sure the toggle button doesn't go out of bounds.
345
+ if @toggle_pos >= Ncurses.getmaxy(@scrollbar_win)
346
+ @toggle_pos = Ncurses.getmaxy(@scrollbar_win) - 1
347
+ end
348
+
349
+ # Draw the scrollbar
350
+ Ncurses.mvwvline(@scrollbar_win,
351
+ 0,
352
+ 0,
353
+ Ncurses::ACS_CKBOARD,
354
+ Ncurses.getmaxy(@scrollbar_win))
355
+
356
+ Ncurses.mvwvline(@scrollbar_win,
357
+ @toggle_pos,
358
+ 0,
359
+ ' '.ord | Ncurses::A_REVERSE,
360
+ @toggle_size)
361
+ end
362
+ end
363
+
364
+ # Box it if needed.
365
+ if box
366
+ Draw.drawObjBox(@win, self)
367
+ end
368
+
369
+ # Refresh the window
370
+ Ncurses.wrefresh @win
371
+ end
372
+
373
+ # This sets the background attribute of the widget.
374
+ def setBKattr(attrib)
375
+ Ncurses.wbkgd(@win, attrib)
376
+ Ncurses.wbkgd(@list_win, attrib)
377
+ unless @scrollbar_win.nil?
378
+ Ncurses.wbkgd(@scrollbar_win, attrib)
379
+ end
380
+ end
381
+
382
+ # This function destroys
383
+ def destroy
384
+ self.cleanTitle
385
+
386
+ # Clean up the windows.
387
+ RNDK.deleteCursesWindow(@scrollbar_win)
388
+ RNDK.deleteCursesWindow(@shadow_win)
389
+ RNDK.deleteCursesWindow(@list_win)
390
+ RNDK.deleteCursesWindow(@win)
391
+
392
+ # Clean the key bindings.
393
+ self.cleanBindings(:SCROLL)
394
+
395
+ # Unregister this object
396
+ RNDK::Screen.unregister(:SCROLL, self)
397
+ end
398
+
399
+ # This function erases the scrolling list from the screen.
400
+ def erase
401
+ RNDK.eraseCursesWindow(@win)
402
+ RNDK.eraseCursesWindow(@shadow_win)
403
+ end
404
+
405
+ def allocListArrays(old_size, new_size)
406
+ result = true
407
+ new_list = Array.new(new_size)
408
+ new_len = Array.new(new_size)
409
+ new_pos = Array.new(new_size)
410
+
411
+ (0...old_size).each do |n|
412
+ new_list[n] = @item[n]
413
+ new_len[n] = @item_len[n]
414
+ new_pos[n] = @item_pos[n]
415
+ end
416
+
417
+ @item = new_list
418
+ @item_len = new_len
419
+ @item_pos = new_pos
420
+
421
+ return result
422
+ end
423
+
424
+ def allocListItem(which, work, used, number, value)
425
+ if number > 0
426
+ value = "%4d. %s" % [number, value]
427
+ end
428
+
429
+ item_len = []
430
+ item_pos = []
431
+ @item[which] = RNDK.char2Chtype(value, item_len, item_pos)
432
+ @item_len[which] = item_len[0]
433
+ @item_pos[which] = item_pos[0]
434
+
435
+ @item_pos[which] = RNDK.justifyString(@box_width,
436
+ @item_len[which], @item_pos[which])
437
+ return true
438
+ end
439
+
440
+ # This function creates the scrolling list information and sets up the
441
+ # needed variables for the scrolling list to work correctly.
442
+ def createItemList(numbers, list, list_size)
443
+ status = 0
444
+ if list_size > 0
445
+ widest_item = 0
446
+ x = 0
447
+ have = 0
448
+ temp = ''
449
+ if allocListArrays(0, list_size)
450
+ # Create the items in the scrolling list.
451
+ status = 1
452
+ (0...list_size).each do |x|
453
+ number = if numbers then x + 1 else 0 end
454
+ if !self.allocListItem(x, temp, have, number, list[x])
455
+ status = 0
456
+ break
457
+ end
458
+
459
+ widest_item = [@item_len[x], widest_item].max
460
+ end
461
+
462
+ if status
463
+ self.updateViewWidth(widest_item);
464
+
465
+ # Keep the boolean flag 'numbers'
466
+ @numbers = numbers
467
+ end
468
+ end
469
+ else
470
+ status = 1 # null list is ok - for a while
471
+ end
472
+
473
+ return status
474
+ end
475
+
476
+ # This sets certain attributes of the scrolling list.
477
+ def set(list, list_size, numbers, highlight, box)
478
+ self.setItems(list, list_size, numbers)
479
+ self.setHighlight(highlight)
480
+ self.setBox(box)
481
+ end
482
+
483
+ # This sets the scrolling list items
484
+ def setItems(list, list_size, numbers)
485
+ if self.createItemList(numbers, list, list_size) <= 0
486
+ return
487
+ end
488
+
489
+ # Clean up the display.
490
+ (0...@view_size).each do |x|
491
+ Draw.writeBlanks(@win, 1, x, RNDK::HORIZONTAL, 0, @box_width - 2);
492
+ end
493
+
494
+ self.setViewSize(list_size)
495
+ self.setPosition(0)
496
+ @left_char = 0
497
+ end
498
+
499
+ def getItems(list)
500
+ (0...@list_size).each do |x|
501
+ list << RNDK.chtype2Char(@item[x])
502
+ end
503
+
504
+ return @list_size
505
+ end
506
+
507
+ # This sets the highlight of the scrolling list.
508
+ def setHighlight(highlight)
509
+ @highlight = highlight
510
+ end
511
+
512
+ def getHighlight(highlight)
513
+ return @highlight
514
+ end
515
+
516
+ # Resequence the numbers after an insertion/deletion.
517
+ def resequence
518
+ if @numbers
519
+ (0...@list_size).each do |j|
520
+ target = @item[j]
521
+
522
+ source = "%4d. %s" % [j + 1, ""]
523
+
524
+ k = 0
525
+ while k < source.size
526
+ # handle deletions that change the length of number
527
+ if source[k] == "." && target[k] != "."
528
+ source = source[0...k] + source[k+1..-1]
529
+ end
530
+
531
+ target[k] &= Ncurses::A_ATTRIBUTES
532
+ target[k] |= source[k].ord
533
+ k += 1
534
+ end
535
+ end
536
+ end
537
+ end
538
+
539
+ def insertListItem(item)
540
+ @item = @item[0..item] + @item[item..-1]
541
+ @item_len = @item_len[0..item] + @item_len[item..-1]
542
+ @item_pos = @item_pos[0..item] + @item_pos[item..-1]
543
+ return true
544
+ end
545
+
546
+ # This adds a single item to a scrolling list, at the end of the list.
547
+ def addItem(item)
548
+ item_number = @list_size
549
+ widest_item = self.WidestItem
550
+ temp = ''
551
+ have = 0
552
+
553
+ if self.allocListArrays(@list_size, @list_size + 1) &&
554
+ self.allocListItem(item_number, temp, have,
555
+ if @numbers then item_number + 1 else 0 end,
556
+ item)
557
+ # Determine the size of the widest item.
558
+ widest_item = [@item_len[item_number], widest_item].max
559
+
560
+ self.updateViewWidth(widest_item)
561
+ self.setViewSize(@list_size + 1)
562
+ end
563
+ end
564
+
565
+ # This adds a single item to a scrolling list before the current item
566
+ def insertItem(item)
567
+ widest_item = self.WidestItem
568
+ temp = ''
569
+ have = 0
570
+
571
+ if self.allocListArrays(@list_size, @list_size + 1) &&
572
+ self.insertListItem(@current_item) &&
573
+ self.allocListItem(@current_item, temp, have,
574
+ if @numbers then @current_item + 1 else 0 end,
575
+ item)
576
+ # Determine the size of the widest item.
577
+ widest_item = [@item_len[@current_item], widest_item].max
578
+
579
+ self.updateViewWidth(widest_item)
580
+ self.setViewSize(@list_size + 1)
581
+ self.resequence
582
+ end
583
+ end
584
+
585
+ # This removes a single item from a scrolling list.
586
+ def deleteItem(position)
587
+ if position >= 0 && position < @list_size
588
+ # Adjust the list
589
+ @item = @item[0...position] + @item[position+1..-1]
590
+ @item_len = @item_len[0...position] + @item_len[position+1..-1]
591
+ @item_pos = @item_pos[0...position] + @item_pos[position+1..-1]
592
+
593
+ self.setViewSize(@list_size - 1)
594
+
595
+ if @list_size > 0
596
+ self.resequence
597
+ end
598
+
599
+ if @list_size < self.maxViewSize
600
+ @win.werase # force the next redraw to be complete
601
+ end
602
+
603
+ # do this to update the view size, etc
604
+ self.setPosition(@current_item)
605
+ end
606
+ end
607
+
608
+ def focus
609
+ self.drawCurrent
610
+ Ncurses.wrefresh @list_win
611
+ end
612
+
613
+ def unfocus
614
+ self.drawCurrent
615
+ Ncurses.wrefresh @list_win
616
+ end
617
+
618
+ def AvailableWidth
619
+ @box_width - (2 * @border_size)
620
+ end
621
+
622
+ def updateViewWidth(widest)
623
+ @max_left_char = if @box_width > widest
624
+ then 0
625
+ else widest - self.AvailableWidth
626
+ end
627
+ end
628
+
629
+ def WidestItem
630
+ @max_left_char + self.AvailableWidth
631
+ end
632
+ end
633
+ end