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
@@ -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