/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pivot.wtk.skin;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.Area;

import org.apache.pivot.collections.Dictionary;
import org.apache.pivot.wtk.ApplicationContext;
import org.apache.pivot.wtk.Bounds;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Cursor;
import org.apache.pivot.wtk.Dimensions;
import org.apache.pivot.wtk.GraphicsUtilities;
import org.apache.pivot.wtk.Insets;
import org.apache.pivot.wtk.Keyboard;
import org.apache.pivot.wtk.Mouse;
import org.apache.pivot.wtk.Platform;
import org.apache.pivot.wtk.TextPane;
import org.apache.pivot.wtk.TextPaneListener;
import org.apache.pivot.wtk.TextPaneSelectionListener;
import org.apache.pivot.wtk.Theme;
import org.apache.pivot.wtk.text.Document;
import org.apache.pivot.wtk.text.Node;
import org.apache.pivot.wtk.text.Paragraph;

/**
 * Text pane skin.
 */
public class TextPaneSkin extends ContainerSkin implements TextPane.Skin, TextPaneListener,
    TextPaneSelectionListener {
    private class BlinkCaretCallback implements Runnable {
        @Override
        public void run() {
            caretOn = !caretOn;

            if (selection == null) {
                TextPane textPane = (TextPane) getComponent();
                textPane.repaint(caret.x, caret.y, caret.width, caret.height);
            }
        }
    }

    private class ScrollSelectionCallback implements Runnable {
        @Override
        public void run() {
            TextPane textPane = (TextPane) getComponent();
            int selectionStart = textPane.getSelectionStart();
            int selectionLength = textPane.getSelectionLength();
            int selectionEnd = selectionStart + selectionLength - 1;

            switch (scrollDirection) {
                case UP: {
                    // Get previous offset
                    int offset = getNextInsertionPoint(mouseX, selectionStart, scrollDirection);

                    if (offset != -1) {
                        textPane.setSelection(offset, selectionEnd - offset + 1);
                        scrollCharacterToVisible(offset + 1);
                    }

                    break;
                }

                case DOWN: {
                    // Get next offset
                    int offset = getNextInsertionPoint(mouseX, selectionEnd, scrollDirection);

                    if (offset != -1) {
                        // If the next character is a paragraph terminator and
                        // is not the
                        // final terminator character, increment the selection
                        Document document = textPane.getDocument();
                        if (document.getCharacterAt(offset) == '\n'
                            && offset < documentView.getCharacterCount() - 1) {
                            offset++;
                        }

                        textPane.setSelection(selectionStart, offset - selectionStart);
                        scrollCharacterToVisible(offset - 1);
                    }

                    break;
                }

                default: {
                    throw new RuntimeException();
                }
            }
        }
    }

    private TextPaneSkinDocumentView documentView = null;

    private int caretX = 0;
    private Rectangle caret = new Rectangle();
    private Area selection = null;

    private boolean caretOn = false;

    private int anchor = -1;
    private TextPane.ScrollDirection scrollDirection = null;
    private int mouseX = -1;

    private BlinkCaretCallback blinkCaretCallback = new BlinkCaretCallback();
    private ApplicationContext.ScheduledCallback scheduledBlinkCaretCallback = null;

    private ScrollSelectionCallback scrollSelectionCallback = new ScrollSelectionCallback();
    private ApplicationContext.ScheduledCallback scheduledScrollSelectionCallback = null;

    private Font font;
    private Color color;
    private Color inactiveColor;
    private Color selectionColor;
    private Color selectionBackgroundColor;
    private Color inactiveSelectionColor;
    private Color inactiveSelectionBackgroundColor;

    private Insets margin = new Insets(4);

    private boolean wrapText = true;
    private int tabWidth = 4;
    private boolean acceptsTab = false;

    private static final int SCROLL_RATE = 30;

    public TextPaneSkin() {
        Theme theme = Theme.getTheme();
        font = theme.getFont();

        color = defaultForegroundColor();
        selectionBackgroundColor = defaultForegroundColor();
        inactiveSelectionBackgroundColor = defaultForegroundColor();
        if (!themeIsDark()) {
            selectionColor = Color.LIGHT_GRAY;
            inactiveSelectionColor = Color.LIGHT_GRAY;
        } else {
            selectionColor = Color.DARK_GRAY;
            inactiveSelectionColor = Color.DARK_GRAY;
        }

        inactiveColor = Color.GRAY;
    }

    @Override
    public void install(Component component) {
        super.install(component);

        TextPane textPane = (TextPane) component;
        textPane.getTextPaneListeners().add(this);
        textPane.getTextPaneSelectionListeners().add(this);

        textPane.setCursor(Cursor.TEXT);

        Document document = textPane.getDocument();
        if (document != null) {
            documentView = (TextPaneSkinDocumentView) TextPaneSkinNodeView.createNodeView(this, document);
            documentView.attach();
            updateSelection();
        }
    }

    @Override
    public boolean isFocusable() {
        return true;
    }

    @Override
    public int getPreferredWidth(int height) {
        int preferredWidth;

        if (documentView == null) {
            preferredWidth = 0;
        } else {
            Dimensions documentDimensions = documentView.getPreferredSize(Integer.MAX_VALUE);

            preferredWidth = documentDimensions.width + margin.left + margin.right;
        }

        return preferredWidth;
    }

    @Override
    public int getPreferredHeight(int width) {
        int preferredHeight;

        if (documentView == null || width == -1) {
            preferredHeight = 0;
        } else {
            int breakWidth;
            if (wrapText) {
                breakWidth = Math.max(width - (margin.left + margin.right), 0);
            } else {
                breakWidth = Integer.MAX_VALUE;
            }

            Dimensions documentDimensions = documentView.getPreferredSize(breakWidth);

            preferredHeight = documentDimensions.height + margin.top + margin.bottom;
        }

        return preferredHeight;
    }

    @Override
    public Dimensions getPreferredSize() {
        int preferredHeight;
        int preferredWidth;

        if (documentView == null) {
            preferredWidth = 0;
            preferredHeight = 0;
        } else {
            Dimensions documentDimensions = documentView.getPreferredSize(Integer.MAX_VALUE);

            preferredWidth = documentDimensions.width + margin.left + margin.right;
            preferredHeight = documentDimensions.height + margin.top + margin.bottom;
        }

        return new Dimensions(preferredWidth, preferredHeight);
    }

    @Override
    public int getBaseline(int width, int height) {
        FontRenderContext fontRenderContext = Platform.getFontRenderContext();
        LineMetrics lm = font.getLineMetrics("", fontRenderContext);
        float ascent = lm.getAscent();
        return margin.top + Math.round(ascent);
    }

    @Override
    public void layout() {
        if (documentView != null) {
            TextPane textPane = (TextPane) getComponent();
            int width = getWidth();

            int breakWidth;
            if (wrapText) {
                breakWidth = Math.max(width - (margin.left + margin.right), 0);
            } else {
                breakWidth = Integer.MAX_VALUE;
            }
            documentView.layout(breakWidth);
            documentView.setSkinLocation(margin.left, margin.top);

            updateSelection();
            caretX = caret.x;

            if (textPane.isFocused()) {
                scrollCharacterToVisible(textPane.getSelectionStart());
            }

            showCaret(textPane.isFocused() && textPane.getSelectionLength() == 0);
        }
    }

    @Override
    public void paint(Graphics2D graphics) {
        super.paint(graphics);

        TextPane textPane = (TextPane) getComponent();

        if (documentView != null) {
            // Draw the selection highlight
            if (selection != null) {
                graphics.setColor(textPane.isFocused() && textPane.isEditable() ? selectionBackgroundColor
                    : inactiveSelectionBackgroundColor);
                graphics.fill(selection);
            }

            int width = getWidth();
            int breakWidth;
            if (wrapText) {
                breakWidth = Math.max(width - (margin.left + margin.right), 0);
            } else {
                breakWidth = Integer.MAX_VALUE;
            }
            documentView.layout(breakWidth);

            // Draw the document content
            graphics.translate(margin.left, margin.top);
            documentView.paint(graphics);
            graphics.translate(-margin.left, -margin.top);

            // Draw the caret
            if (selection == null && caretOn && textPane.isFocused()) {
                graphics.setColor(textPane.isEditable() ? color : inactiveColor);
                graphics.fill(caret);
            }
        }
    }

    @Override
    public int getInsertionPoint(int x, int y) {
        int offset;

        if (documentView == null) {
            offset = -1;
        } else {
            int xUpdated = Math.min(documentView.getWidth() - 1, Math.max(x - margin.left, 0));

            if (y < margin.top) {
                offset = documentView.getNextInsertionPoint(xUpdated, -1,
                    TextPane.ScrollDirection.DOWN);
            } else if (y > documentView.getHeight() + margin.top) {
                offset = documentView.getNextInsertionPoint(xUpdated, -1,
                    TextPane.ScrollDirection.UP);
            } else {
                offset = documentView.getInsertionPoint(xUpdated, y - margin.top);
            }
        }

        return offset;
    }

    @Override
    public int getNextInsertionPoint(int x, int from, TextPane.ScrollDirection direction) {
        int offset;

        if (documentView == null) {
            offset = -1;
        } else {
            offset = documentView.getNextInsertionPoint(x - margin.left, from, direction);
        }

        return offset;
    }

    @Override
    public int getRowAt(int offset) {
        int rowIndex;

        if (documentView == null) {
            rowIndex = -1;
        } else {
            rowIndex = documentView.getRowAt(offset);
        }

        return rowIndex;
    }

    @Override
    public int getRowCount() {
        int rowCount;

        if (documentView == null) {
            rowCount = 0;
        } else {
            rowCount = documentView.getRowCount();
        }

        return rowCount;
    }

    @Override
    public Bounds getCharacterBounds(int offset) {
        Bounds characterBounds;

        if (documentView == null) {
            characterBounds = null;
        } else {
            characterBounds = documentView.getCharacterBounds(offset);

            if (characterBounds != null) {
                characterBounds = characterBounds.translate(margin.left, margin.top);
            }
        }

        return characterBounds;
    }

    /**
     * Gets current value of style that determines the behavior of <tt>TAB</tt>
     * and <tt>Ctrl-TAB</tt> characters.
     *
     * @return <tt>true</tt> if <tt>TAB</tt> inserts an appropriate number of
     * spaces, while <tt>Ctrl-TAB</tt> shifts focus to next component.
     * <tt>false</tt> (default) means <tt>TAB</tt> shifts focus and
     * <tt>Ctrl-TAB</tt> inserts spaces.
     */
    public boolean getAcceptsTab() {
        return acceptsTab;
    }

    /**
     * Sets current value of style that determines the behavior of <tt>TAB</tt>
     * and <tt>Ctrl-TAB</tt> characters.
     *
     * @param acceptsTab <tt>true</tt> if <tt>TAB</tt> inserts an appropriate
     * number of spaces, while <tt>Ctrl-TAB</tt> shifts focus to next component.
     * <tt>false</tt> (default) means <tt>TAB</tt> shifts focus and
     * <tt>Ctrl-TAB</tt> inserts spaces.
     */
    public void setAcceptsTab(boolean acceptsTab) {
        this.acceptsTab = acceptsTab;
    }

    @Override
    public int getTabWidth() {
        return tabWidth;
    }

    public void setTabWidth(int tabWidth) {
        if (tabWidth < 0) {
            throw new IllegalArgumentException("tabWidth is negative.");
        }

        this.tabWidth = tabWidth;
    }

    private void scrollCharacterToVisible(int offset) {
        TextPane textPane = (TextPane) getComponent();
        Bounds characterBounds = getCharacterBounds(offset);

        if (characterBounds != null) {
            textPane.scrollAreaToVisible(characterBounds.x, characterBounds.y,
                characterBounds.width, characterBounds.height);
        }
    }

    /**
     * @return The font of the text.
     */
    public Font getFont() {
        return font;
    }

    /**
     * Sets the font of the text.
     *
     * @param font The new font for all the text.
     */
    public void setFont(Font font) {
        if (font == null) {
            throw new IllegalArgumentException("font is null.");
        }

        this.font = font;
        invalidateComponent();
    }

    /**
     * Sets the font of the text.
     *
     * @param font A {@link ComponentSkin#decodeFont(String) font specification}
     */
    public final void setFont(String font) {
        if (font == null) {
            throw new IllegalArgumentException("font is null.");
        }

        setFont(decodeFont(font));
    }

    /**
     * Sets the font of the text.
     *
     * @param font A dictionary {@link Theme#deriveFont describing a font}
     */
    public final void setFont(Dictionary<String, ?> font) {
        if (font == null) {
            throw new IllegalArgumentException("font is null.");
        }

        setFont(Theme.deriveFont(font));
    }

    /**
     * @return The foreground color of the text.
     */
    public Color getColor() {
        return color;
    }

    /**
     * Sets the foreground color of the text.
     *
     * @param color The new text color.
     */
    public void setColor(Color color) {
        if (color == null) {
            throw new IllegalArgumentException("color is null.");
        }

        this.color = color;
        repaintComponent();
    }

    /**
     * Sets the foreground color of the text.
     *
     * @param color Any of the {@linkplain GraphicsUtilities#decodeColor color
     * values recognized by Pivot}.
     */
    public final void setColor(String color) {
        if (color == null) {
            throw new IllegalArgumentException("color is null.");
        }

        setColor(GraphicsUtilities.decodeColor(color));
    }

    public Color getInactiveColor() {
        return inactiveColor;
    }

    public void setInactiveColor(Color inactiveColor) {
        if (inactiveColor == null) {
            throw new IllegalArgumentException("inactiveColor is null.");
        }

        this.inactiveColor = inactiveColor;
        repaintComponent();
    }

    public final void setInactiveColor(String inactiveColor) {
        if (inactiveColor == null) {
            throw new IllegalArgumentException("inactiveColor is null.");
        }

        setColor(GraphicsUtilities.decodeColor(inactiveColor));
    }

    public Color getSelectionColor() {
        return selectionColor;
    }

    public void setSelectionColor(Color selectionColor) {
        if (selectionColor == null) {
            throw new IllegalArgumentException("selectionColor is null.");
        }

        this.selectionColor = selectionColor;
        repaintComponent();
    }

    public final void setSelectionColor(String selectionColor) {
        if (selectionColor == null) {
            throw new IllegalArgumentException("selectionColor is null.");
        }

        setSelectionColor(GraphicsUtilities.decodeColor(selectionColor));
    }

    public Color getSelectionBackgroundColor() {
        return selectionBackgroundColor;
    }

    public void setSelectionBackgroundColor(Color selectionBackgroundColor) {
        if (selectionBackgroundColor == null) {
            throw new IllegalArgumentException("selectionBackgroundColor is null.");
        }

        this.selectionBackgroundColor = selectionBackgroundColor;
        repaintComponent();
    }

    public final void setSelectionBackgroundColor(String selectionBackgroundColor) {
        if (selectionBackgroundColor == null) {
            throw new IllegalArgumentException("selectionBackgroundColor is null.");
        }

        setSelectionBackgroundColor(GraphicsUtilities.decodeColor(selectionBackgroundColor));
    }

    public Color getInactiveSelectionColor() {
        return inactiveSelectionColor;
    }

    public void setInactiveSelectionColor(Color inactiveSelectionColor) {
        if (inactiveSelectionColor == null) {
            throw new IllegalArgumentException("inactiveSelectionColor is null.");
        }

        this.inactiveSelectionColor = inactiveSelectionColor;
        repaintComponent();
    }

    public final void setInactiveSelectionColor(String inactiveSelectionColor) {
        if (inactiveSelectionColor == null) {
            throw new IllegalArgumentException("inactiveSelectionColor is null.");
        }

        setInactiveSelectionColor(GraphicsUtilities.decodeColor(inactiveSelectionColor));
    }

    public Color getInactiveSelectionBackgroundColor() {
        return inactiveSelectionBackgroundColor;
    }

    public void setInactiveSelectionBackgroundColor(Color inactiveSelectionBackgroundColor) {
        if (inactiveSelectionBackgroundColor == null) {
            throw new IllegalArgumentException("inactiveSelectionBackgroundColor is null.");
        }

        this.inactiveSelectionBackgroundColor = inactiveSelectionBackgroundColor;
        repaintComponent();
    }

    public final void setInactiveSelectionBackgroundColor(String inactiveSelectionBackgroundColor) {
        if (inactiveSelectionBackgroundColor == null) {
            throw new IllegalArgumentException("inactiveSelectionBackgroundColor is null.");
        }

        setInactiveSelectionBackgroundColor(GraphicsUtilities.decodeColor(inactiveSelectionBackgroundColor));
    }

    /**
     * @return The amount of space between the edge of the TextPane and its
     * Document.
     */
    public Insets getMargin() {
        return margin;
    }

    /**
     * Sets the amount of space between the edge of the TextPane and its
     * Document.
     *
     * @param margin The new set of margin values.
     */
    public void setMargin(Insets margin) {
        if (margin == null) {
            throw new IllegalArgumentException("margin is null.");
        }

        this.margin = margin;
        invalidateComponent();
    }

    /**
     * Sets the amount of space between the edge of the TextPane and its
     * Document.
     *
     * @param margin A dictionary with keys in the set {left, top, bottom,
     * right}.
     */
    public final void setMargin(Dictionary<String, ?> margin) {
        if (margin == null) {
            throw new IllegalArgumentException("margin is null.");
        }

        setMargin(new Insets(margin));
    }

    /**
     * Sets the amount of space between the edge of the TextPane and its
     * Document.
     *
     * @param margin The single margin value for all edges.
     */
    public final void setMargin(int margin) {
        setMargin(new Insets(margin));
    }

    /**
     * Sets the amount of space between the edge of the TextPane and its
     * Document.
     *
     * @param margin The new single margin value for all the edges.
     */
    public final void setMargin(Number margin) {
        if (margin == null) {
            throw new IllegalArgumentException("margin is null.");
        }

        setMargin(margin.intValue());
    }

    /**
     * Sets the amount of space between the edge of the TextPane and its
     * Document.
     *
     * @param margin A string containing an integer or a JSON dictionary with
     * keys left, top, bottom, and/or right.
     */
    public final void setMargin(String margin) {
        if (margin == null) {
            throw new IllegalArgumentException("margin is null.");
        }

        setMargin(Insets.decode(margin));
    }

    public boolean getWrapText() {
        return wrapText;
    }

    public void setWrapText(boolean wrapText) {
        if (this.wrapText != wrapText) {
            this.wrapText = wrapText;

            if (documentView != null) {
                documentView.invalidateUpTree();
            }
        }
    }

    @Override
    public boolean mouseMove(Component component, int x, int y) {
        boolean consumed = super.mouseMove(component, x, y);

        if (Mouse.getCapturer() == component) {
            TextPane textPane = (TextPane) getComponent();

            Bounds visibleArea = textPane.getVisibleArea();
            visibleArea = new Bounds(visibleArea.x, visibleArea.y, visibleArea.width,
                visibleArea.height);

            if (y >= visibleArea.y && y < visibleArea.y + visibleArea.height) {
                // Stop the scroll selection timer
                if (scheduledScrollSelectionCallback != null) {
                    scheduledScrollSelectionCallback.cancel();
                    scheduledScrollSelectionCallback = null;
                }

                scrollDirection = null;
                int offset = getInsertionPoint(x, y);

                if (offset != -1) {
                    // Select the range
                    if (offset > anchor) {
                        textPane.setSelection(anchor, offset - anchor);
                    } else {
                        textPane.setSelection(offset, anchor - offset);
                    }
                }
            } else {
                if (scheduledScrollSelectionCallback == null) {
                    scrollDirection = (y < visibleArea.y) ? TextPane.ScrollDirection.UP
                        : TextPane.ScrollDirection.DOWN;

                    scheduledScrollSelectionCallback = ApplicationContext.scheduleRecurringCallback(
                        scrollSelectionCallback, SCROLL_RATE);

                    // Run the callback once now to scroll the selection
                    // immediately
                    scrollSelectionCallback.run();
                }
            }

            mouseX = x;
        } else {
            if (Mouse.isPressed(Mouse.Button.LEFT) && Mouse.getCapturer() == null && anchor != -1) {
                // Capture the mouse so we can select text
                Mouse.capture(component);
            }
        }

        return consumed;
    }

    @Override
    public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {
        boolean consumed = super.mouseDown(component, button, x, y);

        if (button == Mouse.Button.LEFT) {
            TextPane textPane = (TextPane) component;

            anchor = getInsertionPoint(x, y);

            if (anchor != -1) {
                if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)) {
                    // Select the range
                    int selectionStart = textPane.getSelectionStart();

                    if (anchor > selectionStart) {
                        textPane.setSelection(selectionStart, anchor - selectionStart);
                    } else {
                        textPane.setSelection(anchor, selectionStart - anchor);
                    }
                } else {
                    // Move the caret to the insertion point
                    textPane.setSelection(anchor, 0);
                    consumed = true;
                }
            }

            caretX = caret.x;

            // Set focus to the text input
            textPane.requestFocus();
        }

        return consumed;
    }

    @Override
    public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
        boolean consumed = super.mouseUp(component, button, x, y);

        if (Mouse.getCapturer() == component) {
            // Stop the scroll selection timer
            if (scheduledScrollSelectionCallback != null) {
                scheduledScrollSelectionCallback.cancel();
                scheduledScrollSelectionCallback = null;
            }

            Mouse.release();
        }

        anchor = -1;
        scrollDirection = null;
        mouseX = -1;

        return consumed;
    }

    @Override
    public boolean keyTyped(final Component component, char character) {
        boolean consumed = super.keyTyped(component, character);

        final TextPane textPane = (TextPane) getComponent();

        if (textPane.isEditable()) {
            Document document = textPane.getDocument();

            if (document != null) {
                // Ignore characters in the control range and the ASCII delete
                // character as well as meta key presses
                if (character > 0x1F && character != 0x7F
                    && !Keyboard.isPressed(Keyboard.Modifier.META)) {
                    textPane.insert(character);
                    showCaret(true);
                }
            }
        }

        return consumed;
    }

    private int getRowOffset(Document document, int index) {
        if (document != null) {
            Node node = document.getDescendantAt(index);
            while (node != null && !(node instanceof Paragraph)) {
                node = node.getParent();
            }
            // TODO: doesn't take into account the line wrapping within a paragraph
            if (node != null) {
                return node.getDocumentOffset();
            }
        }
        return 0;
    }

    private int getRowLength(Document document, int index) {
        if (document != null) {
            Node node = document.getDescendantAt(index);
            while (node != null && !(node instanceof Paragraph)) {
                node = node.getParent();
            }
            // TODO: doesn't take into account the line wrapping within a paragraph
            // Assuming the node is a Paragraph, the count includes the trailing \n, so discount it
            if (node != null) {
                return node.getCharacterCount() - 1;
            }
        }
        return 0;
    }

    @Override
    public boolean keyPressed(final Component component, int keyCode,
        Keyboard.KeyLocation keyLocation) {
        boolean consumed = false;

        final TextPane textPane = (TextPane) getComponent();
        Document document = textPane.getDocument();

        int selectionStart = textPane.getSelectionStart();
        int selectionLength = textPane.getSelectionLength();

        Keyboard.Modifier commandModifier = Platform.getCommandModifier();
        boolean commandPressed = Keyboard.isPressed(commandModifier);
        // boolean wordNavPressed = Keyboard.isPressed(Platform.getWordNavigationModifier());
        boolean shiftPressed = Keyboard.isPressed(Keyboard.Modifier.SHIFT);
        // boolean ctrlPressed = Keyboard.isPressed(Keyboard.Modifier.CTRL);
        boolean metaPressed = Keyboard.isPressed(Keyboard.Modifier.META);
        boolean isEditable = textPane.isEditable();

        if (document != null) {
            if (keyCode == Keyboard.KeyCode.ENTER && isEditable) {
                textPane.insertParagraph();

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.DELETE && isEditable) {
                textPane.delete(false);

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.BACKSPACE && isEditable) {
                textPane.delete(true);

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.HOME
                   || (keyCode == Keyboard.KeyCode.LEFT && metaPressed)) {
                int start;
                if (commandPressed) {
                    // Move the caret to the beginning of the text
                    start = 0;
                } else {
                    // Move the caret to the beginning of the line
                    start = getRowOffset(document, selectionStart);
                }

                if (shiftPressed) {
                    selectionLength += selectionStart - start;
                } else {
                    selectionLength = 0;
                }

                if (selectionStart >= 0) {
                    textPane.setSelection(start, selectionLength);
                    scrollCharacterToVisible(start);

                    consumed = true;
                }
            } else if (keyCode == Keyboard.KeyCode.END
                   || (keyCode == Keyboard.KeyCode.RIGHT && metaPressed)) {
                int end;
                int index = selectionStart + selectionLength;

                if (commandPressed) {
                    // Move the caret to end of the text
                    end = textPane.getCharacterCount() - 1;
                } else {
                    // Move the caret to the end of the line
                    int rowOffset = getRowOffset(document, index);
                    int rowLength = getRowLength(document, index);
                    end = rowOffset + rowLength;
                }

                if (shiftPressed) {
                    selectionLength += end - index;
                } else {
                    selectionStart = end;
                    if (selectionStart < textPane.getCharacterCount()
                        && document.getCharacterAt(selectionStart) == '\n') {
                        selectionStart--;
                    }

                    selectionLength = 0;
                }

                if (selectionStart + selectionLength <= textPane.getCharacterCount()) {
                    textPane.setSelection(selectionStart, selectionLength);
                    scrollCharacterToVisible(selectionStart + selectionLength);

                    consumed = true;
                }
            } else if (keyCode == Keyboard.KeyCode.LEFT) {
                if (shiftPressed) {
                    // Add the previous character to the selection
                    if (selectionStart > 0) {
                        selectionStart--;
                        selectionLength++;
                    }
                } else if (Keyboard.isPressed(Keyboard.Modifier.CTRL)) {
                    // Move the caret to the start of the next word to our left
                    if (selectionStart > 0) {
                        // first, skip over any space immediately to our left
                        while (selectionStart > 0
                            && Character.isWhitespace(document.getCharacterAt(selectionStart - 1))) {
                            selectionStart--;
                        }
                        // then, skip over any word-letters to our left
                        while (selectionStart > 0
                            && !Character.isWhitespace(document.getCharacterAt(selectionStart - 1))) {
                            selectionStart--;
                        }

                        selectionLength = 0;
                    }
                } else {
                    // Clear the selection and move the caret back by one
                    // character
                    if (selectionLength == 0 && selectionStart > 0) {
                        selectionStart--;
                    }

                    selectionLength = 0;
                }

                textPane.setSelection(selectionStart, selectionLength);
                scrollCharacterToVisible(selectionStart);

                caretX = caret.x;

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.RIGHT) {
                if (shiftPressed) {
                    // Add the next character to the selection
                    if (selectionStart + selectionLength < document.getCharacterCount()) {
                        selectionLength++;
                    }

                    textPane.setSelection(selectionStart, selectionLength);
                    scrollCharacterToVisible(selectionStart + selectionLength);
                } else if (Keyboard.isPressed(Keyboard.Modifier.CTRL)) {
                    // Move the caret to the start of the next word to our right
                    if (selectionStart < document.getCharacterCount()) {
                        // first, skip over any word-letters to our right
                        while (selectionStart < document.getCharacterCount() - 1
                            && !Character.isWhitespace(document.getCharacterAt(selectionStart))) {
                            selectionStart++;
                        }
                        // then, skip over any space immediately to our right
                        while (selectionStart < document.getCharacterCount() - 1
                            && Character.isWhitespace(document.getCharacterAt(selectionStart))) {
                            selectionStart++;
                        }

                        textPane.setSelection(selectionStart, 0);
                        scrollCharacterToVisible(selectionStart);

                        caretX = caret.x;
                    }
                } else {
                    // Clear the selection and move the caret forward by one
                    // character
                    if (selectionLength > 0) {
                        selectionStart += selectionLength - 1;
                    }

                    if (selectionStart < document.getCharacterCount() - 1) {
                        selectionStart++;
                    }

                    textPane.setSelection(selectionStart, 0);
                    scrollCharacterToVisible(selectionStart);

                    caretX = caret.x;
                }

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.UP) {
                int offset = getNextInsertionPoint(caretX, selectionStart,
                    TextPane.ScrollDirection.UP);

                if (offset == -1) {
                    offset = 0;
                }

                if (shiftPressed) {
                    selectionLength = selectionStart + selectionLength - offset;
                } else {
                    selectionLength = 0;
                }

                textPane.setSelection(offset, selectionLength);
                scrollCharacterToVisible(offset);

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.DOWN) {

                if (shiftPressed) {
                    int from;
                    int x;
                    if (selectionLength == 0) {
                        // Get next insertion point from leading selection
                        // character
                        from = selectionStart;
                        x = caretX;
                    } else {
                        // Get next insertion point from right edge of trailing
                        // selection
                        // character
                        from = selectionStart + selectionLength - 1;

                        Bounds trailingSelectionBounds = getCharacterBounds(from);
                        x = trailingSelectionBounds.x + trailingSelectionBounds.width;
                    }

                    int offset = getNextInsertionPoint(x, from, TextPane.ScrollDirection.DOWN);

                    if (offset == -1) {
                        offset = documentView.getCharacterCount() - 1;
                    } else {
                        // If the next character is a paragraph terminator and
                        // is not the
                        // final terminator character, increment the selection
                        if (document.getCharacterAt(offset) == '\n'
                            && offset < documentView.getCharacterCount() - 1) {
                            offset++;
                        }
                    }

                    textPane.setSelection(selectionStart, offset - selectionStart);
                    scrollCharacterToVisible(offset);
                } else {
                    int from;
                    if (selectionLength == 0) {
                        // Get next insertion point from leading selection
                        // character
                        from = selectionStart;
                    } else {
                        // Get next insertion point from trailing selection
                        // character
                        from = selectionStart + selectionLength - 1;
                    }

                    int offset = getNextInsertionPoint(caretX, from, TextPane.ScrollDirection.DOWN);

                    if (offset == -1) {
                        offset = documentView.getCharacterCount() - 1;
                    }

                    textPane.setSelection(offset, 0);
                    scrollCharacterToVisible(offset);
                }

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.TAB
                && (acceptsTab != Keyboard.isPressed(Keyboard.Modifier.CTRL))
                && isEditable) {
                if (textPane.getExpandTabs()) {
                    int linePos = selectionStart - getRowOffset(document, selectionStart);
                    StringBuilder tabBuilder = new StringBuilder(tabWidth);
                    for (int i = 0; i < tabWidth - (linePos % tabWidth); i++) {
                        tabBuilder.append(" ");
                    }
                    textPane.insert(tabBuilder.toString());
                } else {
                    textPane.insert("\t");
                }
                showCaret(true);

                consumed = true;
            } else if (keyCode == Keyboard.KeyCode.INSERT) {
                if (shiftPressed && isEditable) {
                    textPane.paste();
                    consumed = true;
                }
            } else if (commandPressed) {
                if (keyCode == Keyboard.KeyCode.A) {
                    textPane.setSelection(0, document.getCharacterCount());
                    consumed = true;
                } else if (keyCode == Keyboard.KeyCode.X && isEditable) {
                    textPane.cut();
                    consumed = true;
                } else if (keyCode == Keyboard.KeyCode.C) {
                    textPane.copy();
                    consumed = true;
                } else if (keyCode == Keyboard.KeyCode.V && isEditable) {
                    textPane.paste();
                    consumed = true;
                } else if (keyCode == Keyboard.KeyCode.Z && isEditable) {
                    if (shiftPressed) {
                        textPane.redo();
                    } else {
                        textPane.undo();
                    }

                    consumed = true;
                }
            } else {
                consumed = super.keyPressed(component, keyCode, keyLocation);
            }
        }

        return consumed;
    }

    // Component state events
    @Override
    public void enabledChanged(Component component) {
        super.enabledChanged(component);

        repaintComponent();
    }

    @Override
    public void focusedChanged(Component component, Component obverseComponent) {
        super.focusedChanged(component, obverseComponent);

        TextPane textPane = (TextPane) getComponent();
        if (textPane.isFocused() && textPane.getSelectionLength() == 0) {
            scrollCharacterToVisible(textPane.getSelectionStart());
            showCaret(true);
        } else {
            showCaret(false);
        }

        repaintComponent();
    }

    // Text pane events
    @Override
    public void documentChanged(TextPane textPane, Document previousDocument) {
        if (documentView != null) {
            documentView.detach();
            documentView = null;
        }

        Document document = textPane.getDocument();
        if (document != null) {
            documentView = (TextPaneSkinDocumentView) TextPaneSkinNodeView.createNodeView(this, document);
            documentView.attach();
        }

        invalidateComponent();
    }

    @Override
    public void editableChanged(TextPane textPane) {
        // No-op
    }

    // Text pane selection events
    @Override
    public void selectionChanged(TextPane textPane, int previousSelectionStart,
        int previousSelectionLength) {
        // If the document view is valid, repaint the selection state;
        // otherwise,
        // the selection will be updated in layout()
        if (documentView != null && documentView.isValid()) {
            if (selection == null) {
                // Repaint previous caret bounds
                textPane.repaint(caret.x, caret.y, caret.width, caret.height);
            } else {
                // Repaint previous selection bounds
                Rectangle bounds = selection.getBounds();
                textPane.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
            }

            updateSelection();

            if (selection == null) {
                showCaret(textPane.isFocused());
            } else {
                showCaret(false);

                // Repaint current selection bounds
                Rectangle bounds = selection.getBounds();
                textPane.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
            }
        }
    }

    private void updateSelection() {
        if (documentView.getCharacterCount() > 0) {
            TextPane textPane = (TextPane) getComponent();

            // Update the caret
            int selectionStart = textPane.getSelectionStart();

            Bounds leadingSelectionBounds = getCharacterBounds(selectionStart);
            // sanity check - this is where a lot of bugs show up
            if (leadingSelectionBounds == null) {
                throw new IllegalStateException("no bounds for selection " + selectionStart);
            }
            caret = leadingSelectionBounds.toRectangle();
            caret.width = 1;

            // Update the selection
            int selectionLength = textPane.getSelectionLength();

            if (selectionLength > 0) {
                int selectionEnd = selectionStart + selectionLength - 1;
                Bounds trailingSelectionBounds = getCharacterBounds(selectionEnd);
                selection = new Area();

                int firstRowIndex = getRowAt(selectionStart);
                int lastRowIndex = getRowAt(selectionEnd);

                if (firstRowIndex == lastRowIndex) {
                    selection.add(new Area(new Rectangle(leadingSelectionBounds.x,
                        leadingSelectionBounds.y, trailingSelectionBounds.x
                            + trailingSelectionBounds.width - leadingSelectionBounds.x,
                        trailingSelectionBounds.y + trailingSelectionBounds.height
                            - leadingSelectionBounds.y)));
                } else {
                    int width = getWidth();

                    selection.add(new Area(new Rectangle(leadingSelectionBounds.x,
                        leadingSelectionBounds.y, width - margin.right - leadingSelectionBounds.x,
                        leadingSelectionBounds.height)));

                    if (lastRowIndex - firstRowIndex > 0) {
                        selection.add(new Area(new Rectangle(margin.left, leadingSelectionBounds.y
                            + leadingSelectionBounds.height, width - (margin.left + margin.right),
                            trailingSelectionBounds.y
                                - (leadingSelectionBounds.y + leadingSelectionBounds.height))));
                    }

                    selection.add(new Area(new Rectangle(margin.left, trailingSelectionBounds.y,
                        trailingSelectionBounds.x + trailingSelectionBounds.width - margin.left,
                        trailingSelectionBounds.height)));
                }
            } else {
                selection = null;
            }
        } else {
            // Clear the caret and the selection
            caret = new Rectangle();
            selection = null;
        }
    }

    private void showCaret(boolean show) {
        if (scheduledBlinkCaretCallback != null) {
            scheduledBlinkCaretCallback.cancel();
        }

        if (show) {
            caretOn = true;
            scheduledBlinkCaretCallback = ApplicationContext.scheduleRecurringCallback(
                blinkCaretCallback, Platform.getCursorBlinkRate());

            // Run the callback once now to show the cursor immediately
            blinkCaretCallback.run();
        } else {
            scheduledBlinkCaretCallback = null;
        }
    }

    Area getSelection() {
        return selection;
    }

    void invalidateNodeViewTree() {
        this.documentView.invalidateDownTree();
        invalidateComponent();
    }
}
