rndk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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