slithernix-cdk 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.
data/lib/cdk/scroll.rb ADDED
@@ -0,0 +1,996 @@
1
+ require_relative 'scroller'
2
+
3
+ module CDK
4
+ class SCROLL < CDK::SCROLLER
5
+ attr_reader :item, :list_size, :current_item, :highlight
6
+
7
+ def initialize (cdkscreen, xplace, yplace, splace, height, width, title,
8
+ list, list_size, numbers, highlight, box, shadow)
9
+ super()
10
+ parent_width = cdkscreen.window.maxx
11
+ parent_height = cdkscreen.window.maxy
12
+ box_width = width
13
+ box_height = height
14
+ xpos = xplace
15
+ ypos = yplace
16
+ scroll_adjust = 0
17
+ bindings = {
18
+ CDK::BACKCHAR => Curses::KEY_PPAGE,
19
+ CDK::FORCHAR => Curses::KEY_NPAGE,
20
+ 'g' => Curses::KEY_HOME,
21
+ '1' => Curses::KEY_HOME,
22
+ 'G' => Curses::KEY_END,
23
+ '<' => Curses::KEY_HOME,
24
+ '>' => Curses::KEY_END
25
+ }
26
+
27
+ self.setBox(box)
28
+
29
+ # If the height is a negative value, the height will be ROWS-height,
30
+ # otherwise the height will be the given height
31
+ box_height = CDK.setWidgetDimension(parent_height, height, 0)
32
+
33
+ # If the width is a negative value, the width will be COLS-width,
34
+ # otherwise the width will be the given width
35
+ box_width = CDK.setWidgetDimension(parent_width, width, 0)
36
+
37
+ box_width = self.setTitle(title, box_width)
38
+
39
+ # Set the box height.
40
+ if @title_lines > box_height
41
+ box_height = @title_lines + [list_size, 8].min + 2 * @border_size
42
+ end
43
+
44
+ # Adjust the box width if there is a scroll bar
45
+ if splace == CDK::LEFT || splace == CDK::RIGHT
46
+ @scrollbar = true
47
+ box_width += 1
48
+ else
49
+ @scrollbar = false
50
+ end
51
+
52
+ # Make sure we didn't extend beyond the dimensions of the window.
53
+ @box_width = if box_width > parent_width
54
+ then parent_width - scroll_adjust
55
+ else box_width
56
+ end
57
+ @box_height = if box_height > parent_height
58
+ then parent_height
59
+ else box_height
60
+ end
61
+
62
+ self.setViewSize(list_size)
63
+
64
+ # Rejustify the x and y positions if we need to.
65
+ xtmp = [xpos]
66
+ ytmp = [ypos]
67
+ CDK.alignxy(cdkscreen.window, xtmp, ytmp, @box_width, @box_height)
68
+ xpos = xtmp[0]
69
+ ypos = ytmp[0]
70
+
71
+ # Make the scrolling window
72
+ @win = Curses::Window.new(@box_height, @box_width, ypos, xpos)
73
+
74
+ # Is the scrolling window null?
75
+ if @win.nil?
76
+ return nil
77
+ end
78
+
79
+ # Turn the keypad on for the window
80
+ @win.keypad(true)
81
+
82
+ # Create the scrollbar window.
83
+ if splace == CDK::RIGHT
84
+ @scrollbar_win = @win.subwin(self.maxViewSize, 1,
85
+ self.SCREEN_YPOS(ypos), xpos + box_width - @border_size - 1)
86
+ elsif splace == CDK::LEFT
87
+ @scrollbar_win = @win.subwin(self.maxViewSize, 1,
88
+ self.SCREEN_YPOS(ypos), self.SCREEN_XPOS(xpos))
89
+ else
90
+ @scrollbar_win = nil
91
+ end
92
+
93
+ # create the list window
94
+ @list_win = @win.subwin(self.maxViewSize,
95
+ box_width - (2 * @border_size) - scroll_adjust,
96
+ self.SCREEN_YPOS(ypos),
97
+ self.SCREEN_XPOS(xpos) + (if splace == CDK::LEFT then 1 else 0 end))
98
+
99
+ # Set the rest of the variables
100
+ @screen = cdkscreen
101
+ @parent = cdkscreen.window
102
+ @shadow_win = nil
103
+ @scrollbar_placement = splace
104
+ @max_left_char = 0
105
+ @left_char = 0
106
+ @highlight = highlight
107
+ # initExitType (scrollp);
108
+ @accepts_focus = true
109
+ @input_window = @win
110
+ @shadow = shadow
111
+
112
+ self.setPosition(0);
113
+
114
+ # Create the scrolling list item list and needed variables.
115
+ if self.createItemList(numbers, list, list_size) <= 0
116
+ return nil
117
+ end
118
+
119
+ # Do we need to create a shadow?
120
+ if shadow
121
+ @shadow_win = Curses::Window.new(@box_height, box_width,
122
+ ypos + 1, xpos + 1)
123
+ end
124
+
125
+ # Set up the key bindings.
126
+ bindings.each do |from, to|
127
+ #self.bind(:SCROLL, from, getc_lambda, to)
128
+ self.bind(:SCROLL, from, :getc, to)
129
+ end
130
+
131
+ cdkscreen.register(:SCROLL, self);
132
+
133
+ return self
134
+ end
135
+
136
+ def object_type
137
+ :SCROLL
138
+ end
139
+
140
+ def position
141
+ super(@win)
142
+ end
143
+
144
+ # Put the cursor on the currently-selected item's row.
145
+ def fixCursorPosition
146
+ scrollbar_adj = if @scrollbar_placement == LEFT then 1 else 0 end
147
+ ypos = self.SCREEN_YPOS(@current_item - @current_top)
148
+ xpos = self.SCREEN_XPOS(0) + scrollbar_adj
149
+
150
+ # Another .move that breaks a bunch of stuff!, BIGLY!!!
151
+ #@input_window.move(ypos, xpos)
152
+ @input_window.refresh
153
+ end
154
+
155
+ # This actually does all the 'real' work of managing the scrolling list.
156
+ def activate(actions)
157
+ # Draw the scrolling list
158
+ self.draw(@box)
159
+
160
+ if actions.nil? || actions.size == 0
161
+ while true
162
+ self.fixCursorPosition
163
+ input = self.getch([])
164
+
165
+ # Inject the character into the widget.
166
+ ret = self.inject(input)
167
+ if @exit_type != :EARLY_EXIT
168
+ return ret
169
+ end
170
+ end
171
+ else
172
+ # Inject each character one at a time.
173
+ actions.each do |action|
174
+ ret = self.inject(action)
175
+ if @exit_type != :EARLY_EXIT
176
+ return ret
177
+ end
178
+ end
179
+ end
180
+
181
+ # Set the exit type for the widget and return
182
+ self.setExitType(0)
183
+ return -1
184
+ end
185
+
186
+ # This injects a single character into the widget.
187
+ def inject(input)
188
+ pp_return = 1
189
+ ret = -1
190
+ complete = false
191
+
192
+ # Set the exit type for the widget.
193
+ self.setExitType(0)
194
+
195
+ # Draw the scrolling list
196
+ self.drawList(@box)
197
+
198
+ #Check if there is a pre-process function to be called.
199
+ unless @pre_process_func.nil?
200
+ pp_return = @pre_process_func.call(:SCROLL, self,
201
+ @pre_process_data, input)
202
+ end
203
+
204
+ # Should we continue?
205
+ if pp_return != 0
206
+ # Check for a predefined key binding.
207
+ if self.checkBind(:SCROLL, input) != false
208
+ #self.checkEarlyExit
209
+ complete = true
210
+ else
211
+ case input
212
+ when Curses::KEY_UP
213
+ self.KEY_UP
214
+ when Curses::KEY_DOWN
215
+ self.KEY_DOWN
216
+ when Curses::KEY_RIGHT
217
+ self.KEY_RIGHT
218
+ when Curses::KEY_LEFT
219
+ self.KEY_LEFT
220
+ when Curses::KEY_PPAGE
221
+ self.KEY_PPAGE
222
+ when Curses::KEY_NPAGE
223
+ self.KEY_NPAGE
224
+ when Curses::KEY_HOME
225
+ self.KEY_HOME
226
+ when Curses::KEY_END
227
+ self.KEY_END
228
+ when '$'
229
+ @left_char = @max_left_char
230
+ when '|'
231
+ @left_char = 0
232
+ when CDK::KEY_ESC
233
+ self.setExitType(input)
234
+ complete = true
235
+ when Curses::Error
236
+ self.setExitType(input)
237
+ complete = true
238
+ when CDK::REFRESH
239
+ @screen.erase
240
+ @screen.refresh
241
+ when CDK::KEY_TAB, Curses::KEY_ENTER, CDK::KEY_RETURN
242
+ self.setExitType(input)
243
+ ret = @current_item
244
+ complete = true
245
+ end
246
+ end
247
+
248
+ if !complete && !(@post_process_func.nil?)
249
+ @post_process_func.call(:SCROLL, self, @post_process_data, input)
250
+ end
251
+ end
252
+
253
+ if !complete
254
+ self.drawList(@box)
255
+ self.setExitType(0)
256
+ end
257
+
258
+ self.fixCursorPosition
259
+ @result_data = ret
260
+
261
+ #return ret != -1
262
+ return ret
263
+ end
264
+
265
+ def getCurrentTop
266
+ return @current_top
267
+ end
268
+
269
+ def setCurrentTop(item)
270
+ if item < 0
271
+ item = 0
272
+ elsif item > @max_top_item
273
+ item = @max_top_item
274
+ end
275
+ @current_top = item
276
+
277
+ self.setPosition(item);
278
+ end
279
+
280
+ # This moves the scroll field to the given location.
281
+ def move(xplace, yplace, relative, refresh_flag)
282
+ windows = [@win, @list_win, @shadow_win, @scrollbar_win]
283
+ self.move_specific(xplace, yplace, relative, refresh_flag,
284
+ windows, [])
285
+ end
286
+
287
+ # This function draws the scrolling list widget.
288
+ def draw(box)
289
+ # Draw in the shadow if we need to.
290
+ unless @shadow_win.nil?
291
+ Draw.drawShadow(@shadow_win)
292
+ end
293
+
294
+ self.drawTitle(@win)
295
+
296
+ # Draw in the scrolling list items.
297
+ self.drawList(box)
298
+ end
299
+
300
+ def drawCurrent
301
+ # Rehighlight the current menu item.
302
+ screen_pos = @item_pos[@current_item] - @left_char
303
+ highlight = if self.has_focus
304
+ then @highlight
305
+ else Curses::A_NORMAL
306
+ end
307
+
308
+ Draw.writeChtypeAttrib(@list_win,
309
+ if screen_pos >= 0 then screen_pos else 0 end,
310
+ @current_high, @item[@current_item], highlight, CDK::HORIZONTAL,
311
+ if screen_pos >= 0 then 0 else 1 - screen_pos end,
312
+ @item_len[@current_item])
313
+ end
314
+
315
+ def drawList(box)
316
+ # If the list is empty, don't draw anything.
317
+ if @list_size > 0
318
+ # Redraw the list
319
+ (0...@view_size).each do |j|
320
+ k = j + @current_top
321
+
322
+ Draw.writeBlanks(@list_win, 0, j, CDK::HORIZONTAL, 0,
323
+ @box_width - (2 * @border_size))
324
+
325
+ # Draw the elements in the scrolling list.
326
+ if k < @list_size
327
+ screen_pos = @item_pos[k] - @left_char
328
+ ypos = j
329
+
330
+ # Write in the correct line.
331
+ Draw.writeChtype(@list_win,
332
+ if screen_pos >= 0 then screen_pos else 1 end,
333
+ ypos, @item[k], CDK::HORIZONTAL,
334
+ if screen_pos >= 0 then 0 else 1 - screen_pos end,
335
+ @item_len[k])
336
+ end
337
+ end
338
+
339
+ self.drawCurrent
340
+
341
+ # Determine where the toggle is supposed to be.
342
+ unless @scrollbar_win.nil?
343
+ @toggle_pos = (@current_item * @step).floor
344
+
345
+ # Make sure the toggle button doesn't go out of bounds.
346
+
347
+ if @toggle_pos >= @scrollbar_win.maxy
348
+ @toggle_pos = @scrollbar_win.maxy - 1
349
+ end
350
+
351
+ # Draw the scrollbar
352
+ @scrollbar_win.mvwvline(0, 0, CDK::ACS_CKBOARD,
353
+ @scrollbar_win.maxy)
354
+ @scrollbar_win.mvwvline(@toggle_pos, 0, ' '.ord | Curses::A_REVERSE,
355
+ @toggle_size)
356
+ end
357
+ end
358
+
359
+ # Box it if needed.
360
+ if box
361
+ Draw.drawObjBox(@win, self)
362
+ end
363
+
364
+ # Refresh the window
365
+ @win.refresh
366
+ end
367
+
368
+ # This sets the background attribute of the widget.
369
+ def setBKattr(attrib)
370
+ @win.wbkgd(attrib)
371
+ @list_win.wbkgd(attrib)
372
+ unless @scrollbar_win.nil?
373
+ @scrollbar_win.wbkgd(attrib)
374
+ end
375
+ end
376
+
377
+ # This function destroys
378
+ def destroy
379
+ self.cleanTitle
380
+
381
+ # Clean up the windows.
382
+ CDK.deleteCursesWindow(@scrollbar_win)
383
+ CDK.deleteCursesWindow(@shadow_win)
384
+ CDK.deleteCursesWindow(@list_win)
385
+ CDK.deleteCursesWindow(@win)
386
+
387
+ # Clean the key bindings.
388
+ self.cleanBindings(:SCROLL)
389
+
390
+ # Unregister this object
391
+ CDK::SCREEN.unregister(:SCROLL, self)
392
+ end
393
+
394
+ # This function erases the scrolling list from the screen.
395
+ def erase
396
+ CDK.eraseCursesWindow(@win)
397
+ CDK.eraseCursesWindow(@shadow_win)
398
+ end
399
+
400
+ def allocListArrays(old_size, new_size)
401
+ result = true
402
+ new_list = Array.new(new_size)
403
+ new_len = Array.new(new_size)
404
+ new_pos = Array.new(new_size)
405
+
406
+ (0...old_size).each do |n|
407
+ new_list[n] = @item[n]
408
+ new_len[n] = @item_len[n]
409
+ new_pos[n] = @item_pos[n]
410
+ end
411
+
412
+ @item = new_list
413
+ @item_len = new_len
414
+ @item_pos = new_pos
415
+
416
+ return result
417
+ end
418
+
419
+ def allocListItem(which, work, used, number, value)
420
+ if number > 0
421
+ value = "%4d. %s" % [number, value]
422
+ end
423
+
424
+ item_len = []
425
+ item_pos = []
426
+ @item[which] = CDK.char2Chtype(value, item_len, item_pos)
427
+ @item_len[which] = item_len[0]
428
+ @item_pos[which] = item_pos[0]
429
+
430
+ @item_pos[which] = CDK.justifyString(@box_width,
431
+ @item_len[which], @item_pos[which])
432
+ return true
433
+ end
434
+
435
+ # This function creates the scrolling list information and sets up the
436
+ # needed variables for the scrolling list to work correctly.
437
+ def createItemList(numbers, list, list_size)
438
+ status = 0
439
+ if list_size > 0
440
+ widest_item = 0
441
+ x = 0
442
+ have = 0
443
+ temp = ''
444
+ if allocListArrays(0, list_size)
445
+ # Create the items in the scrolling list.
446
+ status = 1
447
+ (0...list_size).each do |x|
448
+ number = if numbers then x + 1 else 0 end
449
+ if !self.allocListItem(x, temp, have, number, list[x])
450
+ status = 0
451
+ break
452
+ end
453
+
454
+ widest_item = [@item_len[x], widest_item].max
455
+ end
456
+
457
+ if status
458
+ self.updateViewWidth(widest_item);
459
+
460
+ # Keep the boolean flag 'numbers'
461
+ @numbers = numbers
462
+ end
463
+ end
464
+ else
465
+ status = 1 # null list is ok - for a while
466
+ end
467
+
468
+ return status
469
+ end
470
+
471
+ # This sets certain attributes of the scrolling list.
472
+ def set(list, list_size, numbers, highlight, box)
473
+ self.setItems(list, list_size, numbers)
474
+ self.setHighlight(highlight)
475
+ self.setBox(box)
476
+ end
477
+
478
+ # This sets the scrolling list items
479
+ def setItems(list, list_size, numbers)
480
+ if self.createItemList(numbers, list, list_size) <= 0
481
+ return
482
+ end
483
+
484
+ # Clean up the display.
485
+ (0...@view_size).each do |x|
486
+ Draw.writeBlanks(@win, 1, x, CDK::HORIZONTAL, 0, @box_width - 2);
487
+ end
488
+
489
+ self.setViewSize(list_size)
490
+ self.setPosition(0)
491
+ @left_char = 0
492
+ end
493
+
494
+ def getItems(list)
495
+ (0...@list_size).each do |x|
496
+ list << CDK.chtype2Char(@item[x])
497
+ end
498
+
499
+ return @list_size
500
+ end
501
+
502
+ # This sets the highlight of the scrolling list.
503
+ def setHighlight(highlight)
504
+ @highlight = highlight
505
+ end
506
+
507
+ def getHighlight(highlight)
508
+ return @highlight
509
+ end
510
+
511
+ # Resequence the numbers after an insertion/deletion.
512
+ def resequence
513
+ if @numbers
514
+ (0...@list_size).each do |j|
515
+ target = @item[j]
516
+
517
+ source = "%4d. %s" % [j + 1, ""]
518
+
519
+ k = 0
520
+ while k < source.size
521
+ # handle deletions that change the length of number
522
+ if source[k] == "." && target[k] != "."
523
+ source = source[0...k] + source[k+1..-1]
524
+ end
525
+
526
+ target[k] &= Curses::A_ATTRIBUTES
527
+ target[k] |= source[k].ord
528
+ k += 1
529
+ end
530
+ end
531
+ end
532
+ end
533
+
534
+ def insertListItem(item)
535
+ @item = @item[0..item] + @item[item..-1]
536
+ @item_len = @item_len[0..item] + @item_len[item..-1]
537
+ @item_pos = @item_pos[0..item] + @item_pos[item..-1]
538
+ return true
539
+ end
540
+
541
+ # This adds a single item to a scrolling list, at the end of the list.
542
+ def addItem(item)
543
+ item_number = @list_size
544
+ widest_item = self.WidestItem
545
+ temp = ''
546
+ have = 0
547
+
548
+ if self.allocListArrays(@list_size, @list_size + 1) &&
549
+ self.allocListItem(item_number, temp, have,
550
+ if @numbers then item_number + 1 else 0 end,
551
+ item)
552
+ # Determine the size of the widest item.
553
+ widest_item = [@item_len[item_number], widest_item].max
554
+
555
+ self.updateViewWidth(widest_item)
556
+ self.setViewSize(@list_size + 1)
557
+ end
558
+ end
559
+
560
+ # This adds a single item to a scrolling list before the current item
561
+ def insertItem(item)
562
+ widest_item = self.WidestItem
563
+ temp = ''
564
+ have = 0
565
+
566
+ if self.allocListArrays(@list_size, @list_size + 1) &&
567
+ self.insertListItem(@current_item) &&
568
+ self.allocListItem(@current_item, temp, have,
569
+ if @numbers then @current_item + 1 else 0 end,
570
+ item)
571
+ # Determine the size of the widest item.
572
+ widest_item = [@item_len[@current_item], widest_item].max
573
+
574
+ self.updateViewWidth(widest_item)
575
+ self.setViewSize(@list_size + 1)
576
+ self.resequence
577
+ end
578
+ end
579
+
580
+ # This removes a single item from a scrolling list.
581
+ def deleteItem(position)
582
+ if position >= 0 && position < @list_size
583
+ # Adjust the list
584
+ @item = @item[0...position] + @item[position+1..-1]
585
+ @item_len = @item_len[0...position] + @item_len[position+1..-1]
586
+ @item_pos = @item_pos[0...position] + @item_pos[position+1..-1]
587
+
588
+ self.setViewSize(@list_size - 1)
589
+
590
+ if @list_size > 0
591
+ self.resequence
592
+ end
593
+
594
+ if @list_size < self.maxViewSize
595
+ @win.erase # force the next redraw to be complete
596
+ end
597
+
598
+ # do this to update the view size, etc
599
+ self.setPosition(@current_item)
600
+ end
601
+ end
602
+
603
+ def focus
604
+ self.drawCurrent
605
+ @list_win.refresh
606
+ end
607
+
608
+ def unfocus
609
+ self.drawCurrent
610
+ @list_win.refresh
611
+ end
612
+
613
+ def AvailableWidth
614
+ @box_width - (2 * @border_size)
615
+ end
616
+
617
+ def updateViewWidth(widest)
618
+ @max_left_char = if @box_width > widest
619
+ then 0
620
+ else widest - self.AvailableWidth
621
+ end
622
+ end
623
+
624
+ def WidestItem
625
+ @max_left_char + self.AvailableWidth
626
+ end
627
+ end
628
+
629
+ class BUTTON < CDK::CDKOBJS
630
+ def initialize(cdkscreen, xplace, yplace, text, callback, box, shadow)
631
+ super()
632
+ parent_width = cdkscreen.window.maxx
633
+ parent_height = cdkscreen.window.maxy
634
+ box_width = 0
635
+ xpos = xplace
636
+ ypos = yplace
637
+
638
+ self.setBox(box)
639
+ box_height = 1 + 2 * @border_size
640
+
641
+ # Translate the string to a chtype array.
642
+ info_len = []
643
+ info_pos = []
644
+ @info = CDK.char2Chtype(text, info_len, info_pos)
645
+ @info_len = info_len[0]
646
+ @info_pos = info_pos[0]
647
+ box_width = [box_width, @info_len].max + 2 * @border_size
648
+
649
+ # Create the string alignments.
650
+ @info_pos = CDK.justifyString(box_width - 2 * @border_size,
651
+ @info_len, @info_pos)
652
+
653
+ # Make sure we didn't extend beyond the dimensions of the window.
654
+ box_width = if box_width > parent_width
655
+ then parent_width
656
+ else box_width
657
+ end
658
+ box_height = if box_height > parent_height
659
+ then parent_height
660
+ else box_height
661
+ end
662
+
663
+ # Rejustify the x and y positions if we need to.
664
+ xtmp = [xpos]
665
+ ytmp = [ypos]
666
+ CDK.alignxy(cdkscreen.window, xtmp, ytmp, box_width, box_height)
667
+ xpos = xtmp[0]
668
+ ypos = ytmp[0]
669
+
670
+ # Create the button.
671
+ @screen = cdkscreen
672
+ # ObjOf (button)->fn = &my_funcs;
673
+ @parent = cdkscreen.window
674
+ @win = Curses::Window.new(box_height, box_width, ypos, xpos)
675
+ @shadow_win = nil
676
+ @xpos = xpos
677
+ @ypos = ypos
678
+ @box_width = box_width
679
+ @box_height = box_height
680
+ @callback = callback
681
+ @input_window = @win
682
+ @accepts_focus = true
683
+ @shadow = shadow
684
+
685
+ if @win.nil?
686
+ self.destroy
687
+ return nil
688
+ end
689
+
690
+ @win.keypad(true)
691
+
692
+ # If a shadow was requested, then create the shadow window.
693
+ if shadow
694
+ @shadow_win = Curses::Window.new(box_height, box_width,
695
+ ypos + 1, xpos + 1)
696
+ end
697
+
698
+ # Register this baby.
699
+ cdkscreen.register(:BUTTON, self)
700
+ end
701
+
702
+ # This was added for the builder.
703
+ def activate(actions)
704
+ self.draw(@box)
705
+ ret = -1
706
+
707
+ if actions.nil? || actions.size == 0
708
+ while true
709
+ input = self.getch([])
710
+
711
+ # Inject the character into the widget.
712
+ ret = self.inject(input)
713
+ if @exit_type != :EARLY_EXIT
714
+ return ret
715
+ end
716
+ end
717
+ else
718
+ # Inject each character one at a time.
719
+ actions.each do |x|
720
+ ret = self.inject(action)
721
+ if @exit_type == :EARLY_EXIT
722
+ return ret
723
+ end
724
+ end
725
+ end
726
+
727
+ # Set the exit type and exit
728
+ self.setExitType(0)
729
+ return -1
730
+ end
731
+
732
+ # This sets multiple attributes of the widget.
733
+ def set(mesg, box)
734
+ self.setMessage(mesg)
735
+ self.setBox(box)
736
+ end
737
+
738
+ # This sets the information within the button.
739
+ def setMessage(info)
740
+ info_len = []
741
+ info_pos = []
742
+ @info = CDK.char2Chtype(info, info_len, info_pos)
743
+ @info_len = info_len[0]
744
+ @info_pos = CDK.justifyString(@box_width - 2 * @border_size,
745
+ info_pos[0])
746
+
747
+ # Redraw the button widget.
748
+ self.erase
749
+ self.draw(box)
750
+ end
751
+
752
+ def getMessage
753
+ return @info
754
+ end
755
+
756
+ # This sets the background attribute of the widget.
757
+ def setBKattr(attrib)
758
+ @win.wbkgd(attrib)
759
+ end
760
+
761
+ def drawText
762
+ box_width = @box_width
763
+
764
+ # Draw in the message.
765
+ (0...(box_width - 2 * @border_size)).each do |i|
766
+ pos = @info_pos
767
+ len = @info_len
768
+ if i >= pos && (i - pos) < len
769
+ c = @info[i - pos]
770
+ else
771
+ c = ' '
772
+ end
773
+
774
+ if @has_focus
775
+ c = Curses::A_REVERSE | c
776
+ end
777
+
778
+ @win.mvwaddch(@border_size, i + @border_size, c)
779
+ end
780
+ end
781
+
782
+ # This draws the button widget
783
+ def draw(box)
784
+ # Is there a shadow?
785
+ unless @shadow_win.nil?
786
+ Draw.drawShadow(@shadow_win)
787
+ end
788
+
789
+ # Box the widget if asked.
790
+ if @box
791
+ Draw.drawObjBox(@win, self)
792
+ end
793
+ self.drawText
794
+ @win.refresh
795
+ end
796
+
797
+ # This erases the button widget.
798
+ def erase
799
+ if self.validCDKObject
800
+ CDK.eraseCursesWindow(@win)
801
+ CDK.eraseCursesWindow(@shadow_win)
802
+ end
803
+ end
804
+
805
+ # This moves the button field to the given location.
806
+ def move(xplace, yplace, relative, refresh_flag)
807
+ current_x = @win.begx
808
+ current_y = @win.begy
809
+ xpos = xplace
810
+ ypos = yplace
811
+
812
+ # If this is a relative move, then we will adjust where we want
813
+ # to move to.
814
+ if relative
815
+ xpos = @win.begx + xplace
816
+ ypos = @win.begy + yplace
817
+ end
818
+
819
+ # Adjust the window if we need to.
820
+ xtmp = [xpos]
821
+ ytmp = [ypos]
822
+ CDK.alignxy(@screen.window, xtmp, ytmp, @box_width, @box_height)
823
+ xpos = xtmp[0]
824
+ ypos = ytmp[0]
825
+
826
+ # Get the difference
827
+ xdiff = current_x - xpos
828
+ ydiff = current_y - ypos
829
+
830
+ # Move the window to the new location.
831
+ CDK.moveCursesWindow(@win, -xdiff, -ydiff)
832
+ CDK.moveCursesWindow(@shadow_win, -xdiff, -ydiff)
833
+
834
+ # Thouch the windows so they 'move'.
835
+ CDK::SCREEN.refreshCDKWindow(@screen.window)
836
+
837
+ # Redraw the window, if they asked for it.
838
+ if refresh_flag
839
+ self.draw(@box)
840
+ end
841
+ end
842
+
843
+ # This allows the user to use the cursor keys to adjust the
844
+ # position of the widget.
845
+ def position
846
+ # Declare some variables
847
+ orig_x = @win.begx
848
+ orig_y = @win.begy
849
+ key = 0
850
+
851
+ # Let them move the widget around until they hit return
852
+ # SUSPECT FOR BUG
853
+ while key != Curses::KEY_ENTER && key != CDK::KEY_RETURN
854
+ key = self.getch([])
855
+ if key == Curses::KEY_UP || key == '8'
856
+ if @win.begy > 0
857
+ self.move(0, -1, true, true)
858
+ else
859
+ CDK.Beep
860
+ end
861
+ elsif key == Curses::KEY_DOWN || key == '2'
862
+ if @win.begy + @win.maxy < @screen.window.maxy - 1
863
+ self.move(0, 1, true, true)
864
+ else
865
+ CDK.Beep
866
+ end
867
+ elsif key == Curses::KEY_LEFT || key == '4'
868
+ if @win.begx > 0
869
+ self.move(-1, 0, true, true)
870
+ else
871
+ CDK.Beep
872
+ end
873
+ elsif key == Curses::KEY_RIGHT || key == '6'
874
+ if @win.begx + @win.maxx < @screen.window.maxx - 1
875
+ self.move(1, 0, true, true)
876
+ else
877
+ CDK.Beep
878
+ end
879
+ elsif key == '7'
880
+ if @win.begy > 0 && @win.begx > 0
881
+ self.move(-1, -1, true, true)
882
+ else
883
+ CDK.Beep
884
+ end
885
+ elsif key == '9'
886
+ if @win.begx + @win.maxx < @screen.window.maxx - 1 &&
887
+ @win.begy > 0
888
+ self.move(1, -1, true, true)
889
+ else
890
+ CDK.Beep
891
+ end
892
+ elsif key == '1'
893
+ if @win.begx > 0 &&
894
+ @win.begx + @win.maxx < @screen.window.maxx - 1
895
+ self.move(-1, 1, true, true)
896
+ else
897
+ CDK.Beep
898
+ end
899
+ elsif key == '3'
900
+ if @win.begx + @win.maxx < @screen.window.maxx - 1 &&
901
+ @win.begy + @win.maxy < @screen.window.maxy - 1
902
+ self.move(1, 1, true, true)
903
+ else
904
+ CDK.Beep
905
+ end
906
+ elsif key == '5'
907
+ self.move(CDK::CENTER, CDK::CENTER, false, true)
908
+ elsif key == 't'
909
+ self.move(@win.begx, CDK::TOP, false, true)
910
+ elsif key == 'b'
911
+ self.move(@win.begx, CDK::BOTTOM, false, true)
912
+ elsif key == 'l'
913
+ self.move(CDK::LEFT, @win.begy, false, true)
914
+ elsif key == 'r'
915
+ self.move(CDK::RIGHT, @win.begy, false, true)
916
+ elsif key == 'c'
917
+ self.move(CDK::CENTER, @win.begy, false, true)
918
+ elsif key == 'C'
919
+ self.move(@win.begx, CDK::CENTER, false, true)
920
+ elsif key == CDK::REFRESH
921
+ @screen.erase
922
+ @screen.refresh
923
+ elsif key == CDK::KEY_ESC
924
+ self.move(orig_x, orig_y, false, true)
925
+ elsif key != CDK::KEY_RETURN && key != Curses::KEY_ENTER
926
+ CDK.Beep
927
+ end
928
+ end
929
+ end
930
+
931
+ # This destroys the button object pointer.
932
+ def destroy
933
+ CDK.deleteCursesWindow(@shadow_win)
934
+ CDK.deleteCursesWindow(@win)
935
+
936
+ self.cleanBindings(:BUTTON)
937
+
938
+ CDK::SCREEN.unregister(:BUTTON, self)
939
+ end
940
+
941
+ # This injects a single character into the widget.
942
+ def inject(input)
943
+ ret = -1
944
+ complete = false
945
+
946
+ self.setExitType(0)
947
+
948
+ # Check a predefined binding.
949
+ if self.checkBind(:BUTTON, input)
950
+ complete = true
951
+ else
952
+ case input
953
+ when CDK::KEY_ESC
954
+ self.setExitType(input)
955
+ complete = true
956
+ when Curses::Error
957
+ self.setExitType(input)
958
+ complete = true
959
+ when ' ', CDK::KEY_RETURN, Curses::KEY_ENTER
960
+ unless @callback.nil?
961
+ @callback.call(self)
962
+ end
963
+ self.setExitType(Curses::KEY_ENTER)
964
+ ret = 0
965
+ complete = true
966
+ when CDK::REFRESH
967
+ @screen.erase
968
+ @screen.refresh
969
+ else
970
+ CDK.Beep
971
+ end
972
+ end
973
+
974
+ unless complete
975
+ self.setExitType(0)
976
+ end
977
+
978
+ @result_data = ret
979
+ return ret
980
+ end
981
+
982
+ def focus
983
+ self.drawText
984
+ @win.refresh
985
+ end
986
+
987
+ def unfocus
988
+ self.drawText
989
+ @win.refresh
990
+ end
991
+
992
+ def object_type
993
+ :BUTTON
994
+ end
995
+ end
996
+ end