package org.netxilia.server.js; import static org.stjs.javascript.Global.$castArray; import static org.stjs.javascript.Global.$map; import static org.stjs.javascript.JSStringAdapter.charCodeAt; import org.stjs.javascript.Array; import org.stjs.javascript.Map; import org.stjs.javascript.functions.Callback0; import org.stjs.javascript.functions.Function1; import org.stjs.javascript.jquery.Event; public class Shortcuts { private static final int CTRL = 1; private static final int SHIFT = 2; private static final int ALT = 4; private static final int META = 8; private static final Map<String, Integer> meta = $map("ctrl", CTRL, "shift", SHIFT, "alt", ALT, "meta", META); // Special Keys - and their codes private static final Map<String, Integer> special_keys = $map("esc", 27, "escape", 27, "tab", 9, "space", 32, "return", 13, "enter", 13, "backspace", 8, "scrolllock", 145, "scroll_lock", 145, "scroll", 145, "capslock", 20, "caps_lock", 20, "caps", 20, "numlock", 144, "num_lock", 144, "num", 144, "pause", 19, "break", 19, "insert", 45, "home", 36, "delete", 46, "end", 35, "pageup", 33, "page_up", 33, "pu", 33, "pagedown", 34, "page_down", 34, "pd", 34, "left", 37, "up", 38, "right", 39, "down", 40, "f1", 112, "f2", 113, "f3", 114, "f4", 115, "f5", 116, "f6", 117, "f7", 118, "f8", 119, "f9", 120, "f10", 121, "f11", 122, "f12", 123); private Map<Integer, Handler> handlers; private Handler defaultHandler; public Shortcuts() { this.handlers = $map(); this.defaultHandler = null; } public void addPropagate(String combination, final Callback0 handler) { addInternal(combination, handler, true); } public void addSimple(String combination, final Callback0 handler) { addInternal(combination, handler, false); } private void addInternal(String combination, final Callback0 handler, boolean propagate) { add(combination, new Function1<Event, Boolean>() { @Override public Boolean $invoke(Event p1) { handler.$invoke(); return false; } }, propagate); } public void add(String combination, Function1<Event, Boolean> handler, boolean propagate) { Array<String> keys = $castArray(combination.toLowerCase().split("+")); int metaCode = 0, code = 0; for (int k : keys) { String key = keys.$get(k); if (meta.$get(key) != null) { metaCode += meta.$get(key); } else if (special_keys.$get(key) != null) { code = special_keys.$get(key); } else { code = charCodeAt(key.toUpperCase(), 0); }// the upper case letter } Handler h = new Handler(handler, propagate, combination, metaCode * 1000 + code); this.handlers.$put(metaCode * 1000 + code, h); } public void addDefault(Function1<Event, Boolean> handler, boolean propagate) { this.defaultHandler = new Handler(handler, propagate, null, 0); } public boolean handleEvent(Event e) { // if (e.keyCode == 17) { // e.preventDefault(); // return; // } int code = e.keyCode; int metaCode = 0; if (e.ctrlKey) { metaCode += CTRL; } if (e.shiftKey) { metaCode += SHIFT; } if (e.altKey) { metaCode += ALT; } // if(e.metaKey) metaCode += mask.META; Handler h = this.handlers.$get(metaCode * 1000 + code); if (h == null) { h = this.defaultHandler; } if (h != null) { boolean ret = h.handler.$invoke(e); if (!ret && !h.propagate) { e.preventDefault(); } return h.propagate && ret; } return true; } private class Handler { public final Function1<Event, Boolean> handler; public final boolean propagate; public final String combination; public final int code; public Handler(Function1<Event, Boolean> handler, boolean propagate, String combination, int code) { this.handler = handler; this.propagate = propagate; this.combination = combination; this.code = code; } } }