/*
 * Copyright 1997-1998 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.java.swing.plaf.motif;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.text.*;
import javax.swing.plaf.*;

/**
 * Provides the look and feel features that are common across
 * the Motif/CDE text LAF implementations.
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases.  The current serialization support is appropriate
 * for short term storage or RMI between applications running the same
 * version of Swing.  A future release of Swing will provide support for
 * long term persistence.
 *
 * @author  Timothy Prinzing
 */
public class MotifTextUI {

    /**
     * Creates the object to use for a caret for all of the Motif
     * text components.  The caret is rendered as an I-beam on Motif.
     *
     * @return the caret object
     */
    public static Caret createCaret() {
        return new MotifCaret();
    }

    /**
     * The motif caret is rendered as an I beam.
     * <p>
     * <strong>Warning:</strong>
     * Serialized objects of this class will not be compatible with
     * future Swing releases.  The current serialization support is appropriate
     * for short term storage or RMI between applications running the same
     * version of Swing.  A future release of Swing will provide support for
     * long term persistence.
     */
    public static class MotifCaret extends DefaultCaret implements UIResource {

        /**
         * Called when the component containing the caret gains
         * focus.  This is implemented to repaint the component
         * so the focus rectangle will be re-rendered, as well
         * as providing the superclass behavior.
         *
         * @param e the focus event
         * @see FocusListener#focusGained
         */
        public void focusGained(FocusEvent e) {
            super.focusGained(e);
            getComponent().repaint();
        }

        /**
         * Called when the component containing the caret loses
         * focus.  This is implemented to set the caret to visibility
         * to false.
         *
         * @param e the focus event
         * @see FocusListener#focusLost
         */
        public void focusLost(FocusEvent e) {
            super.focusLost(e);
            getComponent().repaint();
        }

        /**
         * Damages the area surrounding the caret to cause
         * it to be repainted.  If paint() is reimplemented,
         * this method should also be reimplemented.
         *
         * @param r  the current location of the caret, does nothing if null
         * @see #paint
         */
        protected void damage(Rectangle r) {
            if (r != null) {
                x = r.x - IBeamOverhang - 1;
                y = r.y;
                width = r.width + (2 * IBeamOverhang) + 3;
                height = r.height;
                repaint();
            }
        }

        /**
         * Renders the caret as a vertical line.  If this is reimplemented
         * the damage method should also be reimplemented as it assumes the
         * shape of the caret is a vertical line.  Does nothing if isVisible()
         * is false.  The caret color is derived from getCaretColor() if
         * the component has focus, else from getDisabledTextColor().
         *
         * @param g the graphics context
         * @see #damage
         */
        public void paint(Graphics g) {
            if(isVisible()) {
                try {
                    JTextComponent c = getComponent();
                    Color fg = c.hasFocus() ? c.getCaretColor() :
                        c.getDisabledTextColor();
                    TextUI mapper = c.getUI();
                    int dot = getDot();
                    Rectangle r = mapper.modelToView(c, dot);
                    int x0 = r.x - IBeamOverhang;
                    int x1 = r.x + IBeamOverhang;
                    int y0 = r.y + 1;
                    int y1 = r.y + r.height - 2;
                    g.setColor(fg);
                    g.drawLine(r.x, y0, r.x, y1);
                    g.drawLine(x0, y0, x1, y0);
                    g.drawLine(x0, y1, x1, y1);
                } catch (BadLocationException e) {
                    // can't render I guess
                    //System.err.println("Can't render caret");
                }
            }
        }

        static final int IBeamOverhang = 2;
    }

    /**
     * Default bindings all keymaps implementing the Motif feel.
     */
    static final JTextComponent.KeyBinding[] defaultBindings = {
        new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,
                                                                    InputEvent.CTRL_MASK),
                                             DefaultEditorKit.copyAction),
        new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT,
                                                                    InputEvent.SHIFT_MASK),
                                             DefaultEditorKit.pasteAction),
        new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,
                                                                    InputEvent.SHIFT_MASK),
                                             DefaultEditorKit.cutAction),
        new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,
                                                                    InputEvent.SHIFT_MASK),
                                             DefaultEditorKit.selectionBackwardAction),
        new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,
                                                                    InputEvent.SHIFT_MASK),
                                             DefaultEditorKit.selectionForwardAction),
    };


}
