Class: VER::WidgetMajorMode
- Includes:
- Keymap::Results
- Defined in:
- lib/ver/widget_major_mode.rb
Overview
The WidgetMajorMode associates a widget with a major mode. It keeps a limited history of the events that arrive at [on_event]. It also maintains a stack of the event patterns and tries to match against the keymaps of the major and minor modes.
This class has its own list of minor modes, which can be modified and may differ from the minor modes of the original major mode.
It is responsible to keep the keymaps of major and minor modes functioning by ensuring that they are actually bound to the tag of the major mode.
Constant Summary
Constants inherited from Struct
Instance Attribute Summary collapse
-
#action_history ⇒ Object
Returns the value of attribute action_history.
-
#event_history ⇒ Object
Returns the value of attribute event_history.
-
#major ⇒ Object
Returns the value of attribute major.
-
#minors ⇒ Object
Returns the value of attribute minors.
-
#read_amount ⇒ Object
Returns the value of attribute read_amount.
-
#reader ⇒ Object
Returns the value of attribute reader.
-
#stack ⇒ Object
Returns the value of attribute stack.
-
#widget ⇒ Object
Returns the value of attribute widget.
Instance Method Summary collapse
- #actions ⇒ Object
-
#bind(pattern, &block) ⇒ Object
Shortcut to bind a pattern on the associated widget.
- #bind_key(key) ⇒ Object
- #bound_keys ⇒ Object
- #establish_tag ⇒ Object
- #fake(input) ⇒ Object
- #forget(*minors) ⇒ Object
-
#handle_reader(event) ⇒ Object
ignore event for now, it might be needed later.
-
#initialize(widget, major) ⇒ WidgetMajorMode
constructor
A new instance of WidgetMajorMode.
- #inspect ⇒ Object
- #listen ⇒ Object
- #message(*args) ⇒ Object
- #name ⇒ Object
- #on_event(event) ⇒ Object
- #read(amount, &reader) ⇒ Object
- #replace_minor(old, new) ⇒ Object
- #replaced_by(other) ⇒ Object
- #replaces(other) ⇒ Object
- #replacing(other) ⇒ Object
- #resolve(pattern) ⇒ Object
- #synchronize ⇒ Object
- #tag ⇒ Object
- #to_camel_case ⇒ Object
- #to_hash ⇒ Object
- #to_tcl ⇒ Object
- #use(*minors) ⇒ Object
- #warn(*args) ⇒ Object
Methods inherited from Struct
Constructor Details
#initialize(widget, major) ⇒ WidgetMajorMode
Returns a new instance of WidgetMajorMode.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/ver/widget_major_mode.rb', line 17 def initialize(, major) self. = self.major = MajorMode[major] self.event_history = SizedArray.new(500) # this may be too small still self.action_history = SizedArray.new(100) self.stack = [] self.minors = [] establish_tag use(*self.major.minors) listen # in case we had some keymap updates, they must have been registered by # now, since otherwise we wouldn't be here. # This will be called around 3 times per startup. Event.done_yet? end |
Instance Attribute Details
#action_history ⇒ Object
Returns the value of attribute action_history
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def action_history @action_history end |
#event_history ⇒ Object
Returns the value of attribute event_history
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def event_history @event_history end |
#major ⇒ Object
Returns the value of attribute major
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def major @major end |
#minors ⇒ Object
Returns the value of attribute minors
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def minors @minors end |
#read_amount ⇒ Object
Returns the value of attribute read_amount
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def read_amount @read_amount end |
#reader ⇒ Object
Returns the value of attribute reader
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def reader @reader end |
#stack ⇒ Object
Returns the value of attribute stack
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def stack @stack end |
#widget ⇒ Object
Returns the value of attribute widget
12 13 14 |
# File 'lib/ver/widget_major_mode.rb', line 12 def @widget end |
Instance Method Details
#actions ⇒ Object
197 198 199 |
# File 'lib/ver/widget_major_mode.rb', line 197 def actions major.actions + minors.map{|minor| minor.actions }.flatten end |
#bind(pattern, &block) ⇒ Object
Shortcut to bind a pattern on the associated widget.
44 45 46 |
# File 'lib/ver/widget_major_mode.rb', line 44 def bind(pattern, &block) .bind(pattern, &block) end |
#bind_key(key) ⇒ Object
48 49 50 |
# File 'lib/ver/widget_major_mode.rb', line 48 def bind_key(key) major.bind_key(key) end |
#bound_keys ⇒ Object
39 40 41 |
# File 'lib/ver/widget_major_mode.rb', line 39 def bound_keys major.bound_keys end |
#establish_tag ⇒ Object
231 232 233 234 235 236 |
# File 'lib/ver/widget_major_mode.rb', line 231 def establish_tag = . specific = [0, 1] general = [-3..-1] .(*specific, major.tag, *general) end |
#fake(input) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/ver/widget_major_mode.rb', line 66 def fake(input) input.scan(/<[\w-]+>|[^<>]/) do |name| # get the widget that currently has focus, this might not be self. path = Tk::Focus.focus = Tk.(path) if == self. on_event(Event[name]) Tk.update else .type(name) end end end |
#forget(*minors) ⇒ Object
62 63 64 |
# File 'lib/ver/widget_major_mode.rb', line 62 def forget(*minors) self.minors -= minors.map{|name| MinorMode[name] } end |
#handle_reader(event) ⇒ Object
ignore event for now, it might be needed later
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/ver/widget_major_mode.rb', line 126 def handle_reader(event) read_amount = self.read_amount if stack.size >= read_amount stack.clear # before we call, we reset the state in case the reader adds a new reader. reader = self.reader self.reader = self.read_amount = nil reader.call(*event_history.last(read_amount)) true else false end end |
#inspect ⇒ Object
221 222 223 224 225 226 227 228 229 |
# File 'lib/ver/widget_major_mode.rb', line 221 def inspect out = ['#<Ver::WidgetMajorMode'] { major: major.name, minors: minors.map{|m| m.to_sym }, event_history: event_history.map(&:keysym), stack: stack, }.each{|k,v| out << "#{k}=#{v.inspect}" } out.join(' ') << '>' end |
#listen ⇒ Object
35 36 37 |
# File 'lib/ver/widget_major_mode.rb', line 35 def listen VER.root.bind('<<PluginLoaded>>'){|event| synchronize } end |
#message(*args) ⇒ Object
109 110 111 112 113 114 115 |
# File 'lib/ver/widget_major_mode.rb', line 109 def (*args) if .respond_to?(:message) .(*args) else VER.(*args) end end |
#name ⇒ Object
205 206 207 |
# File 'lib/ver/widget_major_mode.rb', line 205 def name major.name end |
#on_event(event) ⇒ Object
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 |
# File 'lib/ver/widget_major_mode.rb', line 81 def on_event(event) VER.touch stack << event.pattern # replace with our subset event = Event.new(event.pattern, event.keysym, event.unicode) event_history << event return handle_reader(event) if reader && read_amount result = resolve(stack) case result when Incomplete result.to_s() # don't do anything yet... when Impossible warn result.to_s stack.clear else stack.clear '' mode, action = *result = WidgetEvent.new(, event) action.call() action_history << [, *result] end end |
#read(amount, &reader) ⇒ Object
142 143 144 145 146 147 |
# File 'lib/ver/widget_major_mode.rb', line 142 def read(amount, &reader) amount = amount.to_int raise ArgumentError, "amount must be greater than 0" unless amount > 0 self.read_amount = amount self.reader = reader end |
#replace_minor(old, new) ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/ver/widget_major_mode.rb', line 171 def replace_minor(old, new) old, new = MinorMode[old], MinorMode[new] minors.dup.each do |minor| if minor == old new.replaces self, old do minors[minors.index(old)] = new end else minor.replace_parent(self, old, new) end end synchronize end |
#replaced_by(other) ⇒ Object
159 160 161 162 163 |
# File 'lib/ver/widget_major_mode.rb', line 159 def replaced_by(other) Tk::Event.generate(, "<<LeaveMode>>", data: name) Tk::Event.generate(, "<<LeaveMajorMode>>", data: name) Tk::Event.generate(, "<<LeaveMajorMode#{to_camel_case}>>", data: name) end |
#replaces(other) ⇒ Object
153 154 155 156 157 |
# File 'lib/ver/widget_major_mode.rb', line 153 def replaces(other) other.replaced_by(self) if other yield if block_given? self.replacing(other) end |
#replacing(other) ⇒ Object
165 166 167 168 169 |
# File 'lib/ver/widget_major_mode.rb', line 165 def replacing(other) Tk::Event.generate(, "<<EnterMajorMode#{to_camel_case}>>", data: name) Tk::Event.generate(, "<<EnterMajorMode>>", data: name) Tk::Event.generate(, "<<EnterMode>>", data: name) end |
#resolve(pattern) ⇒ Object
149 150 151 |
# File 'lib/ver/widget_major_mode.rb', line 149 def resolve(pattern) major.resolve(pattern, minors) end |
#synchronize ⇒ Object
187 188 189 190 191 192 193 194 195 |
# File 'lib/ver/widget_major_mode.rb', line 187 def synchronize major.keymap.keys.each do |key| major.bind_key(key) end minors.each do |minor| minor.synchronize_recursively(self) end end |
#tag ⇒ Object
209 210 211 |
# File 'lib/ver/widget_major_mode.rb', line 209 def tag major.tag end |
#to_camel_case ⇒ Object
217 218 219 |
# File 'lib/ver/widget_major_mode.rb', line 217 def to_camel_case major.name.to_s.split('_').map{|e| e.capitalize}.join end |
#to_hash ⇒ Object
201 202 203 |
# File 'lib/ver/widget_major_mode.rb', line 201 def to_hash [major.keymap, *minors].inject{|h, m| h.merge(m.keymap) } end |
#to_tcl ⇒ Object
213 214 215 |
# File 'lib/ver/widget_major_mode.rb', line 213 def to_tcl .tk_pathname end |
#use(*minors) ⇒ Object
52 53 54 55 56 57 58 59 60 |
# File 'lib/ver/widget_major_mode.rb', line 52 def use(*minors) minors.each do |name| minor = MinorMode[name] next if self.minors.any?{|m| m.name == minor.name } self.minors << minor end synchronize end |