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/scale.rb ADDED
@@ -0,0 +1,538 @@
1
+ require 'rndk'
2
+
3
+ module RNDK
4
+ class SCALE < RNDK::Widget
5
+ def initialize(rndkscreen, xplace, yplace, title, label, field_attr,
6
+ field_width, start, low, high, inc, fast_inc, box, shadow)
7
+ super()
8
+ parent_width = Ncurses.getmaxx(rndkscreen.window)
9
+ parent_height = Ncurses.getmaxy(rndkscreen.window)
10
+ bindings = {
11
+ 'u' => Ncurses::KEY_UP,
12
+ 'U' => Ncurses::KEY_PPAGE,
13
+ RNDK::BACKCHAR => Ncurses::KEY_PPAGE,
14
+ RNDK::FORCHAR => Ncurses::KEY_NPAGE,
15
+ 'g' => Ncurses::KEY_HOME,
16
+ '^' => Ncurses::KEY_HOME,
17
+ 'G' => Ncurses::KEY_END,
18
+ '$' => Ncurses::KEY_END,
19
+ }
20
+
21
+ self.setBox(box)
22
+
23
+ box_height = @border_size * 2 + 1
24
+ box_width = field_width + 2 * @border_size
25
+
26
+ # Set some basic values of the widget's data field.
27
+ @label = []
28
+ @label_len = 0
29
+ @label_win = nil
30
+
31
+ # If the field_width is a negative value, the field_width will
32
+ # be COLS-field_width, otherwise the field_width will be the
33
+ # given width.
34
+ field_width = RNDK.setWidgetDimension(parent_width, field_width, 0)
35
+ box_width = field_width + 2 * @border_size
36
+
37
+ # Translate the label string to a chtype array
38
+ unless label.nil?
39
+ label_len = []
40
+ @label = RNDK.char2Chtype(label, label_len, [])
41
+ @label_len = label_len[0]
42
+ box_width = @label_len + field_width + 2
43
+ end
44
+
45
+ old_width = box_width
46
+ box_width = self.setTitle(title, box_width)
47
+ horizontal_adjust = (box_width - old_width) / 2
48
+
49
+ box_height += @title_lines
50
+
51
+ # Make sure we didn't extend beyond the dimensions of the window.
52
+ box_width = [box_width, parent_width].min
53
+ box_height = [box_height, parent_height].min
54
+ field_width = [field_width,
55
+ box_width - @label_len - 2 * @border_size].min
56
+
57
+ # Rejustify the x and y positions if we need to.
58
+ xtmp = [xplace]
59
+ ytmp = [yplace]
60
+ RNDK.alignxy(rndkscreen.window, xtmp, ytmp, box_width, box_height)
61
+ xpos = xtmp[0]
62
+ ypos = ytmp[0]
63
+
64
+ # Make the widget's window.
65
+ @win = Ncurses.newwin(box_height, box_width, ypos, xpos)
66
+
67
+ # Is the main window nil?
68
+ if @win.nil?
69
+ self.destroy
70
+ return nil
71
+ end
72
+
73
+ # Create the widget's label window.
74
+ if @label.size > 0
75
+ @label_win = Ncurses.subwin(@win,
76
+ 1,
77
+ @label_len,
78
+ ypos + @title_lines + @border_size,
79
+ xpos + horizontal_adjust + @border_size)
80
+ if @label_win.nil?
81
+ self.destroy
82
+ return nil
83
+ end
84
+ end
85
+
86
+ # Create the widget's data field window.
87
+ @field_win = Ncurses.subwin(@win,
88
+ 1,
89
+ field_width,
90
+ ypos + @title_lines + @border_size,
91
+ xpos + @label_len + horizontal_adjust + @border_size)
92
+ if @field_win.nil?
93
+ self.destroy
94
+ return nil
95
+ end
96
+
97
+ Ncurses.keypad(@field_win, true)
98
+ Ncurses.keypad(@win, true)
99
+
100
+ # Create the widget's data field.
101
+ @screen = rndkscreen
102
+ @parent = rndkscreen.window
103
+ @shadow_win = nil
104
+ @box_width = box_width
105
+ @box_height = box_height
106
+ @field_width = field_width
107
+ @field_attr = field_attr
108
+ @current = low
109
+ @low = low
110
+ @high = high
111
+ @current = start
112
+ @inc = inc
113
+ @fastinc = fast_inc
114
+ @accepts_focus = true
115
+ @input_window = @win
116
+ @shadow = shadow
117
+ @field_edit = 0
118
+
119
+ # Do we want a shadow?
120
+ if shadow
121
+ @shadow_win = Ncurses.newwin(box_height,
122
+ box_width,
123
+ ypos + 1,
124
+ xpos + 1)
125
+ if @shadow_win.nil?
126
+ self.destroy
127
+ return nil
128
+ end
129
+ end
130
+
131
+ # Setup the key bindings.
132
+ bindings.each do |from, to|
133
+ self.bind(self.object_type, from, :getc, to)
134
+ end
135
+
136
+ rndkscreen.register(self.object_type, self)
137
+ end
138
+
139
+ # This allows the person to use the widget's data field.
140
+ def activate(actions)
141
+ ret = -1
142
+ # Draw the widget.
143
+ self.draw(@box)
144
+
145
+ if actions.nil? || actions.size == 0
146
+ input = 0
147
+ while true
148
+ input = self.getch([])
149
+
150
+ # Inject the character into the widget.
151
+ ret = self.inject(input)
152
+ if @exit_type != :EARLY_EXIT
153
+ return ret
154
+ end
155
+ end
156
+ else
157
+ # Inject each character one at a time.
158
+ actions.each do |action|
159
+ ret = self.inject(action)
160
+ end
161
+ if @exit_type != :EARLY_EXIT
162
+ return ret
163
+ end
164
+ end
165
+
166
+ # Set the exit type and return.
167
+ self.setExitType(0)
168
+ return ret
169
+ end
170
+
171
+ # Check if the value lies outsid the low/high range. If so, force it in.
172
+ def limitCurrentValue
173
+ if @current < @low
174
+ @current = @low
175
+ RNDK.beep
176
+ elsif @current > @high
177
+ @current = @high
178
+ RNDK.beep
179
+ end
180
+ end
181
+
182
+ # Move the cursor to the given edit-position
183
+ def moveToEditPosition(new_position)
184
+ return Ncurses.wmove(@field_win, 0, @field_width - new_position - 1)
185
+ end
186
+
187
+ # Check if the cursor is on a valid edit-position. This must be one of
188
+ # the non-blank cells in the field.
189
+ def validEditPosition(new_position)
190
+ if new_position <= 0 || new_position >= @field_width
191
+ return false
192
+ end
193
+ if self.moveToEditPosition(new_position) == Ncurses::ERR
194
+ return false
195
+ end
196
+ ch = Ncurses.winch(@field_win)
197
+ if ch.chr != ' '
198
+ return true
199
+ end
200
+ if new_position > 1
201
+ # Don't use recursion - only one level is wanted
202
+ if self.moveToEditPosition(new_position - 1) == Ncurses::ERR
203
+ return false
204
+ end
205
+ ch = Ncurses.winch(@field_win)
206
+ return ch.chr != ' '
207
+ end
208
+ return false
209
+ end
210
+
211
+ # Set the edit position. Normally the cursor is one cell to the right of
212
+ # the editable field. Moving it left over the field allows the user to
213
+ # modify cells by typing in replacement characters for the field's value.
214
+ def setEditPosition(new_position)
215
+ if new_position < 0
216
+ RNDK.beep
217
+ elsif new_position == 0
218
+ @field_edit = new_position
219
+ elsif self.validEditPosition(new_position)
220
+ @field_edit = new_position
221
+ else
222
+ RNDK.beep
223
+ end
224
+ end
225
+
226
+ # Remove the character from the string at the given column, if it is blank.
227
+ # Returns true if a change was made.
228
+ def self.removeChar(string, col)
229
+ result = false
230
+ if col >= 0 && string[col] != ' '
231
+ while col < string.size - 1
232
+ string[col] = string[col + 1]
233
+ col += 1
234
+ end
235
+ string.chop!
236
+ result = true
237
+ end
238
+ return result
239
+ end
240
+
241
+ # Perform an editing function for the field.
242
+ def performEdit(input)
243
+ result = false
244
+ modify = true
245
+ base = 0
246
+ need = @field_width
247
+ temp = ''
248
+ col = need - @field_edit - 1
249
+
250
+ Ncurses.wmove(@field_win, 0, base)
251
+ Ncurses.winnstr(@field_win, temp, need)
252
+ temp << ' '
253
+ if RNDK.isChar(input) # Replace the char at the cursor
254
+ temp[col] = input.chr
255
+ elsif input == Ncurses::KEY_BACKSPACE
256
+ # delete the char before the cursor
257
+ modify = RNDK::SCALE.removeChar(temp, col - 1)
258
+ elsif input == Ncurses::KEY_DC
259
+ # delete the char at the cursor
260
+ modify = RNDK::SCALE.removeChar(temp, col)
261
+ else
262
+ modify = false
263
+ end
264
+ if modify &&
265
+ ((value, test) = temp.scanf(self.SCAN_FMT)).size == 2 &&
266
+ test == ' ' &&
267
+ value >= @low && value <= @high
268
+ self.setValue(value)
269
+ result = true
270
+ end
271
+
272
+ return result
273
+ end
274
+
275
+ def self.Decrement(value, by)
276
+ if value - by < value
277
+ value - by
278
+ else
279
+ value
280
+ end
281
+ end
282
+
283
+ def self.Increment(value, by)
284
+ if value + by > value
285
+ value + by
286
+ else
287
+ value
288
+ end
289
+ end
290
+
291
+ # This function injects a single character into the widget.
292
+ def inject(input)
293
+ pp_return = 1
294
+ ret = -1
295
+ complete = false
296
+
297
+ # Set the exit type.
298
+ self.setExitType(0)
299
+
300
+ # Draw the field.
301
+ self.drawField
302
+
303
+ # Check if there is a pre-process function to be called.
304
+ unless @pre_process_func.nil?
305
+ # Call the pre-process function.
306
+ pp_return = @pre_process_func.call(self.object_type, self,
307
+ @pre_process_data, input)
308
+ end
309
+
310
+ # Should we continue?
311
+ if pp_return != 0
312
+ # Check for a key bindings.
313
+ if self.checkBind(self.object_type, input)
314
+ complete = true
315
+ else
316
+ case input
317
+ when Ncurses::KEY_LEFT
318
+ self.setEditPosition(@field_edit + 1)
319
+ when Ncurses::KEY_RIGHT
320
+ self.setEditPosition(@field_edit - 1)
321
+ when Ncurses::KEY_DOWN
322
+ @current = RNDK::SCALE.Decrement(@current, @inc)
323
+ when Ncurses::KEY_UP
324
+ @current = RNDK::SCALE.Increment(@current, @inc)
325
+ when Ncurses::KEY_PPAGE
326
+ @current = RNDK::SCALE.Increment(@current, @fastinc)
327
+ when Ncurses::KEY_NPAGE
328
+ @current = RNDK::SCALE.Decrement(@current, @fastinc)
329
+ when Ncurses::KEY_HOME
330
+ @current = @low
331
+ when Ncurses::KEY_END
332
+ @current = @high
333
+ when RNDK::KEY_TAB, RNDK::KEY_RETURN, Ncurses::KEY_ENTER
334
+ self.setExitType(input)
335
+ ret = @current
336
+ complete = true
337
+ when RNDK::KEY_ESC
338
+ self.setExitType(input)
339
+ complete = true
340
+ when Ncurses::ERR
341
+ self.setExitType(input)
342
+ complete = true
343
+ when RNDK::REFRESH
344
+ @screen.erase
345
+ @screen.refresh
346
+ else
347
+ if @field_edit != 0
348
+ if !self.performEdit(input)
349
+ RNDK.beep
350
+ end
351
+ else
352
+ # The cursor is not within the editable text. Interpret
353
+ # input as commands.
354
+ case input
355
+ when 'd'.ord, '-'.ord
356
+ return self.inject(Ncurses::KEY_DOWN)
357
+ when '+'.ord
358
+ return self.inject(Ncurses::KEY_UP)
359
+ when 'D'.ord
360
+ return self.inject(Ncurses::KEY_NPAGE)
361
+ when '0'.ord
362
+ return self.inject(Ncurses::KEY_HOME)
363
+ else
364
+ RNDK.beep
365
+ end
366
+ end
367
+ end
368
+ end
369
+ self.limitCurrentValue
370
+
371
+ # Should we call a post-process?
372
+ if !complete && !(@post_process_func).nil?
373
+ @post_process_func.call(self.object_type, self,
374
+ @post_process_data, input)
375
+ end
376
+ end
377
+
378
+ if !complete
379
+ self.drawField
380
+ self.setExitType(0)
381
+ end
382
+
383
+ @result_data = ret
384
+ return ret
385
+ end
386
+
387
+ # This moves the widget's data field to the given location.
388
+ def move(xplace, yplace, relative, refresh_flag)
389
+ windows = [@win, @label_win, @field_win, @shadow_win]
390
+
391
+ self.move_specific(xplace, yplace, relative, refresh_flag, windows, [])
392
+ end
393
+
394
+ # This function draws the widget.
395
+ def draw(box)
396
+ # Draw the shadow.
397
+ unless @shadow_win.nil?
398
+ Draw.drawShadow(@shadow_win)
399
+ end
400
+
401
+ # Box the widget if asked.
402
+ if box
403
+ Draw.drawObjBox(@win, self)
404
+ end
405
+
406
+ self.drawTitle(@win)
407
+
408
+ # Draw the label.
409
+ unless @label_win.nil?
410
+ Draw.writeChtype(@label_win,
411
+ 0,
412
+ 0,
413
+ @label, RNDK::HORIZONTAL,
414
+ 0,
415
+ @label_len)
416
+ Ncurses.wrefresh(@label_win)
417
+ end
418
+ Ncurses.wrefresh @win
419
+
420
+ # Draw the field window.
421
+ self.drawField
422
+ end
423
+
424
+ # This draws the widget.
425
+ def drawField
426
+ Ncurses.werase(@field_win)
427
+
428
+ # Draw the value in the field.
429
+ temp = @current.to_s
430
+ Draw.writeCharAttrib(@field_win,
431
+ @field_width - temp.size - 1,
432
+ 0,
433
+ temp,
434
+ @field_attr,
435
+ RNDK::HORIZONTAL,
436
+ 0,
437
+ temp.size)
438
+
439
+ self.moveToEditPosition(@field_edit)
440
+ Ncurses.wrefresh(@field_win)
441
+ end
442
+
443
+ # This sets the background attribute of teh widget.
444
+ def setBKattr attrib
445
+ Ncurses.wbkgd(@win, attrib)
446
+ Ncurses.wbkgd(@field_win, attrib)
447
+ Ncurses.wbkgd(@label_win, attrib) unless @label_win.nil?
448
+ end
449
+
450
+ # This function destroys the widget.
451
+ def destroy
452
+ self.cleanTitle
453
+ @label = []
454
+
455
+ # Clean up the windows.
456
+ RNDK.deleteCursesWindow @field_win
457
+ RNDK.deleteCursesWindow @label_win
458
+ RNDK.deleteCursesWindow @shadow_win
459
+ RNDK.deleteCursesWindow @win
460
+
461
+ # Clean the key bindings.
462
+ self.cleanBindings(self.object_type)
463
+
464
+ # Unregister this object
465
+ RNDK::Screen.unregister(self.object_type, self)
466
+ end
467
+
468
+ # This function erases the widget from the screen.
469
+ def erase
470
+ if self.validRNDKObject
471
+ RNDK.eraseCursesWindow @label_win
472
+ RNDK.eraseCursesWindow @field_win
473
+ RNDK.eraseCursesWindow @win
474
+ RNDK.eraseCursesWindow @shadow_win
475
+ end
476
+ end
477
+
478
+ # This function sets the low/high/current values of the widget.
479
+ def set(low, high, value, box)
480
+ self.setLowHigh(low, high)
481
+ self.setValue(value)
482
+ self.setBox(box)
483
+ end
484
+
485
+ # This sets the widget's value
486
+ def setValue(value)
487
+ @current = value
488
+ self.limitCurrentValue
489
+ end
490
+
491
+ def getValue
492
+ return @current
493
+ end
494
+
495
+ # This function sets the low/high values of the widget.
496
+ def setLowHigh(low, high)
497
+ # Make sure the values aren't out of bounds.
498
+ if low <= high
499
+ @low = low
500
+ @high = high
501
+ elsif low > high
502
+ @low = high
503
+ @high = low
504
+ end
505
+
506
+ # Make sure the user hasn't done something silly.
507
+ self.limitCurrentValue
508
+ end
509
+
510
+ def getLowValue
511
+ return @low
512
+ end
513
+
514
+ def getHighValue
515
+ return @high
516
+ end
517
+
518
+ def focus
519
+ self.draw(@box)
520
+ end
521
+
522
+ def unfocus
523
+ self.draw(@box)
524
+ end
525
+
526
+ def position
527
+ super(@win)
528
+ end
529
+
530
+ def SCAN_FMT
531
+ '%d%c'
532
+ end
533
+
534
+ def object_type
535
+ :SCALE
536
+ end
537
+ end
538
+ end