Class: Rbindkeys::BindTree

Inherits:
Object
  • Object
show all
Defined in:
lib/rbindkeys.rb,
lib/rbindkeys/bind_tree.rb

Defined Under Namespace

Classes: Leaf, UnexpecedLeafError

Constant Summary collapse

DEFAULT_DEFAULT_VALUE =
:through
AVAIVABLE_DEFAULT_VALUE =
[:through, :ignore]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(default_value = DEFAULT_DEFAULT_VALUE) ⇒ BindTree

Returns a new instance of BindTree.



23
24
25
26
27
28
29
30
31
# File 'lib/rbindkeys/bind_tree.rb', line 23

def initialize default_value=DEFAULT_DEFAULT_VALUE
  @tree = {}
  @active_key_binds = []
  if AVAIVABLE_DEFAULT_VALUE.include? default_value
    @default_value = default_value
  else
    raise ArgumentError, "expect #{AVAIVABLE_DEFAULT_VALUE.join('/')}"
  end
end

Instance Attribute Details

#active_key_bindsObject (readonly)

active KeyBind TODO create KeyEventHandler which exist between Observer and BindTree TODO move out @active_key_binds to KeyEventHandler



18
19
20
# File 'lib/rbindkeys/bind_tree.rb', line 18

def active_key_binds
  @active_key_binds
end

#default_valueObject (readonly)

a value if no binds hit



21
22
23
# File 'lib/rbindkeys/bind_tree.rb', line 21

def default_value
  @default_value
end

#main_treeObject (readonly)

Returns the value of attribute main_tree.



13
14
15
# File 'lib/rbindkeys/bind_tree.rb', line 13

def main_tree
  @main_tree
end

#treeObject (readonly)

a tree structure which that nodes are Fixnum(keycode) and leaves are Leaf



11
12
13
# File 'lib/rbindkeys/bind_tree.rb', line 11

def tree
  @tree
end

Instance Method Details

#bind(input, output = nil) ⇒ Object

register an input-output pair input: Array of (Array of) input keycodes output: Array of send keycodes or Proc



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
# File 'lib/rbindkeys/bind_tree.rb', line 36

def bind input, output=nil
  input = input.clone
  new_input = []

  if input.kind_of? Array and input[0].kind_of? Array
    new_input = input
    input = new_input.shift
  end

  tail_code = input.pop
  input.sort!

  subtree = @tree
  input.each do |code|
    if subtree.has_key? code and (not subtree[code].kind_of? Hash)
      raise DuplicateNodeError, "already register an input:#{input}"
    end
    subtree[code] ||= {}
    subtree = subtree[code]
  end

  if not new_input.empty?
    if subtree.has_key?(tail_code) and
        not (subtree[tail_code].kind_of?(Leaf) and
             subtree[tail_code].payload.kind_of?(BindTree))
      raise DuplicateNodeError, "already register an input:#{input}"
    end

    if new_input.length == 1
      new_input = new_input.first
    end

    subtree[tail_code] ||= Leaf.new BindTree.new :ignore
    subtree[tail_code].payload.bind new_input, output

  elsif subtree.has_key? tail_code
    raise DuplicateNodeError, "already register an input:#{input}"

  else
    subtree[tail_code] = Leaf.new KeyBind.new input.push(tail_code), output
  end
end

#resolve_for_pressed_event(event, pressed_keys) ⇒ Object

called when event.value == 1



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
# File 'lib/rbindkeys/bind_tree.rb', line 99

def resolve_for_pressed_event event, pressed_keys
  subtree = @tree
  last_code = -1
  pressed_keys.each do |code|
    if last_code >= code
      raise ArgumentError, "expect a sorted Array for 2nd arg (pressed_keys)"
    end
    last_code = code

    if subtree.has_key? code
      subtree = subtree[code]
    end
  end

  subtree = (subtree.kind_of?(Hash) and subtree[event.code])

  if not subtree or subtree.kind_of? Hash
    return @default_value
  elsif subtree.kind_of? Leaf
    if subtree.payload.kind_of? KeyBind
      @active_key_binds << subtree.payload
      return subtree.payload
    elsif subtree.payload.kind_of? BindTree
      return subtree.payload
    end
  else
    raise UnexpecedLeafError, "unexpeced Leaf: #{subtree.inspect}"
  end
end

#resolve_for_pressing_event(event, pressed_keys) ⇒ Object

called when event.value == 2



130
131
132
133
134
135
136
# File 'lib/rbindkeys/bind_tree.rb', line 130

def resolve_for_pressing_event event, pressed_keys
  if @active_key_binds.empty?
    @default_value
  else
    @active_key_binds
  end
end

#resolve_for_released_event(event, pressed_keys) ⇒ Object

called when event.value == 0



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rbindkeys/bind_tree.rb', line 80

def resolve_for_released_event event, pressed_keys
  release_binds = []
  @active_key_binds.reject! do |key_bind|
    if key_bind.input.include? event.code
      release_binds << key_bind
      true
    else
      false
    end
  end

  if release_binds.empty?
    :through
  else
    release_binds
  end
end