Class: CDK::SCALE

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

Direct Known Subclasses

FSCALE, USCALE

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, field_attr, field_width, start, low, high, inc, fast_inc, box, shadow) ⇒ SCALE

Returns a new instance of SCALE.



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

def initialize(cdkscreen, xplace, yplace, title, label, field_attr,
    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
  box_width = field_width + 2 * @border_size

  # Set some basic values of the widget's data field.
  @label = []
  @label_len = 0
  @label_win = nil

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

  # Translate the label string to a chtype array
  unless label.nil?
    label_len = []
    @label = char2Chtype(label, label_len, [])
    @label_len = label_len[0]
    box_width = @label_len + field_width + 2
  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 - 2 * @border_size].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,
      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
  @parent = cdkscreen.window
  @shadow_win = nil
  @box_width = box_width
  @box_height = box_height
  @field_width = field_width
  @field_attr = field_attr
  @current = low
  @low = low
  @high = high
  @current = start
  @inc = inc
  @fastinc = fast_inc
  @accepts_focus = true
  @input_window = @win
  @shadow = shadow
  @field_edit = 0

  # 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(self.object_type, from, :getc, to)
  end

  cdkscreen.register(self.object_type, self)
end

Class Method Details

.Decrement(value, by) ⇒ Object



269
270
271
272
273
274
275
# File 'lib/cdk/components/scale.rb', line 269

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

.Increment(value, by) ⇒ Object



277
278
279
280
281
282
283
# File 'lib/cdk/components/scale.rb', line 277

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.



222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/cdk/components/scale.rb', line 222

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.



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

def activate(actions)
  ret = -1
  # Draw the widget.
  self.draw(@box)

  if actions.nil? || actions.size == 0
    input = 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)
    end
    if @exit_type != :EARLY_EXIT
      return ret
    end
  end

  # Set the exit type and return.
  self.setExitType(0)
  return ret
end

#destroyObject

This function destroys the widget.



438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/cdk/components/scale.rb', line 438

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(self.object_type)

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

#draw(box) ⇒ Object

This function draws the widget.



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

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.



415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/cdk/components/scale.rb', line 415

def drawField
  @field_win.werase

  # Draw the value in the field.
  temp = @current.to_s
  Draw.writeCharAttrib(@field_win,
      @field_width - temp.size - 1, 0, temp, @field_attr,
      CDK::HORIZONTAL, 0, temp.size)

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

#eraseObject

This function erases the widget from the screen.



456
457
458
459
460
461
462
463
# File 'lib/cdk/components/scale.rb', line 456

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

#focusObject



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

def focus
  self.draw(@box)
end

#getHighValueObject



501
502
503
# File 'lib/cdk/components/scale.rb', line 501

def getHighValue
  return @high
end

#getLowValueObject



497
498
499
# File 'lib/cdk/components/scale.rb', line 497

def getLowValue
  return @low
end

#getValueObject



478
479
480
# File 'lib/cdk/components/scale.rb', line 478

def getValue
  return @current
end

#inject(input) ⇒ Object

This function injects a single character into the widget.



286
287
288
289
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
# File 'lib/cdk/components/scale.rb', line 286

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(self.object_type, self,
        @pre_process_data, input)
  end

  # Should we continue?
  if pp_return != 0
    # Check for a key bindings.
    if self.checkBind(self.object_type, 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::SCALE.Decrement(@current, @inc)
      when Ncurses::KEY_UP
        @current = CDK::SCALE.Increment(@current, @inc)
      when Ncurses::KEY_PPAGE
        @current = CDK::SCALE.Increment(@current, @fastinc)
      when Ncurses::KEY_NPAGE
        @current = CDK::SCALE.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(self.object_type, self,
          @post_process_data, input)
    end
  end

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

  @result_data = ret
  return ret
end

#limitCurrentValueObject

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



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

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.



382
383
384
385
386
# File 'lib/cdk/components/scale.rb', line 382

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



177
178
179
# File 'lib/cdk/components/scale.rb', line 177

def moveToEditPosition(new_position)
  return @field_win.wmove(0, @field_width - new_position - 1)
end

#object_typeObject



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

def object_type
  :SCALE
end

#performEdit(input) ⇒ Object

Perform an editing function for the field.



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

def performEdit(input)
  result = false
  modify = true
  base = 0
  need = @field_width
  temp = ''
  col = need - @field_edit - 1

  @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::SCALE.removeChar(temp, col - 1)
  elsif input == Ncurses::KEY_DC
    # delete the char at the cursor
    modify = CDK::SCALE.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



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

def position
  super(@win)
end

#SCAN_FMTObject



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

def SCAN_FMT
  '%d%c'
end

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

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



466
467
468
469
470
# File 'lib/cdk/components/scale.rb', line 466

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 teh widget.



429
430
431
432
433
434
435
# File 'lib/cdk/components/scale.rb', line 429

def setBKattr(attrib)
  @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.



208
209
210
211
212
213
214
215
216
217
218
# File 'lib/cdk/components/scale.rb', line 208

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.



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

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



473
474
475
476
# File 'lib/cdk/components/scale.rb', line 473

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

#unfocusObject



509
510
511
# File 'lib/cdk/components/scale.rb', line 509

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.



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

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 ch.chr != ' '
    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 ch.chr != ' '
  end
  return false
end