Class: CDK::SCROLL

Inherits:
SCROLLER show all
Defined in:
lib/cdk/scroll.rb

Instance Attribute Summary collapse

Attributes inherited from CDKOBJS

#BXAttr, #HZChar, #LLChar, #LRChar, #ULChar, #URChar, #VTChar, #accepts_focus, #binding_list, #border_size, #box, #exit_type, #has_focus, #is_visible, #screen, #screen_index

Instance Method Summary collapse

Methods inherited from SCROLLER

#KEY_DOWN, #KEY_END, #KEY_HOME, #KEY_LEFT, #KEY_NPAGE, #KEY_PPAGE, #KEY_RIGHT, #KEY_UP, #getCurrentItem, #maxViewSize, #setCurrentItem, #setPosition, #setViewSize

Methods inherited from CDKOBJS

#SCREEN_XPOS, #SCREEN_YPOS, #bind, #bindableObject, #checkBind, #cleanBindings, #cleanTitle, #drawTitle, #getBox, #getc, #getch, #isBind, #move_specific, #refreshData, #saveData, #setBXattr, #setBackgroundColor, #setBox, #setExitType, #setHZchar, #setLLchar, #setLRchar, #setPostProcess, #setPreProcess, #setTitle, #setULchar, #setURchar, #setVTchar, #unbind, #validCDKObject, #validObjType

Constructor Details

#initialize(cdkscreen, xplace, yplace, splace, height, width, title, list, list_size, numbers, highlight, box, shadow) ⇒ SCROLL

Returns a new instance of SCROLL.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/cdk/scroll.rb', line 7

def initialize (cdkscreen, xplace, yplace, splace, height, width, title,
    list, list_size, numbers, highlight, box, shadow)
  super()
  parent_width = cdkscreen.window.getmaxx
  parent_height = cdkscreen.window.getmaxy
  box_width = width
  box_height = height
  xpos = xplace
  ypos = yplace
  scroll_adjust = 0
  bindings = {
    CDK::BACKCHAR => Ncurses::KEY_PPAGE,
    CDK::FORCHAR  => Ncurses::KEY_NPAGE,
    'g'           => Ncurses::KEY_HOME,
    '1'           => Ncurses::KEY_HOME,
    'G'           => Ncurses::KEY_END,
    '<'           => Ncurses::KEY_HOME,
    '>'           => Ncurses::KEY_END
  }

  self.setBox(box)

  # If the height is a negative value, the height will be ROWS-height,
  # otherwise the height will be the given height
  box_height = CDK.setWidgetDimension(parent_height, height, 0)

  # If the width is a negative value, the width will be COLS-width,
  # otherwise the width will be the given width
  box_width = CDK.setWidgetDimension(parent_width, width, 0)

  box_width = self.setTitle(title, box_width)

  # Set the box height.
  if @title_lines > box_height
    box_height = @title_lines + [list_size, 8].min + 2 * @border_size
  end

  # Adjust the box width if there is a scroll bar
  if splace == CDK::LEFT || splace == CDK::RIGHT
    @scrollbar = true
    box_width += 1
  else
    @scrollbar = false
  end

  # Make sure we didn't extend beyond the dimensions of the window.
  @box_width = if box_width > parent_width 
               then parent_width - scroll_adjust 
               else box_width 
               end
  @box_height = if box_height > parent_height
                then parent_height
                else box_height
                end

  self.setViewSize(list_size)

  # Rejustify the x and y positions if we need to.
  xtmp = [xpos]
  ytmp = [ypos] 
  CDK.alignxy(cdkscreen.window, xtmp, ytmp, @box_width, @box_height)
  xpos = xtmp[0]
  ypos = ytmp[0]

  # Make the scrolling window
  @win = Ncurses::WINDOW.new(@box_height, @box_width, ypos, xpos)

  # Is the scrolling window null?
  if @win.nil?
    return nil
  end

  # Turn the keypad on for the window
  @win.keypad(true)

  # Create the scrollbar window.
  if splace == CDK::RIGHT
    @scrollbar_win = @win.subwin(self.maxViewSize, 1,
        self.SCREEN_YPOS(ypos), xpos + box_width - @border_size - 1)
  elsif splace == CDK::LEFT
    @scrollbar_win = @win.subwin(self.maxViewSize, 1,
        self.SCREEN_YPOS(ypos), self.SCREEN_XPOS(xpos))
  else
    @scrollbar_win = nil
  end

  # create the list window
  @list_win = @win.subwin(self.maxViewSize,
      box_width - (2 * @border_size) - scroll_adjust,
      self.SCREEN_YPOS(ypos),
      self.SCREEN_XPOS(xpos) + (if splace == CDK::LEFT then 1 else 0 end))

  # Set the rest of the variables
  @screen = cdkscreen
  @parent = cdkscreen.window
  @shadow_win = nil
  @scrollbar_placement = splace
  @max_left_char = 0
  @left_char = 0
  @highlight = highlight
  # initExitType (scrollp);
  @accepts_focus = true
  @input_window = @win
  @shadow = shadow

  self.setPosition(0);

  # Create the scrolling list item list and needed variables.
  if self.createItemList(numbers, list, list_size) <= 0
    return nil
  end

  # Do we need to create a shadow?
  if shadow
    @shadow_win = Ncurses::WINDOW.new(@box_height, box_width,
        ypos + 1, xpos + 1)
  end

  # Set up the key bindings.
  bindings.each do |from, to|
    #self.bind(:SCROLL, from, getc_lambda, to)
    self.bind(:SCROLL, from, :getc, to)
  end

  cdkscreen.register(:SCROLL, self);
  
  return self
end

Instance Attribute Details

#current_itemObject (readonly)

Returns the value of attribute current_item.



5
6
7
# File 'lib/cdk/scroll.rb', line 5

def current_item
  @current_item
end

#highlightObject (readonly)

Returns the value of attribute highlight.



5
6
7
# File 'lib/cdk/scroll.rb', line 5

def highlight
  @highlight
end

#itemObject (readonly)

Returns the value of attribute item.



5
6
7
# File 'lib/cdk/scroll.rb', line 5

def item
  @item
end

#list_sizeObject (readonly)

Returns the value of attribute list_size.



5
6
7
# File 'lib/cdk/scroll.rb', line 5

def list_size
  @list_size
end

Instance Method Details

#activate(actions) ⇒ Object

This actually does all the ‘real’ work of managing the scrolling list.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/cdk/scroll.rb', line 155

def activate(actions)
  # Draw the scrolling list
  self.draw(@box)

  if actions.nil? || actions.size == 0
    while true
      self.fixCursorPosition
      input = self.getch([])

      # Inject the character into the widget.
      ret = self.inject(input)
      if @exit_type != :EARLY_EXIT
        return ret
      end
    end
  else
    # Inject each character one at a time.
    actions.each do |action|
      ret = self.inject(action)
      if @exit_type != :EARLY_EXIT
        return ret
      end
    end
  end

  # Set the exit type for the widget and return
  self.setExitType(0)
  return -1
end

#addItem(item) ⇒ Object

This adds a single item to a scrolling list, at the end of the list.



541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
# File 'lib/cdk/scroll.rb', line 541

def addItem(item)
  item_number = @list_size
  widest_item = self.WidestItem
  temp = ''
  have = 0

  if self.allocListArrays(@list_size, @list_size + 1) &&
      self.allocListItem(item_number, temp, have,
      if @numbers then item_number + 1 else 0 end,
      item)
    # Determine the size of the widest item.
    widest_item = [@item_len[item_number], widest_item].max

    self.updateViewWidth(widest_item)
    self.setViewSize(@list_size + 1)
  end
end

#allocListArrays(old_size, new_size) ⇒ Object



399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
# File 'lib/cdk/scroll.rb', line 399

def allocListArrays(old_size, new_size)
  result = true
  new_list = Array.new(new_size)
  new_len = Array.new(new_size)
  new_pos = Array.new(new_size)

  (0...old_size).each do |n|
    new_list[n] = @item[n]
    new_len[n] = @item_len[n]
    new_pos[n] = @item_pos[n]
  end

  @item = new_list
  @item_len = new_len
  @item_pos = new_pos

  return result
end

#allocListItem(which, work, used, number, value) ⇒ Object



418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/cdk/scroll.rb', line 418

def allocListItem(which, work, used, number, value)
  if number > 0
    value = "%4d. %s" % [number, value]
  end

  item_len = []
  item_pos = []
  @item[which] = CDK.char2Chtype(value, item_len, item_pos)
  @item_len[which] = item_len[0]
  @item_pos[which] = item_pos[0]

  @item_pos[which] = CDK.justifyString(@box_width,
      @item_len[which], @item_pos[which])
  return true
end

#AvailableWidthObject



612
613
614
# File 'lib/cdk/scroll.rb', line 612

def AvailableWidth
  @box_width - (2 * @border_size)
end

#createItemList(numbers, list, list_size) ⇒ Object

This function creates the scrolling list information and sets up the needed variables for the scrolling list to work correctly.



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/cdk/scroll.rb', line 436

def createItemList(numbers, list, list_size)
  status = 0
  if list_size > 0
    widest_item = 0
    x = 0
    have = 0
    temp = ''
    if allocListArrays(0, list_size)
      # Create the items in the scrolling list.
      status = 1
      (0...list_size).each do |x|
        number = if numbers then x + 1 else 0 end
        if !self.allocListItem(x, temp, have, number, list[x])
          status = 0
          break
        end

        widest_item = [@item_len[x], widest_item].max
      end

      if status
        self.updateViewWidth(widest_item);

        # Keep the boolean flag 'numbers'
        @numbers = numbers
      end
    end
  else
    status = 1  # null list is ok - for a while
  end

  return status
end

#deleteItem(position) ⇒ Object

This removes a single item from a scrolling list.



580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
# File 'lib/cdk/scroll.rb', line 580

def deleteItem(position)
  if position >= 0 && position < @list_size
    # Adjust the list
    @item = @item[0...position] + @item[position+1..-1]
    @item_len = @item_len[0...position] + @item_len[position+1..-1]
    @item_pos = @item_pos[0...position] + @item_pos[position+1..-1]

    self.setViewSize(@list_size - 1)

    if @list_size > 0
      self.resequence
    end

    if @list_size < self.maxViewSize
      @win.werase  # force the next redraw to be complete
    end

    # do this to update the view size, etc
    self.setPosition(@current_item)
  end
end

#destroyObject

This function destroys



377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/cdk/scroll.rb', line 377

def destroy
  self.cleanTitle

  # Clean up the windows.
  CDK.deleteCursesWindow(@scrollbar_win)
  CDK.deleteCursesWindow(@shadow_win)
  CDK.deleteCursesWindow(@list_win)
  CDK.deleteCursesWindow(@win)

  # Clean the key bindings.
  self.cleanBindings(:SCROLL)

  # Unregister this object
  CDK::SCREEN.unregister(:SCROLL, self)
end

#draw(box) ⇒ Object

This function draws the scrolling list widget.



287
288
289
290
291
292
293
294
295
296
297
# File 'lib/cdk/scroll.rb', line 287

def draw(box)
  # Draw in the shadow if we need to.
  unless @shadow_win.nil?
    Draw.drawShadow(@shadow_win)
  end

  self.drawTitle(@win)

  # Draw in the scrolling list items.
  self.drawList(box)
end

#drawCurrentObject



299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/cdk/scroll.rb', line 299

def drawCurrent
  # Rehighlight the current menu item.
  screen_pos = @item_pos[@current_item] - @left_char
  highlight = if self.has_focus
              then @highlight
              else Ncurses::A_NORMAL
              end

  Draw.writeChtypeAttrib(@list_win,
      if screen_pos >= 0 then screen_pos else 0 end,
      @current_high, @item[@current_item], highlight, CDK::HORIZONTAL,
      if screen_pos >= 0 then 0 else 1 - screen_pos end,
      @item_len[@current_item])
end

#drawList(box) ⇒ Object



314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/cdk/scroll.rb', line 314

def drawList(box)
  # If the list is empty, don't draw anything.
  if @list_size > 0
    # Redraw the list
    (0...@view_size).each do |j|
      k = j + @current_top

      Draw.writeBlanks(@list_win, 0, j, CDK::HORIZONTAL, 0,
        @box_width - (2 * @border_size))

      # Draw the elements in the scrolling list.
      if k < @list_size
        screen_pos = @item_pos[k] - @left_char
        ypos = j

        # Write in the correct line.
        Draw.writeChtype(@list_win,
            if screen_pos >= 0 then screen_pos else 1 end,
            ypos, @item[k], CDK::HORIZONTAL,
            if screen_pos >= 0 then 0 else 1 - screen_pos end,
            @item_len[k])
      end
    end

    self.drawCurrent

    # Determine where the toggle is supposed to be.
    unless @scrollbar_win.nil?
      @toggle_pos = (@current_item * @step).floor

      # Make sure the toggle button doesn't go out of bounds.
      
      if @toggle_pos >= @scrollbar_win.getmaxy
        @toggle_pos = @scrollbar_win.getmaxy - 1
      end

      # Draw the scrollbar
      @scrollbar_win.mvwvline(0, 0, Ncurses::ACS_CKBOARD,
          @scrollbar_win.getmaxy)
      @scrollbar_win.mvwvline(@toggle_pos, 0, ' '.ord | Ncurses::A_REVERSE,
          @toggle_size)
    end
  end

  # Box it if needed.
  if box
    Draw.drawObjBox(@win, self)
  end

  # Refresh the window
  @win.wrefresh
end

#eraseObject

This function erases the scrolling list from the screen.



394
395
396
397
# File 'lib/cdk/scroll.rb', line 394

def erase
  CDK.eraseCursesWindow(@win)
  CDK.eraseCursesWindow(@shadow_win)
end

#fixCursorPositionObject

Put the cursor on the currently-selected item’s row.



145
146
147
148
149
150
151
152
# File 'lib/cdk/scroll.rb', line 145

def fixCursorPosition
  scrollbar_adj = if @scrollbar_placement == LEFT then 1 else 0 end
  ypos = self.SCREEN_YPOS(@current_item - @current_top)
  xpos = self.SCREEN_XPOS(0) + scrollbar_adj

  @input_window.wmove(ypos, xpos)
  @input_window.wrefresh
end

#focusObject



602
603
604
605
# File 'lib/cdk/scroll.rb', line 602

def focus
  self.drawCurrent
  @list_win.wrefresh
end

#getCurrentTopObject



264
265
266
# File 'lib/cdk/scroll.rb', line 264

def getCurrentTop
  return @current_top
end

#getHighlight(highlight) ⇒ Object



506
507
508
# File 'lib/cdk/scroll.rb', line 506

def getHighlight(highlight)
  return @highlight
end

#getItems(list) ⇒ Object



493
494
495
496
497
498
499
# File 'lib/cdk/scroll.rb', line 493

def getItems(list)
  (0...@list_size).each do |x|
    list << CDK.chtype2Char(@item[x])
  end

  return @list_size
end

#inject(input) ⇒ Object

This injects a single character into the widget.



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/cdk/scroll.rb', line 186

def inject(input)
  pp_return = 1
  ret = -1
  complete = false

  # Set the exit type for the widget.
  self.setExitType(0)

  # Draw the scrolling list
  self.drawList(@box)

  #Check if there is a pre-process function to be called.
  unless @pre_process_func.nil?
    pp_return = @pre_process_func.call(:SCROLL, self,
        @pre_process_data, input)
  end

  # Should we continue?
  if pp_return != 0
    # Check for a predefined key binding.
    if self.checkBind(:SCROLL, input) != false
      #self.checkEarlyExit
      complete = true
    else
      case input
      when Ncurses::KEY_UP
        self.KEY_UP
      when Ncurses::KEY_DOWN
        self.KEY_DOWN
      when Ncurses::KEY_RIGHT
        self.KEY_RIGHT
      when Ncurses::KEY_LEFT
        self.KEY_LEFT
      when Ncurses::KEY_PPAGE
        self.KEY_PPAGE
      when Ncurses::KEY_NPAGE
        self.KEY_NPAGE
      when Ncurses::KEY_HOME
        self.KEY_HOME
      when Ncurses::KEY_END
        self.KEY_END
      when '$'
        @left_char = @max_left_char
      when '|'
        @left_char = 0
      when CDK::KEY_ESC
        self.setExitType(input)
        complete = true
      when Ncurses::ERR
        self.setExitType(input)
        complete = true
      when CDK::REFRESH
        @screen.erase
        @screen.refresh
      when CDK::KEY_TAB, Ncurses::KEY_ENTER, CDK::KEY_RETURN
        self.setExitType(input)
        ret = @current_item
        complete = true
      end
    end

    if !complete && !(@post_process_func.nil?)
      @post_process_func.call(:SCROLL, self, @post_process_data, input)
    end
  end

  if !complete
    self.drawList(@box)
    self.setExitType(0)
  end

  self.fixCursorPosition
  @result_data = ret

  #return ret != -1
  return ret
end

#insertItem(item) ⇒ Object

This adds a single item to a scrolling list before the current item



560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
# File 'lib/cdk/scroll.rb', line 560

def insertItem(item)
  widest_item = self.WidestItem
  temp = ''
  have = 0

  if self.allocListArrays(@list_size, @list_size + 1) &&
      self.insertListItem(@current_item) &&
      self.allocListItem(@current_item, temp, have,
      if @numbers then @current_item + 1 else 0 end,
      item)
    # Determine the size of the widest item.
    widest_item = [@item_len[@current_item], widest_item].max

    self.updateViewWidth(widest_item)
    self.setViewSize(@list_size + 1)
    self.resequence
  end
end

#insertListItem(item) ⇒ Object



533
534
535
536
537
538
# File 'lib/cdk/scroll.rb', line 533

def insertListItem(item)
  @item = @item[0..item] + @item[item..-1]
  @item_len = @item_len[0..item] + @item_len[item..-1]
  @item_pos = @item_pos[0..item] + @item_pos[item..-1]
  return true
end

#move(xplace, yplace, relative, refresh_flag) ⇒ Object

This moves the scroll field to the given location.



280
281
282
283
284
# File 'lib/cdk/scroll.rb', line 280

def move(xplace, yplace, relative, refresh_flag)
  windows = [@win, @list_win, @shadow_win, @scrollbar_win]
  self.move_specific(xplace, yplace, relative, refresh_flag,
      windows, [])
end

#object_typeObject



136
137
138
# File 'lib/cdk/scroll.rb', line 136

def object_type
  :SCROLL
end

#positionObject



140
141
142
# File 'lib/cdk/scroll.rb', line 140

def position
  super(@win)
end

#resequenceObject

Resequence the numbers after an insertion/deletion.



511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
# File 'lib/cdk/scroll.rb', line 511

def resequence
  if @numbers
    (0...@list_size).each do |j|
      target = @item[j]

      source = "%4d. %s" % [j + 1, ""]

      k = 0
      while k < source.size
        # handle deletions that change the length of number
        if source[k] == "." && target[k] != "."
          source = source[0...k] + source[k+1..-1]
        end

        target[k] &= Ncurses::A_ATTRIBUTES
        target[k] |= source[k].ord
        k += 1
      end
    end
  end
end

#set(list, list_size, numbers, highlight, box) ⇒ Object

This sets certain attributes of the scrolling list.



471
472
473
474
475
# File 'lib/cdk/scroll.rb', line 471

def set(list, list_size, numbers, highlight, box)
  self.setItems(list, list_size, numbers)
  self.setHighlight(highlight)
  self.setBox(box)
end

#setBKattr(attrib) ⇒ Object

This sets the background attribute of the widget.



368
369
370
371
372
373
374
# File 'lib/cdk/scroll.rb', line 368

def setBKattr(attrib)
  @win.wbkgd(attrib)
  @list_win.wbkgd(attrib)
  unless @scrollbar_win.nil?
    @scrollbar_win.wbkgd(attrib)
  end
end

#setCurrentTop(item) ⇒ Object



268
269
270
271
272
273
274
275
276
277
# File 'lib/cdk/scroll.rb', line 268

def setCurrentTop(item)
  if item < 0
    item = 0
  elsif item > @max_top_item
    item = @max_top_item
  end
  @current_top = item

  self.setPosition(item);
end

#setHighlight(highlight) ⇒ Object

This sets the highlight of the scrolling list.



502
503
504
# File 'lib/cdk/scroll.rb', line 502

def setHighlight(highlight)
  @highlight = highlight
end

#setItems(list, list_size, numbers) ⇒ Object

This sets the scrolling list items



478
479
480
481
482
483
484
485
486
487
488
489
490
491
# File 'lib/cdk/scroll.rb', line 478

def setItems(list, list_size, numbers)
  if self.createItemList(numbers, list, list_size) <= 0
    return
  end

  # Clean up the display.
  (0...@view_size).each do |x|
    Draw.writeBlanks(@win, 1, x, CDK::HORIZONTAL, 0, @box_width - 2);
  end

  self.setViewSize(list_size)
  self.setPosition(0)
  @left_char = 0
end

#unfocusObject



607
608
609
610
# File 'lib/cdk/scroll.rb', line 607

def unfocus
  self.drawCurrent
  @list_win.wrefresh
end

#updateViewWidth(widest) ⇒ Object



616
617
618
619
620
621
# File 'lib/cdk/scroll.rb', line 616

def updateViewWidth(widest)
  @max_left_char = if @box_width > widest
                   then 0
                   else widest - self.AvailableWidth
                   end
end

#WidestItemObject



623
624
625
# File 'lib/cdk/scroll.rb', line 623

def WidestItem
  @max_left_char + self.AvailableWidth
end