Class: Keyboard

Inherits:
Object show all
Defined in:
lib/keyboard/keyboard.rb

Overview

The Keyboard class defines methods for navigating/typing keys on layouts that are provided by inheriting classes. Keyboard layouts are defined as a matrix of keys. The key types are: special keys - defined as Symbols, i.e. :SHIFT_LOCK, :SHIFT, :BACKSPACE normal keys - defined as Strings, i.e. ‘a’, ‘1’, ‘@’ Splat arrays can be used to simplify rows containing mixed key types. Just don’t make it confusing to read the layout!

Constant Summary collapse

DEBUG =

TODO: Use for debugging only! If pushed to master as false, key navigation will take forever.

false

Instance Method Summary collapse

Constructor Details

#initialize(dut) ⇒ Keyboard

Returns a new instance of Keyboard.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/keyboard/keyboard.rb', line 12

def initialize(dut)
  @dut = dut
  @test_case = dut.send(:test_case)
  @layouts = []
  @start_layout_index = 0
  @verify_roi = nil
  @key_delay = 3.sec
  @shifted = false
  @shift_persists = false
  @wrap_rows = false
  @wrap_cols = false
  @deny_traversals = []
  reset
end

Instance Method Details

#displayed?Boolean

Public: Checks if the current keyboard is displayed.

Returns a Boolean true if the

Returns:

  • (Boolean)


108
109
110
111
112
# File 'lib/keyboard/keyboard.rb', line 108

def displayed?
  return false if displayed_rois.empty?
  displayed_rois.each {|roi| return true if roi.displayed?}
  false
end

#resetObject

Public: Resets all keyboard attributes.

Returns nothing.



117
118
119
120
121
# File 'lib/keyboard/keyboard.rb', line 117

def reset
  @shifted = false
  @cur_coords = nil        # set automatically on first access
  @cur_layout_index = nil  # set automatically on first access
end

#type?(text, args = {}) ⇒ Boolean

Public: This function is used to write the given text on the virtual keyboard.

text - String or Array of String keys to type. start_key - String non-default start key (default: nil). verify_roi - Roi object to verify the typed text (default: nil). delay_between_keys - Delay used between key presses in miliseconds min value of 3000 (default: 3000). nav_only - Boolean whether to navigate without selecting (default: false).

Used to navigate to a single key without selecting it.

Returns Boolean true if successfully able to write the given text. Else, returns false.

Returns:

  • (Boolean)


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
# File 'lib/keyboard/keyboard.rb', line 37

def type?(text, args={})
  @key_delay = args[:delay_between_keys].to_i if args[:delay_between_keys].to_i > 3000
  nav_only = args.fetch(:nav_only, false)
  logger.info("#{nav_only ? 'Navigating to' : 'Typing'} #{text.inspect} on the #{cur_layout.name} keyboard.")
  start_key = args[:start_key]
  # only verify if verify==true (from `type_keys?')
  verify_roi = args[:verify] ? args[:verify_roi] || @verify_roi : nil
  unless start_key.nil?
    @cur_coords = get_key_coords(start_key).first
  end
  unless text.is_a?(Array)
    text = [text]
  end
  first_char = true
  text.each do |val|
    if val.is_a?(String) && val.length > 1
      # type the string
      val.split('').each do |key|
        return false unless type?(key, nav_only: nav_only)
      end
    else
      val = :SPACE if val == ' '
      layout_index, shift, key = get_layout_for_key(val)
      # this is a defined key
      if layout_index != cur_layout_index
        # change to the specified layout
        return false unless type_key?(@layouts[layout_index].nav_to_key)
        last_row_count = cur_key_matrix.count
        last_row_width = cur_key_matrix[cur_coords[0]].count
        @cur_layout_index = layout_index
        last_nav_to_key = cur_layout.nav_to_key
        # check if we need to reset the coords due to difference in dimensions between last and new keyboard
        if cur_key_matrix.count != last_row_count || cur_key_matrix[cur_coords[0]].count != last_row_width
          @cur_coords = get_key_coords(last_nav_to_key).first
        end
        # check if we need to downshift to restore the default case of the new layout
        shift ||= (@shift_persists && @shifted)
      end
      # todo: implement shift lock for efficiency
      # if this layout auto-cases, this is the first character, and the key is uppercase, then shift is not req'd
      no_shift_reqd = cur_layout.auto_case && first_char && (key == key.upcase)
      if shift && !no_shift_reqd
        # press the shift key
        return false unless type_key?(cur_layout.shift_key)
      end
      if nav_only
        return false unless nav_to_key?(key)
      else
        return false unless type_key?(key)
      end
      first_char = false if first_char
      first_char = true if cur_layout.auto_case && key == :SPACE
    end
  end
  # all text typed successfully
  if verify_roi.nil?
    true
  else
    typed = verify_roi.retrieve.sub(/_$/, '')
    if typed == text
      true
    else
      logger.info(%Q(Tried to type "#{text}" but typed "#{typed}" instead!))
      false
    end
  end
end