org.rstudio.core.rebind.command.ShortcutsEmitter.java Source code

Java tutorial

Introduction

Here is the source code for org.rstudio.core.rebind.command.ShortcutsEmitter.java

Source

/*
 * ShortcutsEmitter.java
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.core.rebind.command;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.user.rebind.SourceWriter;

import org.rstudio.core.client.command.KeyboardShortcut;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.transform.Result;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;

import java.io.StringWriter;

public class ShortcutsEmitter {
    public ShortcutsEmitter(TreeLogger logger, String groupName, Element shortcutsEl)
            throws UnableToCompleteException {
        logger_ = logger;
        shortcutsEl_ = shortcutsEl;
        groupName_ = groupName;
    }

    public void generate(SourceWriter writer) throws UnableToCompleteException {
        NodeList children = shortcutsEl_.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node childNode = children.item(i);
            if (childNode.getNodeType() != Node.ELEMENT_NODE)
                continue;
            Element childEl = (Element) childNode;
            if (!childEl.getTagName().equals("shortcut")) {
                logger_.log(Type.ERROR, "Unexpected element: " + elementToString(childEl));
                throw new UnableToCompleteException();
            }

            String condition = childEl.getAttribute("if");
            String command = childEl.getAttribute("refid");
            String shortcutValue = childEl.getAttribute("value");
            String title = childEl.getAttribute("title");
            String disableModes = childEl.getAttribute("disableModes");

            // Use null when we don't have a command associated with the shortcut,
            // otherwise refer to the function that returns the command 
            command += command.isEmpty() ? "null" : "()";

            if (shortcutValue.length() == 0) {
                logger_.log(Type.ERROR, "Required attribute shortcut was missing\n" + elementToString(childEl));
                throw new UnableToCompleteException();
            }

            printShortcut(writer, condition, shortcutValue, command, groupName_, title, disableModes);
        }
    }

    private void printShortcut(SourceWriter writer, String condition, String shortcutValue, String command,
            String shortcutGroup, String title, String disableModes) throws UnableToCompleteException {
        String[] chunks = shortcutValue.split("\\+");
        int modifiers = KeyboardShortcut.NONE;
        boolean cmd = false;
        for (int i = 0; i < chunks.length - 1; i++) {
            String m = chunks[i];
            if (m.equals("Ctrl"))
                modifiers += KeyboardShortcut.CTRL;
            else if (m.equals("Meta"))
                modifiers += KeyboardShortcut.META;
            else if (m.equals("Alt"))
                modifiers += KeyboardShortcut.ALT;
            else if (m.equals("Shift"))
                modifiers += KeyboardShortcut.SHIFT;
            else if (m.equals("Cmd"))
                cmd = true;
            else {
                logger_.log(Type.ERROR, "Invalid shortcut " + shortcutValue);
                throw new UnableToCompleteException();
            }
        }

        String key = toKey(chunks[chunks.length - 1]);
        if (key == null) {
            logger_.log(Type.ERROR,
                    "Invalid shortcut " + shortcutValue + ", only " + "modified alphanumeric characters, enter, "
                            + "left, right, up, down, pageup, pagedown, " + "and tab are valid");
            throw new UnableToCompleteException();
        }

        if (!condition.isEmpty()) {
            writer.println("if (" + condition + ") {");
            writer.indent();
        }

        if (cmd) {
            writer.println("ShortcutManager.INSTANCE.register(" + (modifiers | KeyboardShortcut.CTRL) + ", " + key
                    + ", " + command + ", " + "\"" + shortcutGroup + "\", " + "\"" + title + "\", " + "\""
                    + disableModes + "\");");
            writer.println("ShortcutManager.INSTANCE.register(" + (modifiers | KeyboardShortcut.META) + ", " + key
                    + ", " + command + ", " + "\"" + shortcutGroup + "\", " + "\"" + title + "\", " + "\""
                    + disableModes + "\");");
        } else {
            writer.println("ShortcutManager.INSTANCE.register(" + modifiers + ", " + key + ", " + command + ", "
                    + "\"" + shortcutGroup + "\", " + "\"" + title + "\", " + "\"" + disableModes + "\");");
        }

        if (!condition.isEmpty()) {
            writer.outdent();
            writer.println("}");
        }
    }

    private String toKey(String val) {
        if (val.matches("^[a-zA-Z0-9]$"))
            return "'" + val.toUpperCase() + "'";
        if (val.equals("/"))
            return "191";
        if (val.equalsIgnoreCase("enter"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_ENTER";
        if (val.equalsIgnoreCase("right"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_RIGHT";
        if (val.equalsIgnoreCase("left"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_LEFT";
        if (val.equalsIgnoreCase("up"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_UP";
        if (val.equalsIgnoreCase("down"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_DOWN";
        if (val.equalsIgnoreCase("tab"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_TAB";
        if (val.equalsIgnoreCase("pageup"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_PAGEUP";
        if (val.equalsIgnoreCase("pagedown"))
            return "com.google.gwt.event.dom.client.KeyCodes.KEY_PAGEDOWN";
        if (val.equalsIgnoreCase("F1"))
            return "112";
        if (val.equalsIgnoreCase("F2"))
            return "113";
        if (val.equalsIgnoreCase("F3"))
            return "114";
        if (val.equalsIgnoreCase("F4"))
            return "115";
        if (val.equalsIgnoreCase("F5"))
            return "116";
        if (val.equalsIgnoreCase("F6"))
            return "117";
        if (val.equalsIgnoreCase("F7"))
            return "118";
        if (val.equalsIgnoreCase("F8"))
            return "119";
        if (val.equalsIgnoreCase("F9"))
            return "120";
        if (val.equalsIgnoreCase("F10"))
            return "121";
        if (val.equalsIgnoreCase("F11"))
            return "122";
        if (val.equalsIgnoreCase("F12"))
            return "123";
        if (val.equals("`"))
            return "192";
        if (val.equals("."))
            return "190";
        if (val.equals("="))
            return "187";
        if (val.equals("<"))
            return "188";
        if (val.equals("-"))
            return "189";
        if (val.equals("Backspace"))
            return "8";
        return null;
    }

    private String elementToString(Element el) throws UnableToCompleteException {
        try {
            javax.xml.transform.TransformerFactory tfactory = TransformerFactory.newInstance();
            javax.xml.transform.Transformer xform = tfactory.newTransformer();
            javax.xml.transform.Source src = new DOMSource(el);
            java.io.StringWriter writer = new StringWriter();
            Result result = new javax.xml.transform.stream.StreamResult(writer);
            xform.transform(src, result);
            return writer.toString();
        } catch (Exception e) {
            logger_.log(Type.ERROR, "Error attempting to stringify some XML", e);
            throw new UnableToCompleteException();
        }
    }

    private final TreeLogger logger_;
    private final Element shortcutsEl_;
    private final String groupName_;
}