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,1189 @@
1
+ require 'rndk'
2
+
3
+ module RNDK
4
+ class MATRIX < RNDK::Widget
5
+ attr_accessor :info
6
+ attr_reader :colvalues, :row, :col, :colwidths, :filler
7
+ attr_reader :crow, :ccol
8
+ MAX_MATRIX_ROWS = 1000
9
+ MAX_MATRIX_COLS = 1000
10
+
11
+ @@g_paste_buffer = ''
12
+
13
+ def initialize(rndkscreen, xplace, yplace, rows, cols, vrows, vcols,
14
+ title, rowtitles, coltitles, colwidths, colvalues, rspace, cspace,
15
+ filler, dominant, box, box_cell, shadow)
16
+ super()
17
+ parent_width = Ncurses.getmaxx(rndkscreen.window)
18
+ parent_height = Ncurses.getmaxy(rndkscreen.window)
19
+ box_height = 0
20
+ box_width = 0
21
+ max_row_title_width = 0
22
+ row_space = [0, rspace].max
23
+ col_space = [0, cspace].max
24
+ begx = 0
25
+ begy = 0
26
+ cell_width = 0
27
+ have_rowtitles = false
28
+ have_coltitles = false
29
+ bindings = {
30
+ RNDK::FORCHAR => Ncurses::KEY_NPAGE,
31
+ RNDK::BACKCHAR => Ncurses::KEY_PPAGE,
32
+ }
33
+
34
+ self.setBox(box)
35
+ borderw = if @box then 1 else 0 end
36
+
37
+ # Make sure that the number of rows/cols/vrows/vcols is not zero.
38
+ if rows <= 0 || cols <= 0 || vrows <= 0 || vcols <= 0
39
+ self.destroy
40
+ return nil
41
+ end
42
+
43
+ @cell = Array.new(rows + 1) { |i| Array.new(cols + 1)}
44
+ @info = Array.new(rows + 1) { |i| Array.new(cols + 1) { |i| '' }}
45
+
46
+ # Make sure the number of virtual cells is not larger than the
47
+ # physical size.
48
+ vrows = [vrows, rows].min
49
+ vcols = [vcols, cols].min
50
+
51
+ @rows = rows
52
+ @cols = cols
53
+ @colwidths = [0] * (cols + 1)
54
+ @colvalues = [0] * (cols + 1)
55
+ @coltitle = Array.new(cols + 1) {|i| []}
56
+ @coltitle_len = [0] * (cols + 1)
57
+ @coltitle_pos = [0] * (cols + 1)
58
+ @rowtitle = Array.new(rows + 1) {|i| []}
59
+ @rowtitle_len = [0] * (rows + 1)
60
+ @rowtitle_pos = [0] * (rows + 1)
61
+
62
+ # Count the number of lines in the title
63
+ temp = title.split("\n")
64
+ @title_lines = temp.size
65
+
66
+ # Determine the height of the box.
67
+ if vrows == 1
68
+ box_height = 6 + @title_lines
69
+ else
70
+ if row_space == 0
71
+ box_height = 6 + @title_lines + (vrows - 1) * 2
72
+ else
73
+ box_height = 3 + @title_lines + vrows * 3 +
74
+ (vrows - 1) * (row_space - 1)
75
+ end
76
+ end
77
+
78
+ # Determine the maximum row title width.
79
+ (1..rows).each do |x|
80
+ if !(rowtitles.nil?) && x < rowtitles.size && rowtitles[x].size > 0
81
+ have_rowtitles = true
82
+ end
83
+ rowtitle_len = []
84
+ rowtitle_pos = []
85
+ @rowtitle[x] = RNDK.char2Chtype((rowtitles[x] || ''),
86
+ rowtitle_len, rowtitle_pos)
87
+ @rowtitle_len[x] = rowtitle_len[0]
88
+ @rowtitle_pos[x] = rowtitle_pos[0]
89
+ max_row_title_width = [max_row_title_width, @rowtitle_len[x]].max
90
+ end
91
+
92
+ if have_rowtitles
93
+ @maxrt = max_row_title_width + 2
94
+
95
+ # We need to rejustify the row title cell info.
96
+ (1..rows).each do |x|
97
+ @rowtitle_pos[x] = RNDK.justifyString(@maxrt,
98
+ @rowtitle_len[x], @rowtitle_pos[x])
99
+ end
100
+ else
101
+ @maxrt = 0
102
+ end
103
+
104
+ # Determine the width of the matrix.
105
+ max_width = 2 + @maxrt
106
+ (1..vcols).each do |x|
107
+ max_width += colwidths[x] + 2 + col_space
108
+ end
109
+ max_width -= (col_space - 1)
110
+ box_width = [max_width, box_width].max
111
+ box_width = self.setTitle(title, box_width)
112
+
113
+ # Make sure the dimensions of the window didn't extend
114
+ # beyond the dimensions of the parent window
115
+ box_width = [box_width, parent_width].min
116
+ box_height = [box_height, parent_height].min
117
+
118
+ # Rejustify the x and y positions if we need to.
119
+ xtmp = [xplace]
120
+ ytmp = [yplace]
121
+ RNDK.alignxy(rndkscreen.window, xtmp, ytmp, box_width, box_height)
122
+ xpos = xtmp[0]
123
+ ypos = ytmp[0]
124
+
125
+ # Make the pop-up window.
126
+ @win = Ncurses.newwin(box_height, box_width, ypos, xpos)
127
+
128
+ if @win.nil?
129
+ self.destroy
130
+ return nil
131
+ end
132
+
133
+ # Make the subwindows in the pop-up.
134
+ begx = xpos
135
+ begy = ypos + borderw + @title_lines
136
+
137
+ # Make the 'empty' 0x0 cell.
138
+ @cell[0][0] = Ncurses.subwin(@win, 3, @maxrt, begy, begx)
139
+
140
+ begx += @maxrt + 1
141
+
142
+ # Copy the titles into the structrue.
143
+ (1..cols).each do |x|
144
+ if !(coltitles.nil?) && x < coltitles.size && coltitles[x].size > 0
145
+ have_coltitles = true
146
+ end
147
+ coltitle_len = []
148
+ coltitle_pos = []
149
+ @coltitle[x] = RNDK.char2Chtype(coltitles[x] || '',
150
+ coltitle_len, coltitle_pos)
151
+ @coltitle_len[x] = coltitle_len[0]
152
+ @coltitle_pos[x] = @border_size + RNDK.justifyString(
153
+ colwidths[x], @coltitle_len[x], coltitle_pos[0])
154
+ @colwidths[x] = colwidths[x]
155
+ end
156
+
157
+ if have_coltitles
158
+ # Make the column titles.
159
+ (1..vcols).each do |x|
160
+ cell_width = colwidths[x] + 3
161
+ @cell[0][x] = Ncurses.subwin(@win, borderw, cell_width, begy, begx)
162
+ if @cell[0][x].nil?
163
+ self.destroy
164
+ return nil
165
+ end
166
+ begx += cell_width + col_space - 1
167
+ end
168
+ begy += 1
169
+ end
170
+
171
+ # Make the main cell body
172
+ (1..vrows).each do |x|
173
+ if have_rowtitles
174
+ # Make the row titles
175
+ @cell[x][0] = Ncurses.subwin(@win, 3, @maxrt, begy, xpos + borderw)
176
+
177
+ if @cell[x][0].nil?
178
+ self.destroy
179
+ return nil
180
+ end
181
+ end
182
+
183
+ # Set the start of the x position.
184
+ begx = xpos + @maxrt + borderw
185
+
186
+ # Make the cells
187
+ (1..vcols).each do |y|
188
+ cell_width = colwidths[y] + 3
189
+ @cell[x][y] = Ncurses.subwin(@win, 3, cell_width, begy, begx)
190
+
191
+ if @cell[x][y].nil?
192
+ self.destroy
193
+ return nil
194
+ end
195
+ begx += cell_width + col_space - 1
196
+ Ncurses.keypad(@cell[x][y], true)
197
+ end
198
+ begy += row_space + 2
199
+ end
200
+ Ncurses.keypad(@win, true)
201
+
202
+ # Keep the rest of the info.
203
+ @screen = rndkscreen
204
+ @accepts_focus = true
205
+ @input_window = @win
206
+ @parent = rndkscreen.window
207
+ @vrows = vrows
208
+ @vcols = vcols
209
+ @box_width = box_width
210
+ @box_height = box_height
211
+ @row_space = row_space
212
+ @col_space = col_space
213
+ @filler = filler.ord
214
+ @dominant = dominant
215
+ @row = 1
216
+ @col = 1
217
+ @crow = 1
218
+ @ccol = 1
219
+ @trow = 1
220
+ @lcol = 1
221
+ @oldcrow = 1
222
+ @oldccol = 1
223
+ @oldvrow = 1
224
+ @oldvcol = 1
225
+ @box_cell = box_cell
226
+ @shadow = shadow
227
+ @highlight = Ncurses::A_REVERSE
228
+ @shadow_win = nil
229
+ @callbackfn = lambda do |matrix, input|
230
+ disptype = matrix.colvanlues[matrix.col]
231
+ plainchar = Display.filterByDisplayType(disptype, input)
232
+ charcount = matrix.info[matrix.row][matrix.col].size
233
+
234
+ if plainchar == Ncurses::ERR
235
+ RNDK.beep
236
+ elsif charcount == matrix.colwidths[matrix.col]
237
+ RNDK.beep
238
+ else
239
+ # Update the screen.
240
+ Ncurses.wmove(matrix.CurMatrixCell,
241
+ 1,
242
+ matrix.info[matrix.row][matrix.col].size + 1)
243
+ Ncurses.waddch(matrix.CurMatrixCell,
244
+ if Display.isHiddenDisplayType(disptype)
245
+ then matrix.filler
246
+ else plainchar
247
+ end)
248
+ Ncurses.wrefresh matrix.CurMatrixCell
249
+
250
+ # Update the info string
251
+ matrix.info[matrix.row][matrix.col] =
252
+ matrix.info[matrix.row][matrix.col][0...charcount] +
253
+ plainchar.chr
254
+ end
255
+ end
256
+
257
+ # Make room for the cell information.
258
+ (1..rows).each do |x|
259
+ (1..cols).each do |y|
260
+ @colvalues[y] = colvalues[y]
261
+ @colwidths[y] = colwidths[y]
262
+ end
263
+ end
264
+
265
+ @colvalues = colvalues.clone
266
+ @colwidths = colwidths.clone
267
+
268
+ # Do we want a shadow?
269
+ if shadow
270
+ @shadow_win = Ncurses.newwin(box_height, box_width,
271
+ ypos + 1, xpos + 1)
272
+ end
273
+
274
+ # Set up the key bindings.
275
+ bindings.each do |from, to|
276
+ self.bind(:MATRIX, from, :getc, to)
277
+ end
278
+
279
+ # Register this baby.
280
+ rndkscreen.register(:MATRIX, self)
281
+ end
282
+
283
+ # This activates the matrix.
284
+ def activate(actions)
285
+ self.draw(@box)
286
+
287
+ if actions.nil? || actions.size == 0
288
+ while true
289
+ @input_window = self.CurMatrixCell
290
+ Ncurses.keypad(@input_window, true)
291
+ input = self.getch([])
292
+
293
+ # Inject the character into the widget.
294
+ ret = self.inject(input)
295
+ if @exit_type != :EARLY_EXIT
296
+ return ret
297
+ end
298
+ end
299
+ else
300
+ # Inject each character one at a time.
301
+ actions.each do |action|
302
+ ret = self.inject(action)
303
+ if @exit_type != :EARLY_EXIT
304
+ return ret
305
+ end
306
+ end
307
+ end
308
+
309
+ # Set the exit type and exit.
310
+ self.setExitType(0)
311
+ return -1
312
+ end
313
+
314
+ # This injects a single character into the matrix widget.
315
+ def inject(input)
316
+ refresh_cells = false
317
+ moved_cell = false
318
+ charcount = @info[@row][@col].size
319
+ pp_return = 1
320
+ ret = -1
321
+ complete = false
322
+
323
+ # Set the exit type.
324
+ self.setExitType(0)
325
+
326
+ # Move the cursor to the correct position within the cell.
327
+ if @colwidths[@ccol] == 1
328
+ Ncurses.wmove(self.CurMatrixCell, 1, 1)
329
+ else
330
+ Ncurses.wmove(self.CurMatrixCell, 1, @info[@row][@col].size + 1)
331
+ end
332
+
333
+ # Put the focus on the current cell.
334
+ self.focusCurrent
335
+
336
+ # Check if there is a pre-process function to be called.
337
+ unless @pre_process_func.nil?
338
+ # Call the pre-process function.
339
+ pp_return = @pre_process_func.call(:MATRIX, self,
340
+ @pre_process_data, input)
341
+ end
342
+
343
+ # Should we continue?
344
+ if pp_return != 0
345
+ # Check the key bindings.
346
+ if self.checkBind(:MATRIX, input)
347
+ complete = true
348
+ else
349
+ case input
350
+ when RNDK::TRANSPOSE
351
+ when Ncurses::KEY_HOME
352
+ when Ncurses::KEY_END
353
+ when Ncurses::KEY_BACKSPACE, Ncurses::KEY_DC
354
+ if @colvalues[@col] == :VIEWONLY || charcount <= 0
355
+ RNDK.beep
356
+ else
357
+ charcount -= 1
358
+ Ncurses.mvwdelch(self.CurMatrixCell, 1, charcount + 1)
359
+ Ncurses.mvwinsch(self.CurMatrixCell, 1, charcount + 1, @filler)
360
+
361
+ Ncurses.wrefresh self.CurMatrixCell
362
+ @info[@row][@col] = @info[@row][@col][0...charcount]
363
+ end
364
+ when Ncurses::KEY_RIGHT, RNDK::KEY_TAB
365
+ if @ccol != @vcols
366
+ # We are moving to the right...
367
+ @col += 1
368
+ @ccol += 1
369
+ moved_cell = true
370
+ else
371
+ # We have to shift the columns to the right.
372
+ if @col != @cols
373
+ @lcol += 1
374
+ @col += 1
375
+
376
+ # Redraw the column titles.
377
+ if @rows > @vrows
378
+ self.redrawTitles(false, true)
379
+ end
380
+ refresh_cells = true
381
+ moved_cell = true
382
+ else
383
+ # We are at the far right column, we need to shift
384
+ # down one row, if we can.
385
+ if @row == @rows
386
+ RNDK.beep
387
+ else
388
+ # Set up the columns info.
389
+ @col = 1
390
+ @lcol = 1
391
+ @ccol = 1
392
+
393
+ # Shift the rows...
394
+ if @crow != @vrows
395
+ @row += 1
396
+ @crow += 1
397
+ else
398
+ @row += 1
399
+ @trow += 1
400
+ end
401
+ self.redrawTitles(true, true)
402
+ refresh_cells = true
403
+ moved_cell = true
404
+ end
405
+ end
406
+ end
407
+ when Ncurses::KEY_LEFT, Ncurses::KEY_BTAB
408
+ if @ccol != 1
409
+ # We are moving to the left...
410
+ @col -= 1
411
+ @ccol -= 1
412
+ moved_cell = true
413
+ else
414
+ # Are we at the far left?
415
+ if @lcol != 1
416
+ @lcol -= 1
417
+ @col -= 1
418
+
419
+ # Redraw the column titles.
420
+ if @cols > @vcols
421
+ self.redrawTitles(false, true)
422
+ end
423
+ refresh_cells = true
424
+ moved_cell = true
425
+ else
426
+ # Shift up one line if we can...
427
+ if @row == 1
428
+ RNDK.beep
429
+ else
430
+ # Set up the columns info.
431
+ @col = @cols
432
+ @lcol = @cols - @vcols + 1
433
+ @ccol = @vcols
434
+
435
+ # Shift the rows...
436
+ if @crow != 1
437
+ @row -= 1
438
+ @crow -= 1
439
+ else
440
+ @row -= 1
441
+ @trow -= 1
442
+ end
443
+ self.redrawTitles(true, true)
444
+ refresh_cells = true
445
+ moved_cell = true
446
+ end
447
+ end
448
+ end
449
+ when Ncurses::KEY_UP
450
+ if @crow != 1
451
+ @row -= 1
452
+ @crow -= 1
453
+ moved_cell = true
454
+ else
455
+ if @trow != 1
456
+ @trow -= 1
457
+ @row -= 1
458
+
459
+ # Redraw the row titles.
460
+ if @rows > @vrows
461
+ self.redrawTitles(true, false)
462
+ end
463
+ refresh_cells = true
464
+ moved_cell = true
465
+ else
466
+ RNDK.beep
467
+ end
468
+ end
469
+ when Ncurses::KEY_DOWN
470
+ if @crow != @vrows
471
+ @row += 1
472
+ @crow += 1
473
+ moved_cell = true
474
+ else
475
+ if @trow + @vrows - 1 != @rows
476
+ @trow += 1
477
+ @row += 1
478
+
479
+ # Redraw the titles.
480
+ if @rows > @vrows
481
+ self.redrawTitles(true, false)
482
+ end
483
+ refresh_cells = true
484
+ moved_cell = true
485
+ else
486
+ RNDK.beep
487
+ end
488
+ end
489
+ when Ncurses::KEY_NPAGE
490
+ if @rows > @vrows
491
+ if @trow + (@vrows - 1) * 2 <= @rows
492
+ @trow += @vrows - 1
493
+ @row += @vrows - 1
494
+ self.redrawTitles(true, false)
495
+ refresh_cells = true
496
+ moved_cell = true
497
+ else
498
+ RNDK.beep
499
+ end
500
+ else
501
+ RNDK.beep
502
+ end
503
+ when Ncurses::KEY_PPAGE
504
+ if @rows > @vrows
505
+ if @trow - (@vrows - 1) * 2 >= 1
506
+ @trow -= @vrows - 1
507
+ @row -= @vrows - 1
508
+ self.redrawTitles(true, false)
509
+ refresh_cells = true
510
+ moved_cell = true
511
+ else
512
+ RNDK.beep
513
+ end
514
+ else
515
+ RNDK.beep
516
+ end
517
+ when RNDK.CTRL('G')
518
+ self.jumpToCell(-1, -1)
519
+ self.draw(@box)
520
+ when RNDK::PASTE
521
+ if @@g_paste_buffer.size == 0 ||
522
+ @@g_paste_buffer.size > @colwidths[@ccol]
523
+ RNDK.beep
524
+ else
525
+ self.CurMatrixInfo = @@g_paste_buffer.clone
526
+ self.drawCurCell
527
+ end
528
+ when RNDK::COPY
529
+ @@g_paste_buffer = self.CurMatrixInfo.clone
530
+ when RNDK::CUT
531
+ @@g_paste_buffer = self.CurMatrixInfo.clone
532
+ self.cleanCell(@trow + @crow - 1, @lcol + @ccol - 1)
533
+ self.drawCurCell
534
+ when RNDK::ERASE
535
+ self.cleanCell(@trow + @crow - 1, @lcol + @ccol - 1)
536
+ self.drawCurCell
537
+ when Ncurses::KEY_ENTER, RNDK::KEY_RETURN
538
+ if !@box_cell
539
+ Draw.attrbox(@cell[@oldcrow][@oldccol], ' '.ord, ' '.ord,
540
+ ' '.ord, ' '.ord, ' '.ord, ' '.ord, Ncurses::A_NORMAL)
541
+ else
542
+ self.drawOldCell
543
+ end
544
+ Ncurses.wrefresh self.CurMatrixCell
545
+ self.setExitType(input)
546
+ ret = 1
547
+ complete = true
548
+ when Ncurses::ERR
549
+ self.setExitType(input)
550
+ complete = true
551
+ when RNDK::KEY_ESC
552
+ if !@box_cell
553
+ Draw.attrbox(@cell[@oldcrow][@oldccol], ' '.ord, ' '.ord,
554
+ ' '.ord, ' '.ord, ' '.ord, ' '.ord, Ncurses::A_NORMAL)
555
+ else
556
+ self.drawOldCell
557
+ end
558
+ Ncurses.wrefresh self.CurMatrixCell
559
+ self.setExitType(input)
560
+ complete = true
561
+ when RNDK::REFRESH
562
+ @screen.erase
563
+ @screen.refresh
564
+ else
565
+ @callbackfn.call(self, input)
566
+ end
567
+ end
568
+
569
+ if !complete
570
+ # Did we change cells?
571
+ if moved_cell
572
+ # un-highlight the old box
573
+ if !@box_cell
574
+ Draw.attrbox(@cell[@oldcrow][@oldccol], ' '.ord, ' '.ord,
575
+ ' '.ord, ' '.ord, ' '.ord, ' '.ord, Ncurses::A_NORMAL)
576
+ else
577
+ self.drawOldCell
578
+ end
579
+ Ncurses.wrefresh(@cell[@oldcrow][@oldccol])
580
+
581
+ self.focusCurrent
582
+ end
583
+
584
+ # Redraw each cell
585
+ if refresh_cells
586
+ self.drawEachCell
587
+ self.focusCurrent
588
+ end
589
+
590
+ # Move to the correct position in the cell.
591
+ if refresh_cells || moved_cell
592
+ if @colwidths[@ccol] == 1
593
+ Ncurses.wmove(self.CurMatrixCell, 1, 1)
594
+ else
595
+ Ncurses.wmove(self.CurMatrixCell, 1, self.CurMatrixInfo.size + 1)
596
+ end
597
+ Ncurses.wrefresh self.CurMatrixCell
598
+ end
599
+
600
+ # Should we call a post-process?
601
+ unless @post_process_func.nil?
602
+ @post_process_func.call(:MATRIX, self, @post_process_data, input)
603
+ end
604
+ end
605
+ end
606
+
607
+ if !complete
608
+ # Set the variables we need.
609
+ @oldcrow = @crow
610
+ @oldccol = @ccol
611
+ @oldvrow = @row
612
+ @oldvcol = @col
613
+
614
+ # Set the exit type and exit.
615
+ self.setExitType(0)
616
+ end
617
+
618
+ @result_data = ret
619
+ return ret
620
+ end
621
+
622
+ # Highlight the new field.
623
+ def highlightCell
624
+ disptype = @colvalues[@col]
625
+ highlight = @highlight
626
+ infolen = @info[@row][@col].size
627
+
628
+ # Given the dominance of the color/attributes, we need to set the
629
+ # current cell attribute.
630
+ if @dominant == RNDK::ROW
631
+ highlight = (@rowtitle[@crow][0] || 0) & Ncurses::A_ATTRIBUTES
632
+ elsif @dominant == RNDK::COL
633
+ highlight = (@coltitle[@ccol][0] || 0) & Ncurses::A_ATTRIBUTES
634
+ end
635
+
636
+ # If the column is only one char.
637
+ (1..@colwidths[@ccol]).each do |x|
638
+ ch = if x <= infolen && !Display.isHiddenDisplayType(disptype)
639
+ then RNDK.CharOf(@info[@row][@col][x - 1])
640
+ else @filler
641
+ end
642
+ Ncurses.mvwaddch(self.CurMatrixCell, 1, x, ch.ord | highlight)
643
+ end
644
+ Ncurses.wmove(self.CurMatrixCell, 1, infolen + 1)
645
+ Ncurses.wrefresh self.CurMatrixCell
646
+ end
647
+
648
+ # This moves the matrix field to the given location.
649
+ def move(xplace, yplace, relative, refresh_flag)
650
+ windows = [@win]
651
+
652
+ (0..@vrows).each do |x|
653
+ (0..@vcols).each do |y|
654
+ windows << @cell[x][y]
655
+ end
656
+ end
657
+
658
+ windows << @shadow_win
659
+ self.move_specific(xplace, yplace, relative, refresh_flag, windows, [])
660
+ end
661
+
662
+ # This draws a cell within a matrix.
663
+ def drawCell(row, col, vrow, vcol, attr, box)
664
+ disptype = @colvalues[@col]
665
+ highlight = @filler & Ncurses::A_ATTRIBUTES
666
+ rows = @vrows
667
+ cols = @vcols
668
+ infolen = @info[vrow][vcol].size
669
+
670
+ # Given the dominance of the colors/attributes, we need to set the
671
+ # current cell attribute.
672
+ if @dominant == RNDK::ROW
673
+ highlight = (@rowtitle[row][0] || 0) & Ncurses::A_ATTRIBUTES
674
+ elsif @dominant == RNDK::COL
675
+ highlight = (@coltitle[col][0] || 0) & Ncurses::A_ATTRIBUTES
676
+ end
677
+
678
+ # Draw in the cell info.
679
+ (1..@colwidths[col]).each do |x|
680
+ ch = if x <= infolen && !Display.isHiddenDisplayType(disptype)
681
+ then RNDK.CharOf(@info[vrow][vcol][x-1]).ord | highlight
682
+ else @filler
683
+ end
684
+ Ncurses.mvwaddch(@cell[row][col], 1, x, ch.ord | highlight)
685
+ end
686
+
687
+ Ncurses.wmove(@cell[row][col], 1, infolen + 1)
688
+ Ncurses.wrefresh(@cell[row][col])
689
+
690
+ # Only draw the box iff the user asked for a box.
691
+ if !box
692
+ return
693
+ end
694
+
695
+ # If the value of the column spacing is greater than 0 then these
696
+ # are independent boxes
697
+ if @col_space != 0 && @row_space != 0
698
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_ULCORNER,
699
+ Ncurses::ACS_URCORNER, Ncurses::ACS_LLCORNER,
700
+ Ncurses::ACS_LRCORNER, Ncurses::ACS_HLINE,
701
+ Ncurses::ACS_VLINE, attr)
702
+ return
703
+ end
704
+ if @col_space != 0 && @row_space == 0
705
+ if row == 1
706
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_ULCORNER,
707
+ Ncurses::ACS_URCORNER, Ncurses::ACS_LTEE,
708
+ Ncurses::ACS_RTEE, Ncurses::ACS_HLINE,
709
+ Ncurses::ACS_VLINE, attr)
710
+ return
711
+ elsif row > 1 && row < rows
712
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_LTEE, Ncurses::ACS_RTEE,
713
+ Ncurses::ACS_LTEE, Ncurses::ACS_RTEE, Ncurses::ACS_HLINE,
714
+ Ncurses::ACS_VLINE, attr)
715
+ return
716
+ elsif row == rows
717
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_LTEE, Ncurses::ACS_RTEE,
718
+ Ncurses::ACS_LLCORNER, Ncurses::ACS_LRCORNER, Ncurses::ACS_HLINE,
719
+ Ncurses::ACS_VLINE, attr)
720
+ return
721
+ end
722
+ end
723
+ if @col_space == 0 && @row_space != 0
724
+ if col == 1
725
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_ULCORNER,
726
+ Ncurses::ACS_TTEE, Ncurses::ACS_LLCORNER, Ncurses::ACS_BTEE,
727
+ Ncurses::ACS_HLINE, Ncurses::ACS_VLINE, attr)
728
+ return
729
+ elsif col > 1 && col < cols
730
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_TTEE, Ncurses::ACS_TTEE,
731
+ Ncurses::ACS_BTEE, Ncurses::ACS_BTEE, Ncurses::ACS_HLINE,
732
+ Ncurses::ACS_VLINE, attr)
733
+ return
734
+ elsif col == cols
735
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_TTEE,
736
+ Ncurses::ACS_URCORNER,Ncurses::ACS_BTEE, Ncurses::ACS_LRCORNER,
737
+ Ncurses::ACS_HLINE, Ncurses::ACS_VLINE, attr)
738
+ return
739
+ end
740
+ end
741
+
742
+ # Start drawing the matrix.
743
+ if row == 1
744
+ if col == 1
745
+ # Draw the top left corner
746
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_ULCORNER,
747
+ Ncurses::ACS_TTEE, Ncurses::ACS_LTEE, Ncurses::ACS_PLUS,
748
+ Ncurses::ACS_HLINE, Ncurses::ACS_VLINE, attr)
749
+ elsif col > 1 && col < cols
750
+ # Draw the top middle box
751
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_TTEE, Ncurses::ACS_TTEE,
752
+ Ncurses::ACS_PLUS, Ncurses::ACS_PLUS, Ncurses::ACS_HLINE,
753
+ Ncurses::ACS_VLINE, attr)
754
+ elsif col == cols
755
+ # Draw the top right corner
756
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_TTEE,
757
+ Ncurses::ACS_URCORNER, Ncurses::ACS_PLUS, Ncurses::ACS_RTEE,
758
+ Ncurses::ACS_HLINE, Ncurses::ACS_VLINE, attr)
759
+ end
760
+ elsif row > 1 && row < rows
761
+ if col == 1
762
+ # Draw the middle left box
763
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_LTEE, Ncurses::ACS_PLUS,
764
+ Ncurses::ACS_LTEE, Ncurses::ACS_PLUS, Ncurses::ACS_HLINE,
765
+ Ncurses::ACS_VLINE, attr)
766
+ elsif col > 1 && col < cols
767
+ # Draw the middle box
768
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_PLUS, Ncurses::ACS_PLUS,
769
+ Ncurses::ACS_PLUS, Ncurses::ACS_PLUS, Ncurses::ACS_HLINE,
770
+ Ncurses::ACS_VLINE, attr)
771
+ elsif col == cols
772
+ # Draw the middle right box
773
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_PLUS, Ncurses::ACS_RTEE,
774
+ Ncurses::ACS_PLUS, Ncurses::ACS_RTEE, Ncurses::ACS_HLINE,
775
+ Ncurses::ACS_VLINE, attr)
776
+ end
777
+ elsif row == rows
778
+ if col == 1
779
+ # Draw the bottom left corner
780
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_LTEE, Ncurses::ACS_PLUS,
781
+ Ncurses::ACS_LLCORNER, Ncurses::ACS_BTEE, Ncurses::ACS_HLINE,
782
+ Ncurses::ACS_VLINE, attr)
783
+ elsif col > 1 && col < cols
784
+ # Draw the bottom middle box
785
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_PLUS, Ncurses::ACS_PLUS,
786
+ Ncurses::ACS_BTEE, Ncurses::ACS_BTEE, Ncurses::ACS_HLINE,
787
+ Ncurses::ACS_VLINE, attr)
788
+ elsif col == cols
789
+ # Draw the bottom right corner
790
+ Draw.attrbox(@cell[row][col], Ncurses::ACS_PLUS, Ncurses::ACS_RTEE,
791
+ Ncurses::ACS_BTEE, Ncurses::ACS_LRCORNER, Ncurses::ACS_HLINE,
792
+ Ncurses::ACS_VLINE, attr)
793
+ end
794
+ end
795
+
796
+ self.focusCurrent
797
+ end
798
+
799
+ def drawEachColTitle
800
+ (1..@vcols).each do |x|
801
+ unless @cell[0][x].nil?
802
+ Ncurses.werase @cell[0][x]
803
+
804
+ Draw.writeChtype(@cell[0][x],
805
+ @coltitle_pos[@lcol + x - 1], 0,
806
+ @coltitle[@lcol + x - 1],
807
+ RNDK::HORIZONTAL, 0,
808
+ @coltitle_len[@lcol + x - 1])
809
+
810
+ Ncurses.wrefresh @cell[0][x]
811
+ end
812
+ end
813
+ end
814
+
815
+ def drawEachRowTitle
816
+ (1..@vrows).each do |x|
817
+ unless @cell[x][0].nil?
818
+ Ncurses.werase @cell[x][0]
819
+
820
+ Draw.writeChtype(@cell[x][0],
821
+ @rowtitle_pos[@trow + x - 1], 1,
822
+ @rowtitle[@trow + x - 1],
823
+ RNDK::HORIZONTAL,
824
+ 0,
825
+ @rowtitle_len[@trow + x - 1])
826
+
827
+ Ncurses.wrefresh @cell[x][0]
828
+ end
829
+ end
830
+ end
831
+
832
+ def drawEachCell
833
+ # Fill in the cells.
834
+ (1..@vrows).each do |x|
835
+ (1..@vcols).each do |y|
836
+ self.drawCell(x,
837
+ y,
838
+ @trow + x - 1,
839
+ @lcol + y - 1,
840
+ Ncurses::A_NORMAL,
841
+ @box_cell)
842
+ end
843
+ end
844
+ end
845
+
846
+ def drawCurCell
847
+ self.drawCell(@crow, @ccol, @row, @col, Ncurses::A_NORMAL, @box_cell)
848
+ end
849
+
850
+ def drawOldCell
851
+ self.drawCell(@oldcrow, @oldccol, @oldvrow, @oldvcol, Ncurses::A_NORMAL, @box_cell)
852
+ end
853
+
854
+ # This function draws the matrix widget.
855
+ def draw(box)
856
+ # Did we ask for a shadow?
857
+ unless @shadow_win.nil?
858
+ Draw.drawShadow(@shadow_win)
859
+ end
860
+
861
+ # Should we box the matrix?
862
+ if box
863
+ Draw.drawObjBox(@win, self)
864
+ end
865
+
866
+ self.drawTitle(@win)
867
+
868
+ Ncurses.wrefresh @win
869
+
870
+ self.drawEachColTitle
871
+ self.drawEachRowTitle
872
+ self.drawEachCell
873
+ self.focusCurrent
874
+ end
875
+
876
+ # This function destroys the matrix widget.
877
+ def destroy
878
+ self.cleanTitle
879
+
880
+ # Clear the matrix windows.
881
+ RNDK.deleteCursesWindow(@cell[0][0])
882
+ (1..@vrows).each { |x| RNDK.deleteCursesWindow @cell[x][0] }
883
+ (1..@vcols).each { |x| RNDK.deleteCursesWindow @cell[0][x] }
884
+
885
+ (1..@vrows).each do |x|
886
+ (1..@vcols).each do |y|
887
+ RNDK.deleteCursesWindow @cell[x][y]
888
+ end
889
+ end
890
+
891
+ RNDK.deleteCursesWindow @shadow_win
892
+ RNDK.deleteCursesWindow @win
893
+
894
+ # Clean the key bindings.
895
+ self.cleanBindings(:MATRIX)
896
+
897
+ # Unregister this object.
898
+ RNDK::Screen.unregister(:MATRIX, self)
899
+ end
900
+
901
+ # This function erases the matrix widget from the screen.
902
+ def erase
903
+ if self.validRNDKObject
904
+ # Clear the matrix cells.
905
+ RNDK.eraseCursesWindow @cell[0][0]
906
+
907
+ (1..@vrows).each { |x| RNDK.eraseCursesWindow @cell[x][0] }
908
+ (1..@vcols).each { |x| RNDK.eraseCursesWindow @cell[0][x] }
909
+
910
+ (1..@vrows).each do |x|
911
+ (1..@vcols).each do |y|
912
+ RNDK.eraseCursesWindow @cell[x][y]
913
+ end
914
+ end
915
+
916
+ RNDK.eraseCursesWindow @shadow_win
917
+ RNDK.eraseCursesWindow @win
918
+ end
919
+ end
920
+
921
+ # Set the callback function
922
+ def setCB(callback)
923
+ @callbackfn = callback
924
+ end
925
+
926
+ # This function sets the values of the matrix widget.
927
+ def setCells(info, rows, maxcols, sub_size)
928
+ if rows > @rows
929
+ rows = @rows
930
+ end
931
+
932
+ # Copy in the new info.
933
+ (1..rows).each do |x|
934
+ (1..@cols).each do |y|
935
+ if x <= rows && y <= sub_size[x]
936
+ @info[x][y] = @info[x][y][0..[@colwidths[y], @info[x][y].size].min]
937
+ else
938
+ self.cleanCell(x, y)
939
+ end
940
+ end
941
+ end
942
+ end
943
+
944
+ # This cleans out the information cells in the matrix widget.
945
+ def clean
946
+ (1..@rows).each do |x|
947
+ (1..@cols).each do |y|
948
+ self.cleanCell(x, y)
949
+ end
950
+ end
951
+ end
952
+
953
+ # This cleans one cell in the matrix widget.
954
+ def cleanCell(row, col)
955
+ if row > 0 && row <= @rows && col > col <= @cols
956
+ @info[row][col] = ''
957
+ end
958
+ end
959
+
960
+ # This allows us to hyper-warp to a cell
961
+ def jumpToCell(row, col)
962
+ new_row = row
963
+ new_col = col
964
+
965
+ # Only create the row scale if needed.
966
+ if (row == -1) || (row > @rows)
967
+ # Create the row scale widget.
968
+ scale = RNDK::SCALE.new(@screen, RNDK::CENTER, RNDK::CENTER,
969
+ '<C>Jump to which row.', '</5/B>Row: ', Ncurses::A_NORMAL,
970
+ 5, 1, 1, @rows, 1, 1, true, false)
971
+
972
+ # Activate the scale and get the row.
973
+ new_row = scale.activate([])
974
+ scale.destroy
975
+ end
976
+
977
+ # Only create the column scale if needed.
978
+ if (col == -1) || (col > @cols)
979
+ # Create the column scale widget.
980
+ scale = RNDK::SCALE.new(@screen, RNDK::CENTER, RNDK::CENTER,
981
+ '<C>Jump to which column', '</5/B>Col: ', Ncurses::A_NORMAL,
982
+ 5, 1, 1, @cols, 1, 1, true, false)
983
+
984
+ # Activate the scale and get the column.
985
+ new_col = scale.activate([])
986
+ scale.destroy
987
+ end
988
+
989
+ # Hyper-warp....
990
+ if new_row != @row || @new_col != @col
991
+ return self.moveToCell(new_row, new_col)
992
+ else
993
+ return 1
994
+ end
995
+ end
996
+
997
+ # This allows us to move to a given cell.
998
+ def moveToCell(newrow, newcol)
999
+ row_shift = newrow - @row
1000
+ col_shift = newcol - @col
1001
+
1002
+ # Make sure we aren't asking to move out of the matrix.
1003
+ if newrow > @rows || newcol > @cols || newrow <= 0 || newcol <= 0
1004
+ return 0
1005
+ end
1006
+
1007
+ # Did we move up/down?
1008
+ if row_shift > 0
1009
+ # We are moving down
1010
+ if @vrows == @cols
1011
+ @trow = 1
1012
+ @crow = newrow
1013
+ @row = newrow
1014
+ else
1015
+ if row_shift + @vrows < @rows
1016
+ # Just shift down by row_shift
1017
+ @trow += row_shift
1018
+ @crow = 1
1019
+ @row += row_shift
1020
+ else
1021
+ # We need to munge the values
1022
+ @trow = @rows - @vrows + 1
1023
+ @crow = row_shift + @vrows - @rows + 1
1024
+ @row = newrow
1025
+ end
1026
+ end
1027
+ elsif row_shift < 0
1028
+ # We are moving up.
1029
+ if @vrows == @rows
1030
+ @trow = 1
1031
+ @row = newrow
1032
+ @crow = newrow
1033
+ else
1034
+ if row_shift + @vrows > 1
1035
+ # Just shift up by row_shift...
1036
+ @trow += row_shift
1037
+ @row += row_shift
1038
+ @crow = 1
1039
+ else
1040
+ # We need to munge the values
1041
+ @trow = 1
1042
+ @crow = 1
1043
+ @row = 1
1044
+ end
1045
+ end
1046
+ end
1047
+
1048
+ # Did we move left/right?
1049
+ if col_shift > 0
1050
+ # We are moving right.
1051
+ if @vcols == @cols
1052
+ @lcol = 1
1053
+ @ccol = newcol
1054
+ @col = newcol
1055
+ else
1056
+ if col_shift + @vcols < @cols
1057
+ @lcol += col_shift
1058
+ @ccol = 1
1059
+ @col += col_shift
1060
+ else
1061
+ # We need to munge with the values
1062
+ @lcol = @cols - @vcols + 1
1063
+ @ccol = col_shift + @vcols - @cols + 1
1064
+ @col = newcol
1065
+ end
1066
+ end
1067
+ elsif col_shift < 0
1068
+ # We are moving left.
1069
+ if @vcols == @cols
1070
+ @lcol = 1
1071
+ @col = newcol
1072
+ @ccol = newcol
1073
+ else
1074
+ if col_shift + @vcols > 1
1075
+ # Just shift left by col_shift
1076
+ @lcol += col_shift
1077
+ @col += col_shift
1078
+ @ccol = 1
1079
+ else
1080
+ @lcol = 1
1081
+ @col = 1
1082
+ @ccol = 1
1083
+ end
1084
+ end
1085
+ end
1086
+
1087
+ # Keep the 'old' values around for redrawing sake.
1088
+ @oldcrow = @crow
1089
+ @oldccol = @ccol
1090
+ @oldvrow = @row
1091
+ @oldvcol = @col
1092
+
1093
+ return 1
1094
+ end
1095
+
1096
+ # This redraws the titles indicated...
1097
+ def redrawTitles(row_titles, col_titles)
1098
+ # Redraw the row titles.
1099
+ if row_titles
1100
+ self.drawEachRowTitle
1101
+ end
1102
+
1103
+ # Redraw the column titles.
1104
+ if col_titles
1105
+ self.drawEachColTitle
1106
+ end
1107
+ end
1108
+
1109
+ # This sets the value of a matrix cell.
1110
+ def setCell(row, col, value)
1111
+ # Make sure the row/col combination is within the matrix.
1112
+ if row > @rows || cols > @cols || row <= 0 || col <= 0
1113
+ return -1
1114
+ end
1115
+
1116
+ self.cleanCell(row, col)
1117
+ @info[row][col] = value[0...[@colwidths[col], value.size].min]
1118
+ return 1
1119
+ end
1120
+
1121
+ # This gets the value of a matrix cell.
1122
+ def getCell(row, col)
1123
+ # Make sure the row/col combination is within the matrix.
1124
+ if row > @rows || col > @cols || row <= 0 || col <= 0
1125
+ return 0
1126
+ end
1127
+ return @info[row][col]
1128
+ end
1129
+
1130
+ def CurMatrixCell
1131
+ return @cell[@crow][@ccol]
1132
+ end
1133
+
1134
+ def CurMatrixInfo
1135
+ return @info[@trow + @crow - 1][@lcol + @ccol - 1]
1136
+ end
1137
+
1138
+ def focusCurrent
1139
+ Draw.attrbox(self.CurMatrixCell,
1140
+ Ncurses::ACS_ULCORNER,
1141
+ Ncurses::ACS_URCORNER,
1142
+ Ncurses::ACS_LLCORNER,
1143
+ Ncurses::ACS_LRCORNER,
1144
+ Ncurses::ACS_HLINE,
1145
+ Ncurses::ACS_VLINE,
1146
+ Ncurses::A_BOLD)
1147
+
1148
+ Ncurses.wrefresh self.CurMatrixCell
1149
+ self.highlightCell
1150
+ end
1151
+
1152
+ # This returns the current row/col cell
1153
+ def getCol
1154
+ return @col
1155
+ end
1156
+
1157
+ def getRow
1158
+ return @row
1159
+ end
1160
+
1161
+ # This sets the background attribute of the widget.
1162
+ def setBKattr(attrib)
1163
+ Ncurses.wbkgd(@win, attrib)
1164
+
1165
+ # TODO what the hell?
1166
+ (0..@vrows).each do |x|
1167
+ (0..@vcols).each do |y|
1168
+ # wbkgd (MATRIX_CELL (widget, x, y), attrib);
1169
+ end
1170
+ end
1171
+ end
1172
+
1173
+ def focus
1174
+ self.draw(@box)
1175
+ end
1176
+
1177
+ def unfocus
1178
+ self.draw(@box)
1179
+ end
1180
+
1181
+ def position
1182
+ super(@win)
1183
+ end
1184
+
1185
+ def object_type
1186
+ :MATRIX
1187
+ end
1188
+ end
1189
+ end