Class: CDK::SELECTION

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

Instance Attribute Summary collapse

Attributes included from HasTitle

#title_attrib

Attributes included from HasScreen

#is_visible, #screen, #screen_index

Attributes included from ExitConditions

#exit_type

Attributes included from Bindings

#binding_list

Attributes included from Focusable

#accepts_focus, #has_focus

Attributes included from Borders

#BXAttr, #HZChar, #LLChar, #LRChar, #ULChar, #URChar, #VTChar, #border_size, #box

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

#setBackgroundColor, #timeout, #validCDKObject, #validObjType

Methods included from WindowHooks

#refreshData, #saveData

Methods included from WindowInput

#getc, #getch, #setPostProcess, #setPreProcess

Methods included from HasTitle

#cleanTitle, #drawTitle, #init_title, #setTitle

Methods included from HasScreen

#SCREEN_XPOS, #SCREEN_YPOS, #init_screen, #wrefresh

Methods included from ExitConditions

#init_exit_conditions, #resetExitType, #setExitType

Methods included from Bindings

#bind, #bindableObject, #checkBind, #cleanBindings, #init_bindings, #isBind, #unbind

Methods included from Focusable

#init_focus

Methods included from Borders

#getBox, #init_borders, #setBXattr, #setBox, #setHZchar, #setLLchar, #setLRchar, #setULchar, #setURchar, #setVTchar

Methods included from Movement

#move_specific

Methods included from Converters

#char2Chtype, #charOf, #chtype2Char, #chtype2String, #decode_attribute, #encode_attribute

Methods included from Justifications

#justify_string

Methods included from Alignments

#alignxy

Constructor Details

#initialize(cdkscreen, xplace, yplace, splace, height, width, title, list, list_size, choices, choice_count, highlight, box, shadow) ⇒ SELECTION

Returns a new instance of SELECTION.



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
135
136
137
138
# File 'lib/cdk/components/selection.rb', line 7

def initialize(cdkscreen, xplace, yplace, splace, height, width, title,
    list, list_size, choices, choice_count, highlight, box, shadow)
  super()
  widest_item = -1
  parent_width = cdkscreen.window.getmaxx
  parent_height = cdkscreen.window.getmaxy
  box_width = width
  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,
  }

  if choice_count <= 0
    self.destroy
    return nil
  end

  @choice = []
  @choicelen = []

  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

  @maxchoicelen = 0

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

  # Make sure we didn't extend beyond the dimensions of the window.
  @box_width = [box_width, parent_width].min
  @box_height = [box_height, parent_height].min

  self.setViewSize(list_size)

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

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

  # Is the window nil?
  if @win.nil?
    self.destroy
    return nil
  end

  # Turn the keypad on for this 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(ypos))
  else
    @scrollbar_win = nil
  end

  # Set the rest of the variables
  @screen = cdkscreen
  @parent = cdkscreen.window
  @scrollbar_placement = splace
  @max_left_char = 0
  @left_char = 0
  @highlight = highlight
  @choice_count = choice_count
  @accepts_focus = true
  @input_window = @win
  @shadow = shadow

  self.setCurrentItem(0)

  # Each choice has to be converted from string to chtype array
  (0...choice_count).each do |j|
    choicelen = []
    @choice << char2Chtype(choices[j], choicelen, [])
    @choicelen << choicelen[0]
    @maxchoicelen = [@maxchoicelen, choicelen[0]].max
  end

  # Each item in the needs to be converted to chtype array
  widest_item = self.createList(list, list_size)
  if widest_item > 0
    self.updateViewWidth(widest_item)
  elsif list_size > 0
    self.destroy
    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

  # Setup the key bindings
  bindings.each do |from, to|
    self.bind(:SELECTION, from, :getc, to)
  end

  # Register this baby.
  cdkscreen.register(:SELECTION, self)
end

Instance Attribute Details

#selectionsObject (readonly)

Returns the value of attribute selections.



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

def selections
  @selections
end

Instance Method Details

#activate(actions) ⇒ Object

This actually manages the selection widget



154
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
# File 'lib/cdk/components/selection.rb', line 154

def activate(actions)
  # Draw the selection 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 and return.
  self.setExitType(0)
  return 0
end

#AvailableWidthObject

Determine how many characters we can shift to the right before all the items have been scrolled off the screen.



592
593
594
# File 'lib/cdk/components/selection.rb', line 592

def AvailableWidth
  @box_width - 2 * @border_size - @maxchoicelen
end

#createList(list, list_size) ⇒ Object



545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
# File 'lib/cdk/components/selection.rb', line 545

def createList(list, list_size)
  status = 0
  widest_item = 0

  if list_size >= 0
    new_list = []
    new_len = []
    new_pos = []

    box_width = self.AvailableWidth
    adjust = @maxchoicelen + @border_size

    status = 1
    (0...list_size).each do |j|
      lentmp = []
      postmp = []
      new_list << char2Chtype(list[j], lentmp, postmp)
      new_len << lentmp[0]
      new_pos << postmp[0]
      #if new_list[j].size == 0
      if new_list[j].nil?
        status = 0
        break
      end
      new_pos[j] =
          justify_string(box_width, new_len[j], new_pos[j]) + adjust
      widest_item = [widest_item, new_len[j]].max
    end

    if status
      self.destroyInfo

      @item = new_list
      @item_pos = new_pos
      @item_len = new_len
      @selections = [0] * list_size
      @mode = [0] * list_size
    end
  else
    self.destroyInfo
  end

  return (if status then widest_item else 0 end)
end

#destroyObject

This function destroys the selection list.



363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/cdk/components/selection.rb', line 363

def destroy
  self.cleanTitle
  self.destroyInfo

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

  # Clean up the key bindings
  self.cleanBindings(:SELECTION)

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

#destroyInfoObject



358
359
360
# File 'lib/cdk/components/selection.rb', line 358

def destroyInfo
  @item = []
end

#draw(box) ⇒ Object

This function draws the selection list.



279
280
281
282
283
284
285
286
287
288
289
# File 'lib/cdk/components/selection.rb', line 279

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

  self.drawTitle(@win)

  # Redraw the list
  self.drawList(box)
end

#drawList(box) ⇒ Object

This function draws the selection list window.



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
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
# File 'lib/cdk/components/selection.rb', line 292

def drawList(box)
  scrollbar_adj = if @scrollbar_placement == LEFT then 1 else 0 end
  screen_pos = 0
  sel_item = -1

  # If there is to be a highlight, assign it now
  if @has_focus
    sel_item = @current_item
  end

  # draw the list...
  j = 0
  while j < @view_size && (j + @current_top) < @list_size
    k = j + @current_top
    if k < @list_size
      screen_pos = self.SCREENPOS(k, scrollbar_adj)
      ypos = self.SCREEN_YPOS(j)
      xpos = self.SCREEN_XPOS(0)

      # Draw the empty line.
      Draw.writeBlanks(@win, xpos, ypos, CDK::HORIZONTAL, 0, @win.getmaxx)

      # Draw the selection item.
      Draw.writeChtypeAttrib(@win,
          if screen_pos >= 0 then screen_pos else 1 end,
          ypos, @item[k],
          if k == sel_item then @highlight else Ncurses::A_NORMAL end,
          CDK::HORIZONTAL,
          if screen_pos >= 0 then 0 else 1 - screen_pos end,
          @item_len[k])

      # Draw the choice value
      Draw.writeChtype(@win, xpos + scrollbar_adj, ypos,
        @choice[@selections[k]], CDK::HORIZONTAL, 0,
        @choicelen[@selections[k]])
    end
    j += 1
  end

  # Determine where the toggle is supposed to be.
  if @scrollbar
    @toggle_pos = (@current_item * @step).floor
    @toggle_pos = [@toggle_pos, @scrollbar_win.getmaxy - 1].min

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

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

  self.fixCursorPosition
end

#eraseObject

This function erases the selection list from the screen.



380
381
382
383
384
385
# File 'lib/cdk/components/selection.rb', line 380

def erase
  if self.validCDKObject
    CDK.eraseCursesWindow(@win)
    CDK.eraseCursesWindow(@shadow_win)
  end
end

#fixCursorPositionObject

Put the cursor on the currently-selected item.



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/cdk/components/selection.rb', line 141

def fixCursorPosition
  scrollbar_adj = if @scrollbar_placement == CDK::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)
  wrefresh(@input_window)
end

#focusObject

methods for generic type methods



537
538
539
# File 'lib/cdk/components/selection.rb', line 537

def focus
  self.drawList(@box)
end

#getChoice(index) ⇒ Object



485
486
487
488
489
490
491
492
493
494
# File 'lib/cdk/components/selection.rb', line 485

def getChoice(index)
  # Make sure the index isn't out of range.
  if index < 0
    return @selections[0]
  elsif index > list_size
    return @selections[@list_size - 1]
  else
    return @selections[index]
  end
end

#getChoicesObject



458
459
460
# File 'lib/cdk/components/selection.rb', line 458

def getChoices
  @selections
end

#getCurrentObject



532
533
534
# File 'lib/cdk/components/selection.rb', line 532

def getCurrent
  return @current_item
end

#getHighlightObject



440
441
442
# File 'lib/cdk/components/selection.rb', line 440

def getHighlight
  @highlight
end

#getItems(list) ⇒ Object



413
414
415
416
417
418
# File 'lib/cdk/components/selection.rb', line 413

def getItems(list)
  @item.each do |item|
    list << chtype2Char(item)
  end
  return @list_size
end

#getMode(index) ⇒ Object



521
522
523
524
525
526
527
528
529
530
# File 'lib/cdk/components/selection.rb', line 521

def getMode(index)
  # Make sure the index isn't out of range
  if index < 0
    return @mode[0]
  elsif index > list_size
    return @mode[@list_size - 1]
  else
    return @mode[index]
  end
end

#getModesObject



505
506
507
# File 'lib/cdk/components/selection.rb', line 505

def getModes
  return @mode
end

#getTitleObject



431
432
433
# File 'lib/cdk/components/selection.rb', line 431

def getTitle
  return chtype2Char(@title)
end

#inject(input) ⇒ Object

This injects a single characer into the widget.



185
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
263
264
265
266
267
268
269
# File 'lib/cdk/components/selection.rb', line 185

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

  # Set the exit type
  self.setExitType(0)

  # Draw the widget 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(:SELECTION, self,
        @pre_process_data, input)
  end

  # Should we continue?
  if pp_return != 0
    # Check for a predefined binding.
    if self.checkBind(:SELECTION, input)
      @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 '$'.ord
        @left_char = @max_left_char
      when '|'
        @left_char = 0
      when ' '.ord
        if @mode[@current_item] == 0
          if @selections[@current_item] == @choice_count - 1
            @selections[@current_item] = 0
          else
            @selections[@current_item] += 1
          end
        else
          CDK.Beep
        end
      when CDK::KEY_ESC
        self.setExitType(input)
        @complete = true
      when Ncurses::ERR
        self.setExitType(input)
        @complete = true
      when Ncurses::KEY_ENTER, CDK::KEY_TAB, CDK::KEY_RETURN
        self.setExitType(input)
        ret = 1
        @complete = true
      when CDK::REFRESH
        @screen.erase
        @screen.refresh
      end
    end
  
    # Should we call a post-process?
    if !@complete && !(@post_process_func.nil?)
      @post_process_func.call(:SELECTION, self, @post_process_data, input)
    end
  end
  
  unless @complete
    self.drawList(@box)
    self.setExitType(0)
  end
  
  @result_data = ret
  self.fixCursorPosition
  return ret
end

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

This moves the selection field to the given location.



272
273
274
275
276
# File 'lib/cdk/components/selection.rb', line 272

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

#object_typeObject



615
616
617
# File 'lib/cdk/components/selection.rb', line 615

def object_type
  :SELECTION
end

#positionObject



611
612
613
# File 'lib/cdk/components/selection.rb', line 611

def position
  super(@win)
end

#SCREENPOS(n, scrollbar_adj) ⇒ Object



607
608
609
# File 'lib/cdk/components/selection.rb', line 607

def SCREENPOS(n, scrollbar_adj)
  @item_pos[n] - @left_char + scrollbar_adj
end

#set(highlight, choices, box) ⇒ Object

This function sets a couple of the selection list attributes



388
389
390
391
392
# File 'lib/cdk/components/selection.rb', line 388

def set(highlight, choices, box)
  self.setChoices(choices)
  self.setHighlight(highlight)
  self.setBox(box)
end

#setBKattr(attrib) ⇒ Object

This sets the background attribute of the widget.



351
352
353
354
355
356
# File 'lib/cdk/components/selection.rb', line 351

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

#setChoice(index, choice) ⇒ Object

This sets a single item’s choice value.



463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# File 'lib/cdk/components/selection.rb', line 463

def setChoice(index, choice)
  correct_choice = choice
  correct_index = index

  # Verify that the choice value is in range.
  if choice < 0
    correct_choice = 0
  elsif choice > @choice_count
    correct_choice = @choice_count - 1
  end

  # make sure the index isn't out of range.
  if index < 0
    correct_index = 0
  elsif index > @list_size
    correct_index = @list_size - 1
  end

  # Set the choice value.
  @selections[correct_index] = correct_choice
end

#setChoices(choices) ⇒ Object

This sets the default choices for the selection list.



445
446
447
448
449
450
451
452
453
454
455
456
# File 'lib/cdk/components/selection.rb', line 445

def setChoices(choices)
  # Set the choice values in the selection list.
  (0...@list_size).each do |j|
    if choices[j] < 0
      @selections[j] = 0
    elsif choices[j] > @choice_count
      @selections[j] = @choice_count - 1
    else
      @selections[j] = choices[j]
    end
  end
end

#setHighlight(highlight) ⇒ Object

This sets the highlight bar.



436
437
438
# File 'lib/cdk/components/selection.rb', line 436

def setHighlight(highlight)
  @highlight = highlight
end

#setItems(list, list_size) ⇒ Object

This sets the selection list items.



395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# File 'lib/cdk/components/selection.rb', line 395

def setItems(list, list_size)
  widest_item = self.createList(list, list_size)
  if widest_item <= 0
    return
  end

  # Clean up the display
  (0...@view_size).each do |j|
    Draw.writeBlanks(@win, self.SCREEN_XPOS(0), self.SCREEN_YPOS(j),
        CDK::HORIZONTAL, 0, @win.getmaxx)
  end

  self.setViewSize(list_size)
  self.setCurrentItem(0)

  self.updateViewWidth(widest_item)
end

#setMode(index, mode) ⇒ Object

This sets a single mode of an item in the selection list.



510
511
512
513
514
515
516
517
518
519
# File 'lib/cdk/components/selection.rb', line 510

def setMode(index, mode)
  # Make sure the index isn't out of range.
  if index < 0
    @mode[0] = mode
  elsif index > @list_size
    @mode[@list_size - 1] = mode
  else
    @mode[index] = mode
  end
end

#setModes(modes) ⇒ Object

This sets the modes of the items in the selection list. Currently there are only two: editable=0 and read-only=1



498
499
500
501
502
503
# File 'lib/cdk/components/selection.rb', line 498

def setModes(modes)
  # set the modes
  (0...@list_size).each do |j|
    @mode[j] = modes[j]
  end
end

#setSelectionTitle(title) ⇒ Object



420
421
422
423
424
425
426
427
428
429
# File 'lib/cdk/components/selection.rb', line 420

def setSelectionTitle(title)
  # Make sure the title isn't nil
  if title.nil?
    return
  end

  self.setTitle(title, -(@box_width + 1))

  self.setViewSize(@list_size)
end

#unfocusObject



541
542
543
# File 'lib/cdk/components/selection.rb', line 541

def unfocus
  self.drawList(@box)
end

#updateViewWidth(widest) ⇒ Object



596
597
598
599
600
601
# File 'lib/cdk/components/selection.rb', line 596

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

#WidestItemObject



603
604
605
# File 'lib/cdk/components/selection.rb', line 603

def WidestItem
  @max_left_char + self.AvailableWidth
end