Class: CDK::SLIDER

Inherits:
CDKOBJS show all
Defined in:
lib/cdk/components/slider.rb

Direct Known Subclasses

FSLIDER, USLIDER

Instance Attribute Summary

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

Class Method Summary collapse

Instance Method Summary collapse

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, title, label, filler, field_width, start, low, high, inc, fast_inc, box, shadow) ⇒ SLIDER

Returns a new instance of SLIDER.



5
6
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/components/slider.rb', line 5

def initialize(cdkscreen, xplace, yplace, title, label, filler,
    field_width, start, low, high, inc, fast_inc, box, shadow)
  super()
  parent_width = cdkscreen.window.getmaxx
  parent_height = cdkscreen.window.getmaxy
  bindings = {
      'u'           => Ncurses::KEY_UP,
      'U'           => Ncurses::KEY_PPAGE,
      CDK::BACKCHAR => Ncurses::KEY_PPAGE,
      CDK::FORCHAR  => Ncurses::KEY_NPAGE,
      'g'           => Ncurses::KEY_HOME,
      '^'           => Ncurses::KEY_HOME,
      'G'           => Ncurses::KEY_END,
      '$'           => Ncurses::KEY_END,
  }
  self.setBox(box)
  box_height = @border_size * 2 + 1

  # Set some basic values of the widget's data field.
  @label = []
  @label_len = 0
  @label_win = nil
  high_value_len = self.formattedSize(high)

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

  # Translate the label string to a chtype array.
  if !(label.nil?) && label.size > 0
    label_len = []
    @label = char2Chtype(label, label_len, [])
    @label_len = label_len[0]
    box_width = @label_len + field_width +
        high_value_len + 2 * @border_size
  else
    box_width = field_width + high_value_len + 2 * @border_size
  end

  old_width = box_width
  box_width = self.setTitle(title, box_width)
  horizontal_adjust = (box_width - old_width) / 2

  box_height += @title_lines

  # 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
  field_width = [field_width,
      box_width - @label_len - high_value_len - 1].min

  # 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 widget's window.
  @win = Ncurses::WINDOW.new(box_height, box_width, ypos, xpos)

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

  # Create the widget's label window.
  if @label.size > 0
    @label_win = @win.subwin(1, @label_len,
        ypos + @title_lines + @border_size,
        xpos + horizontal_adjust + @border_size)
    if @label_win.nil?
      self.destroy
      return nil
    end
  end

  # Create the widget's data field window.
  @field_win = @win.subwin(1, field_width + high_value_len - 1,
      ypos + @title_lines + @border_size,
      xpos + @label_len + horizontal_adjust + @border_size)

  if @field_win.nil?
    self.destroy
    return nil
  end
  @field_win.keypad(true)
  @win.keypad(true)

  # Create the widget's data field.
  @screen = cdkscreen
  @window = cdkscreen.window
  @shadow_win = nil
  @box_width = box_width
  @box_height = box_height
  @field_width = field_width - 1
  @filler = filler
  @low = low
  @high = high
  @current = start
  @inc = inc
  @fastinc = fast_inc
  @accepts_focus = true
  @input_window = @win
  @shadow = shadow
  @field_edit = 0

  # Set the start value.
  if start < low
    @current = low
  end

  # Do we want a shadow?
  if shadow
    @shadow_win = Ncurses::WINDOW.new(box_height, box_width,
        ypos + 1, xpos + 1)
    if @shadow_win.nil?
      self.destroy
      return nil
    end
  end

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

  cdkscreen.register(:SLIDER, self)
end

Class Method Details

.Decrement(value, by) ⇒ Object



273
274
275
276
277
278
279
# File 'lib/cdk/components/slider.rb', line 273

def self.Decrement(value, by)
  if value - by < value
    value - by
  else
    value
  end
end

.Increment(value, by) ⇒ Object



281
282
283
284
285
286
287
# File 'lib/cdk/components/slider.rb', line 281

def self.Increment(value, by)
  if value + by > value
    value + by
  else
    value
  end
end

.removeChar(string, col) ⇒ Object

Remove the character from the string at the given column, if it is blank. Returns true if a change was made.



224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/cdk/components/slider.rb', line 224

def self.removeChar(string, col)
  result = false
  if col >= 0 && string[col] != ' '
    while col < string.size - 1
      string[col] = string[col + 1]
      col += 1
    end
    string.chop!
    result = true
  end
  return result
end

Instance Method Details

#activate(actions) ⇒ Object

This allows the person to use the widget’s data field.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/cdk/components/slider.rb', line 137

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

  if actions.nil? || actions.size == 0
    while true
      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 -1
end

#destroyObject

This function destroys the widget.



450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/cdk/components/slider.rb', line 450

def destroy
  self.cleanTitle
  @label = []

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

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

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

#draw(box) ⇒ Object

This function draws the widget.



392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/cdk/components/slider.rb', line 392

def draw(box)
  # Draw the shadow.
  unless @shadow_win.nil?
    Draw.drawShadow(@shadow_win)
  end

  # Box the widget if asked.
  if box
    Draw.drawObjBox(@win, self)
  end

  self.drawTitle(@win)

  # Draw the label.
  unless @label_win.nil?
    Draw.writeChtype(@label_win, 0, 0, @label, CDK::HORIZONTAL,
        0, @label_len)
    wrefresh(@label_win)
  end
  wrefresh

  # Draw the field window.
  self.drawField
end

#drawFieldObject

This draws the widget.



418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
# File 'lib/cdk/components/slider.rb', line 418

def drawField
  step = 1.0 * @field_width / (@high - @low)

  # Determine how many filler characters need to be drawn.
  filler_characters = (@current - @low) * step

  @field_win.werase

  # Add the character to the window.
  (0...filler_characters).each do |x|
    @field_win.mvwaddch(0, x, @filler)
  end

  # Draw the value in the field.
  Draw.writeCharAttrib(@field_win, @field_width, 0, @current.to_s,
      Ncurses::A_NORMAL, CDK::HORIZONTAL, 0, @current.to_s.size)

  self.moveToEditPosition(@field_edit)
  wrefresh(@field_win)
end

#eraseObject

This function erases the widget from the screen.



468
469
470
471
472
473
474
475
# File 'lib/cdk/components/slider.rb', line 468

def erase
  if self.validCDKObject
    CDK.eraseCursesWindow(@label_win)
    CDK.eraseCursesWindow(@field_win)
    CDK.eraseCursesWindow(@lwin)
    CDK.eraseCursesWindow(@shadow_win)
  end
end

#focusObject



521
522
523
# File 'lib/cdk/components/slider.rb', line 521

def focus
  self.draw(@box)
end

#formattedSize(value) ⇒ Object



477
478
479
# File 'lib/cdk/components/slider.rb', line 477

def formattedSize(value)
  return value.to_s.size
end

#getHighValueObject



517
518
519
# File 'lib/cdk/components/slider.rb', line 517

def getHighValue
  return @high
end

#getLowValueObject



513
514
515
# File 'lib/cdk/components/slider.rb', line 513

def getLowValue
  return @low
end

#getValueObject



494
495
496
# File 'lib/cdk/components/slider.rb', line 494

def getValue
  return @current
end

#inject(input) ⇒ Object

This function injects a single character into the widget.



290
291
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
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/cdk/components/slider.rb', line 290

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

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

  # Draw the field.
  self.drawField

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

  # Should we continue?
  if pp_return != 0
    # Check for a key binding.
    if self.checkBind(:SLIDER, input)
      @complete = true
    else
      case input
      when Ncurses::KEY_LEFT
        self.setEditPosition(@field_edit + 1)
      when Ncurses::KEY_RIGHT
        self.setEditPosition(@field_edit - 1)
      when Ncurses::KEY_DOWN
        @current = CDK::SLIDER.Decrement(@current, @inc)
      when Ncurses::KEY_UP
        @current = CDK::SLIDER.Increment(@current, @inc)
      when Ncurses::KEY_PPAGE
        @current = CDK::SLIDER.Increment(@current, @fastinc)
      when Ncurses::KEY_NPAGE
        @current = CDK::SLIDER.Decrement(@current, @fastinc)
      when Ncurses::KEY_HOME
        @current = @low
      when Ncurses::KEY_END
        @current = @high
      when CDK::KEY_TAB, CDK::KEY_RETURN, Ncurses::KEY_ENTER
        self.setExitType(input)
        ret = @current
        @complete = true
      when CDK::KEY_ESC
        self.setExitType(input)
        @complete = true
      when Ncurses::ERR
        self.setExitType(input)
        @complete = true
      when CDK::REFRESH
        @screen.erase
        @screen.refresh
      else
        if @field_edit != 0
          if !self.performEdit(input)
            CDK.Beep
          end
        else
          # The cursor is not within the editable text. Interpret
          # input as commands.
        case input
        when 'd'.ord, '-'.ord
          return self.inject(Ncurses::KEY_DOWN)
        when '+'.ord
          return self.inject(Ncurses::KEY_UP)
        when 'D'.ord
          return self.inject(Ncurses::KEY_NPAGE)
        when '0'.ord
          return self.inject(Ncurses::KEY_HOME)
        else
          CDK.Beep
        end
        end
      end
    end
    self.limitCurrentValue

    # Should we call a post-process?
    if !@complete && !(@post_process_func.nil?)
      @post_process_func.call(:SLIDER, self, @post_process_data, input)
    end
  end

  if !@complete
    self.drawField
    self.setExitType(0)
  end

  @return_data = 0
  return ret
end

#limitCurrentValueObject

Check if the value lies outside the low/high range. If so, force it in.



167
168
169
170
171
172
173
174
175
# File 'lib/cdk/components/slider.rb', line 167

def limitCurrentValue
  if @current < @low
    @current = @low
    CDK.Beep
  elsif @current > @high
    @current = @high
    CDK.Beep
  end
end

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

This moves the widget’s data field to the given location.



385
386
387
388
389
# File 'lib/cdk/components/slider.rb', line 385

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

#moveToEditPosition(new_position) ⇒ Object

Move the cursor to the given edit-position.



178
179
180
181
# File 'lib/cdk/components/slider.rb', line 178

def moveToEditPosition(new_position)
  return @field_win.wmove(0,
      @field_width + self.formattedSize(@current) - new_position)
end

#object_typeObject



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

def object_type
  :SLIDER
end

#performEdit(input) ⇒ Object

Perform an editing function for the field.



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
270
271
# File 'lib/cdk/components/slider.rb', line 238

def performEdit(input)
  result = false
  modify = true
  base = @field_width
  need = self.formattedSize(@current)
  temp = ''
  col = need - @field_edit

  adj = if col < 0 then -col else 0 end
  if adj != 0
    temp  = ' ' * adj
  end
  @field_win.wmove(0, base)
  @field_win.winnstr(temp, need)
  temp << ' '
  if CDK.isChar(input)  # Replace the char at the cursor
    temp[col] = input.chr
  elsif input == Ncurses::KEY_BACKSPACE
    # delete the char before the cursor
    modify = CDK::SLIDER.removeChar(temp, col - 1)
  elsif input == Ncurses::KEY_DC
    # delete the char at the cursor
    modify = CDK::SLIDER.removeChar(temp, col)
  else
    modify = false
  end
  if modify &&
      ((value, test) = temp.scanf(self.SCAN_FMT)).size == 2 &&
      test == ' ' && value >= @low && value <= @high
    self.setValue(value)
    result = true
  end
  return result
end

#positionObject



533
534
535
# File 'lib/cdk/components/slider.rb', line 533

def position
  super(@win)
end

#SCAN_FMTObject



529
530
531
# File 'lib/cdk/components/slider.rb', line 529

def SCAN_FMT
  '%d%c'
end

#set(low, high, value, box) ⇒ Object

This function sets the low/high/current values of the widget.



482
483
484
485
486
# File 'lib/cdk/components/slider.rb', line 482

def set(low, high, value, box)
  self.setLowHigh(low, high)
  self.setValue(value)
  self.setBox(box)
end

#setBKattr(attrib) ⇒ Object

This sets the background attribute of the widget.



440
441
442
443
444
445
446
447
# File 'lib/cdk/components/slider.rb', line 440

def setBKattr(attrib)
  # Set the widget's background attribute.
  @win.wbkgd(attrib)
  @field_win.wbkgd(attrib)
  unless @label_win.nil?
    @label_win.wbkgd(attrib)
  end
end

#setEditPosition(new_position) ⇒ Object

Set the edit position. Normally the cursor is one cell to the right of the editable field. Moving it left, over the field, allows the user to modify cells by typing in replacement characters for the field’s value.



210
211
212
213
214
215
216
217
218
219
220
# File 'lib/cdk/components/slider.rb', line 210

def setEditPosition(new_position)
  if new_position < 0
    CDK.Beep
  elsif new_position == 0
    @field_edit = new_position
  elsif self.validEditPosition(new_position)
    @field_edit = new_position
  else
    CDK.Beep
  end
end

#setLowHigh(low, high) ⇒ Object

This function sets the low/high values of the widget.



499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'lib/cdk/components/slider.rb', line 499

def setLowHigh(low, high)
  # Make sure the values aren't out of bounds.
  if low <= high
    @low = low
    @high = high
  elsif low > high
    @low = high
    @high = low
  end

  # Make sure the user hasn't done something silly.
  self.limitCurrentValue
end

#setValue(value) ⇒ Object

This sets the widget’s value.



489
490
491
492
# File 'lib/cdk/components/slider.rb', line 489

def setValue(value)
  @current = value
  self.limitCurrentValue
end

#unfocusObject



525
526
527
# File 'lib/cdk/components/slider.rb', line 525

def unfocus
  self.draw(@box)
end

#validEditPosition(new_position) ⇒ Object

Check if the cursor is on a valid edit-position. This must be one of the non-blank cells in the field.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/cdk/components/slider.rb', line 185

def validEditPosition(new_position)
  if new_position <= 0 || new_position >= @field_width
    return false
  end
  if self.moveToEditPosition(new_position) == Ncurses::ERR
    return false
  end
  ch = @field_win.winch
  if charOf(ch) != ' '
    return true
  end
  if new_position > 1
    # Don't use recursion - only one level is wanted
    if self.moveToEditPosition(new_position - 1) == Ncurses::ERR
      return false
    end
    ch = @field_win.winch
    return charOf(ch) != ' '
  end
  return false
end