aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts/mode.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'content_scripts/mode.coffee')
-rw-r--r--content_scripts/mode.coffee78
1 files changed, 70 insertions, 8 deletions
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee
index f7bf9e69..e4b6017c 100644
--- a/content_scripts/mode.coffee
+++ b/content_scripts/mode.coffee
@@ -1,12 +1,74 @@
-root = exports ? window
-class root.Mode
- constructor: (onKeydown, onKeypress, onKeyup, @popModeCallback) ->
+class Mode
+ # Static members.
+ @modes: []
+ @current: -> Mode.modes[0]
+ @suppressPropagation = false
+ @propagate = true
+
+ # Default values.
+ name: "" # The name of this mode.
+ badge: "" # A badge to display on the popup when this mode is active.
+ keydown: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions.
+ keypress: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions.
+ keyup: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions.
+ onDeactivate: -> # Called when leaving this mode.
+ onReactivate: -> # Called when this mode is reactivated.
+
+ constructor: (options) ->
+ extend @, options
+
@handlerId = handlerStack.push
- keydown: onKeydown
- keypress: onKeypress
- keyup: onKeyup
+ keydown: @checkForBuiltInHandler "keydown", @keydown
+ keypress: @checkForBuiltInHandler "keypress", @keypress
+ keyup: @checkForBuiltInHandler "keyup", @keyup
+ reactivateMode: =>
+ @onReactivate()
+ Mode.setBadge()
+ return Mode.suppressPropagation
+
+ Mode.modes.unshift @
+ Mode.setBadge()
+
+ # Allow the strings "suppress" and "pass" to be used as proxies for the built-in handlers.
+ checkForBuiltInHandler: (type, handler) ->
+ switch handler
+ when "suppress" then @generateSuppressPropagation type
+ when "pass" then @generatePassThrough type
+ else handler
- popMode: ->
+ # Generate a default handler which always passes through; except Esc, which pops the current mode.
+ generatePassThrough: (type) ->
+ me = @
+ (event) ->
+ if type == "keydown" and KeyboardUtils.isEscape event
+ me.popMode event
+ return Mode.suppressPropagation
+ handlerStack.passThrough
+
+ # Generate a default handler which always suppresses propagation; except Esc, which pops the current mode.
+ generateSuppressPropagation: (type) ->
+ handler = @generatePassThrough type
+ (event) -> handler(event) and Mode.suppressPropagation # Always falsy.
+
+ # Leave the current mode; event may or may not be provide. It is the responsibility of the creator of this
+ # object to know whether or not an event will be provided. Bubble a "reactivateMode" event to notify the
+ # now-active mode that it is once again top dog.
+ popMode: (event) ->
+ Mode.modes = Mode.modes.filter (mode) => mode != @
handlerStack.remove @handlerId
- @popModeCallback()
+ @onDeactivate event
+ handlerStack.bubbleEvent "reactivateMode", event
+
+ # Set the badge on the browser popup to indicate the current mode; static method.
+ @setBadge: ->
+ badge = Mode.getBadge()
+ chrome.runtime.sendMessage({ handler: "setBadge", badge: badge })
+
+ # Static convenience methods.
+ @is: (mode) -> Mode.current()?.name == mode
+ @getBadge: -> Mode.current()?.badge || ""
+ @isInsert: -> Mode.is "insert"
+
+root = exports ? window
+root.Mode = Mode