jdk/src/solaris/classes/sun/awt/X11/XTextFieldPeer.java
changeset 2 90ce3da70b43
child 3938 ef327bd847c0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTextFieldPeer.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,729 @@
+/*
+ * Copyright 2003-2007 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 sun.awt.X11;
+
+import java.awt.*;
+import java.awt.peer.*;
+import java.awt.event.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.TextEvent;
+import javax.swing.text.*;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.InputMap;
+import javax.swing.JPasswordField;
+import javax.swing.SwingUtilities;
+import javax.swing.TransferHandler;
+
+import java.awt.event.MouseEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.plaf.UIResource;
+import javax.swing.UIDefaults;
+import javax.swing.JTextField;
+import javax.swing.JComponent;
+import javax.swing.border.Border;
+import com.sun.java.swing.plaf.motif.*;
+import java.awt.im.InputMethodRequests;
+
+import java.util.logging.*;
+import sun.awt.CausedFocusEvent;
+import sun.awt.ComponentAccessor;
+
+public class XTextFieldPeer extends XComponentPeer implements TextFieldPeer {
+    private static final Logger log = Logger.getLogger("sun.awt.X11.XTextField");
+
+    String text;
+    XAWTTextField xtext;
+
+    boolean firstChangeSkipped;
+
+    public XTextFieldPeer(TextField target) {
+        super(target);
+        int start, end;
+        firstChangeSkipped = false;
+        text = target.getText();
+        xtext = new XAWTTextField(text,this, target.getParent());
+        xtext.getDocument().addDocumentListener(xtext);
+        xtext.setCursor(target.getCursor());
+        target.enableInputMethods(true);
+        xtext.enableInputMethods(true);
+        XToolkit.specialPeerMap.put(xtext,this);
+
+        TextField txt = (TextField) target;
+        initTextField();
+        setText(txt.getText());
+        if (txt.echoCharIsSet()) {
+            setEchoChar(txt.getEchoChar());
+        }
+        else setEchoChar((char)0);
+
+        start = txt.getSelectionStart();
+        end = txt.getSelectionEnd();
+
+        if (end > start) {
+            select(start, end);
+        }
+        // Fix for 5100200
+        // Restoring Motif behaviour
+        // Since the end position of the selected text can be greater then the length of the text,
+        // so we should set caret to max position of the text
+        int caretPosition = Math.min(end, text.length());
+        setCaretPosition(caretPosition);
+
+        setEditable(txt.isEditable());
+
+        // After this line we should not change the component's text
+        firstChangeSkipped = true;
+    }
+
+    public void dispose() {
+        XToolkit.specialPeerMap.remove(xtext);
+        xtext.removeNotify();
+        super.dispose();
+    }
+
+    void initTextField() {
+        setVisible(target.isVisible());
+
+        setBounds(x, y, width, height, SET_BOUNDS);
+
+        foreground = ComponentAccessor.getForeground(target);
+        if (foreground == null)
+            foreground = SystemColor.textText;
+
+        setForeground(foreground);
+
+        background = ComponentAccessor.getBackground(target);
+        if (background == null) {
+            if (((TextField)target).isEditable()) background = SystemColor.text;
+            else background = SystemColor.control;
+        }
+        setBackground(background);
+
+        if (!target.isBackgroundSet()) {
+            // This is a way to set the background color of the TextArea
+            // without calling setBackground - go through reflection
+            ComponentAccessor.setBackground(target, background);
+        }
+        if (!target.isForegroundSet()) {
+            target.setForeground(SystemColor.textText);
+        }
+
+        setFont(font);
+    }
+
+
+    /**
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public void setEditable(boolean editable) {
+        if (xtext != null) {
+            xtext.setEditable(editable);
+            xtext.repaint();
+        }
+    }
+
+    /**
+     * @see java.awt.peer.ComponentPeer
+     */
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+        if (xtext != null) {
+            xtext.setEnabled(enabled);
+            xtext.repaint();
+        }
+    }
+
+    /**
+     * @see java.awt.peer.TextComponentPeer
+     */
+
+    public InputMethodRequests getInputMethodRequests() {
+        if (xtext != null) return xtext.getInputMethodRequests();
+        else  return null;
+
+    }
+
+    void handleJavaInputMethodEvent(InputMethodEvent e) {
+        if (xtext != null)
+            xtext.processInputMethodEventImpl(e);
+    }
+
+
+    /**
+     * @see java.awt.peer.TextFieldPeer
+     */
+    public void setEchoChar(char c) {
+        if (xtext != null) {
+            xtext.setEchoChar(c);
+            xtext.putClientProperty("JPasswordField.cutCopyAllowed",
+                    xtext.echoCharIsSet() ? Boolean.FALSE : Boolean.TRUE);
+        }
+    }
+
+    /**
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public int getSelectionStart() {
+        return xtext.getSelectionStart();
+    }
+
+    /**
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public int getSelectionEnd() {
+        return xtext.getSelectionEnd();
+    }
+
+    /**
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public String getText() {
+        return xtext.getText();
+    }
+
+    /**
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public void setText(String txt) {
+        setXAWTTextField(txt);
+        repaint();
+    }
+
+    protected boolean setXAWTTextField(String txt) {
+        text = txt;
+        if (xtext != null)  {
+            // JTextField.setText() posts two different events (remove & insert).
+            // Since we make no differences between text events,
+            // the document listener has to be disabled while
+            // JTextField.setText() is called.
+            xtext.getDocument().removeDocumentListener(xtext);
+            xtext.setText(txt);
+            if (firstChangeSkipped) {
+                postEvent(new TextEvent(target, TextEvent.TEXT_VALUE_CHANGED));
+            }
+            xtext.getDocument().addDocumentListener(xtext);
+            xtext.setCaretPosition(0);
+        }
+        return true;
+    }
+
+    /**
+     * to be implemented.
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public void setCaretPosition(int position) {
+        if (xtext != null) xtext.setCaretPosition(position);
+    }
+
+    /**
+     * DEPRECATED
+     * @see java.awt.peer.TextFieldPeer
+     */
+    public void setEchoCharacter(char c) {
+        setEchoChar(c);
+    }
+
+    void repaintText() {
+        xtext.repaintNow();
+    }
+
+    public void setBackground(Color c) {
+        if (log.isLoggable(Level.FINE)) log.fine("target="+ target + ", old=" + background + ", new=" + c);
+        background = c;
+        if (xtext != null) {
+            xtext.setBackground(c);
+            xtext.setSelectedTextColor(c);
+        }
+        repaintText();
+    }
+
+    public void setForeground(Color c) {
+        foreground = c;
+        if (xtext != null) {
+            xtext.setForeground(foreground);
+            xtext.setSelectionColor(foreground);
+            xtext.setCaretColor(foreground);
+        }
+        repaintText();
+    }
+
+    public void setFont(Font f) {
+        synchronized (getStateLock()) {
+            font = f;
+            if (xtext != null) {
+                xtext.setFont(font);
+            }
+        }
+        xtext.validate();
+    }
+
+    /**
+     * DEPRECATED
+     * @see java.awt.peer.TextFieldPeer
+     */
+    public Dimension preferredSize(int cols) {
+        return getPreferredSize(cols);
+    }
+
+    /**
+     * Deselects the the highlighted text.
+     */
+    public void deselect() {
+        int selStart=xtext.getSelectionStart();
+        int selEnd=xtext.getSelectionEnd();
+        if (selStart != selEnd) {
+            xtext.select(selStart,selStart);
+        }
+    }
+
+
+    /**
+     * to be implemented.
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public int getCaretPosition() {
+        return xtext.getCaretPosition();
+    }
+
+
+
+    /**
+     * @see java.awt.peer.TextComponentPeer
+     */
+    public void select(int s, int e) {
+        xtext.select(s,e);
+        // Fixed 5100806
+        // We must take care that Swing components repainted correctly
+        xtext.repaint();
+    }
+
+
+    public Dimension getMinimumSize() {
+        return xtext.getMinimumSize();
+    }
+
+    public Dimension getPreferredSize() {
+        return xtext.getPreferredSize();
+    }
+
+    public Dimension getPreferredSize(int cols) {
+        return getMinimumSize(cols);
+    }
+
+    private static final int PADDING = 16;
+
+    public Dimension getMinimumSize(int cols) {
+        Font f = xtext.getFont();
+        FontMetrics fm = xtext.getFontMetrics(f);
+        return new Dimension(fm.charWidth('0') * cols + 10,
+                             fm.getMaxDescent() + fm.getMaxAscent() + PADDING);
+
+    }
+
+    public boolean isFocusable() {
+        return true;
+    }
+
+    // NOTE: This method is called by privileged threads.
+    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
+    public void action(final long when, final int modifiers) {
+        postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
+                                  text, when,
+                                  modifiers));
+    }
+
+
+    protected void disposeImpl() {
+    }
+
+
+    public void repaint() {
+        if (xtext  != null) xtext.repaint();
+    }
+
+    public void paint(Graphics g) {
+        if (xtext  != null) xtext.paint(g);
+    }
+
+
+    public void print(Graphics g) {
+        if (xtext != null) {
+            xtext.print(g);
+        }
+    }
+
+    public void focusLost(FocusEvent e) {
+        super.focusLost(e);
+        xtext.forwardFocusLost(e);
+    }
+
+    public void focusGained(FocusEvent e) {
+        super.focusGained(e);
+        xtext.forwardFocusGained(e);
+    }
+
+    void handleJavaKeyEvent(KeyEvent e) {
+        ComponentAccessor.processEvent(xtext,e);
+    }
+
+
+    public void handleJavaMouseEvent( MouseEvent mouseEvent ) {
+        super.handleJavaMouseEvent(mouseEvent);
+        if (xtext != null)  {
+            mouseEvent.setSource(xtext);
+            int id = mouseEvent.getID();
+            if (id == MouseEvent.MOUSE_DRAGGED || id == MouseEvent.MOUSE_MOVED)
+                xtext.processMouseMotionEventImpl(mouseEvent);
+            else
+                xtext.processMouseEventImpl(mouseEvent);
+        }
+    }
+
+
+    /**
+     * DEPRECATED
+     */
+    public Dimension minimumSize() {
+        return getMinimumSize();
+    }
+
+    /**
+     * DEPRECATED
+     */
+    public Dimension minimumSize(int cols) {
+        return getMinimumSize(cols);
+    }
+
+    public void setVisible(boolean b) {
+        super.setVisible(b);
+        if (xtext != null) xtext.setVisible(b);
+    }
+
+    public void setBounds(int x, int y, int width, int height, int op) {
+        super.setBounds(x, y, width, height, op);
+        if (xtext != null) {
+            /*
+             * Fixed 6277332, 6198290:
+             * the coordinates is coming (to peer): relatively to closest HW parent
+             * the coordinates is setting (to textField): relatively to closest ANY parent
+             * the parent of peer is target.getParent()
+             * the parent of textField is the same
+             * see 6277332, 6198290 for more information
+             */
+            int childX = x;
+            int childY = y;
+            Component parent = target.getParent();
+            // we up to heavyweight parent in order to be sure
+            // that the coordinates of the text pane is relatively to closest parent
+            while (parent.isLightweight()){
+                childX -= parent.getX();
+                childY -= parent.getY();
+                parent = parent.getParent();
+            }
+            xtext.setBounds(childX,childY,width,height);
+            xtext.validate();
+        }
+    }
+
+
+    //
+    // Accessibility support
+    //
+
+    // stub functions: to be fully implemented in a future release
+    public int getIndexAtPoint(int x, int y) { return -1; }
+    public Rectangle getCharacterBounds(int i) { return null; }
+    public long filterEvents(long mask) { return 0; }
+
+
+    /*  To be fully implemented in a future release
+
+        int oldSelectionStart;
+        int oldSelectionEnd;
+
+        public native int getIndexAtPoint(int x, int y);
+        public native Rectangle getCharacterBounds(int i);
+        public native long filterEvents(long mask);
+
+        /**
+         * Handle a change in the text selection endpoints
+         * (Note: could be simply a change in the caret location)
+         *
+         public void selectionValuesChanged(int start, int end) {
+         return;  // Need to write implemetation of this.
+         }
+    */
+
+
+    class  AWTTextFieldUI extends MotifPasswordFieldUI {
+
+        /**
+         * Creates a UI for a JTextField.
+         *
+         * @param c the text field
+         * @return the UI
+         */
+        JTextField jtf;
+
+
+        protected String getPropertyPrefix() {
+            JTextComponent comp = getComponent();
+            if (comp instanceof JPasswordField && ((JPasswordField)comp).echoCharIsSet()) {
+                return "PasswordField";
+            } else {
+                return "TextField";
+            }
+        }
+
+        public void installUI(JComponent c) {
+            super.installUI(c);
+
+            jtf = (JTextField) c;
+
+            JTextField editor = jtf;
+
+            UIDefaults uidefaults = XToolkit.getUIDefaults();
+
+            String prefix = getPropertyPrefix();
+            Font f = editor.getFont();
+            if ((f == null) || (f instanceof UIResource)) {
+                editor.setFont(uidefaults.getFont(prefix + ".font"));
+            }
+
+            Color bg = editor.getBackground();
+            if ((bg == null) || (bg instanceof UIResource)) {
+                editor.setBackground(uidefaults.getColor(prefix + ".background"));
+            }
+
+            Color fg = editor.getForeground();
+            if ((fg == null) || (fg instanceof UIResource)) {
+                editor.setForeground(uidefaults.getColor(prefix + ".foreground"));
+            }
+
+            Color color = editor.getCaretColor();
+            if ((color == null) || (color instanceof UIResource)) {
+                editor.setCaretColor(uidefaults.getColor(prefix + ".caretForeground"));
+            }
+
+            Color s = editor.getSelectionColor();
+            if ((s == null) || (s instanceof UIResource)) {
+                editor.setSelectionColor(uidefaults.getColor(prefix + ".selectionBackground"));
+            }
+
+            Color sfg = editor.getSelectedTextColor();
+            if ((sfg == null) || (sfg instanceof UIResource)) {
+                editor.setSelectedTextColor(uidefaults.getColor(prefix + ".selectionForeground"));
+            }
+
+            Color dfg = editor.getDisabledTextColor();
+            if ((dfg == null) || (dfg instanceof UIResource)) {
+                editor.setDisabledTextColor(uidefaults.getColor(prefix + ".inactiveForeground"));
+            }
+
+            Border b = editor.getBorder();
+            if ((b == null) || (b instanceof UIResource)) {
+                editor.setBorder(uidefaults.getBorder(prefix + ".border"));
+            }
+
+            Insets margin = editor.getMargin();
+            if (margin == null || margin instanceof UIResource) {
+                editor.setMargin(uidefaults.getInsets(prefix + ".margin"));
+            }
+        }
+
+        protected void installKeyboardActions() {
+            super.installKeyboardActions();
+
+            JTextComponent comp = getComponent();
+
+            UIDefaults uidefaults = XToolkit.getUIDefaults();
+
+            String prefix = getPropertyPrefix();
+
+            InputMap map = (InputMap)uidefaults.get(prefix + ".focusInputMap");
+
+            if (map != null) {
+                SwingUtilities.replaceUIInputMap(comp, JComponent.WHEN_FOCUSED,
+                                                 map);
+            }
+        }
+
+        protected Caret createCaret() {
+            return new XAWTCaret();
+        }
+    }
+
+    class XAWTCaret extends DefaultCaret {
+        public void focusGained(FocusEvent e) {
+            super.focusGained(e);
+            getComponent().repaint();
+        }
+
+        public void focusLost(FocusEvent e) {
+            super.focusLost(e);
+            getComponent().repaint();
+        }
+
+        // Fix for 5100950: textarea.getSelectedText() returns the de-selected text, on XToolkit
+        // Restoring Motif behaviour
+        // If the text is unhighlighted then we should sets the selection range to zero
+        public void setSelectionVisible(boolean vis) {
+            if (vis){
+                super.setSelectionVisible(vis);
+            }else{
+                // In order to de-select the selection
+                setDot(getDot());
+            }
+        }
+    }
+
+    class XAWTTextField extends JPasswordField
+        implements ActionListener,
+                   DocumentListener
+    {
+
+        boolean isFocused = false;
+
+        XComponentPeer peer;
+
+        public XAWTTextField(String text, XComponentPeer peer, Container parent) {
+            super(text);
+            this.peer = peer;
+            setDoubleBuffered(true);
+            setFocusable(false);
+            ComponentAccessor.setParent(this,parent);
+            setBackground(peer.getPeerBackground());
+            setForeground(peer.getPeerForeground());
+            setFont(peer.getPeerFont());
+            setCaretPosition(0);
+            addActionListener(this);
+            addNotify();
+
+        }
+
+        public void actionPerformed( ActionEvent actionEvent ) {
+            peer.postEvent(new ActionEvent(peer.target,
+                                           ActionEvent.ACTION_PERFORMED,
+                                           getText(),
+                                           actionEvent.getWhen(),
+                                           actionEvent.getModifiers()));
+
+        }
+
+        public void insertUpdate(DocumentEvent e) {
+            if (peer != null) {
+                peer.postEvent(new TextEvent(peer.target,
+                                             TextEvent.TEXT_VALUE_CHANGED));
+            }
+        }
+
+        public void removeUpdate(DocumentEvent e) {
+            if (peer != null) {
+                peer.postEvent(new TextEvent(peer.target,
+                                             TextEvent.TEXT_VALUE_CHANGED));
+            }
+        }
+
+        public void changedUpdate(DocumentEvent e) {
+            if (peer != null) {
+                peer.postEvent(new TextEvent(peer.target,
+                                             TextEvent.TEXT_VALUE_CHANGED));
+            }
+        }
+
+        public ComponentPeer getPeer() {
+            return (ComponentPeer) peer;
+        }
+
+
+        public void repaintNow() {
+            paintImmediately(getBounds());
+        }
+
+        public Graphics getGraphics() {
+            return peer.getGraphics();
+        }
+
+        public void updateUI() {
+            ComponentUI ui = new AWTTextFieldUI();
+            setUI(ui);
+        }
+
+
+        void forwardFocusGained( FocusEvent e) {
+            isFocused = true;
+            FocusEvent fe = CausedFocusEvent.retarget(e, this);
+            super.processFocusEvent(fe);
+
+        }
+
+
+        void forwardFocusLost( FocusEvent e) {
+            isFocused = false;
+            FocusEvent fe = CausedFocusEvent.retarget(e, this);
+            super.processFocusEvent(fe);
+
+        }
+
+        public boolean hasFocus() {
+            return isFocused;
+        }
+
+
+        public void processInputMethodEventImpl(InputMethodEvent e) {
+            processInputMethodEvent(e);
+        }
+
+        public void processMouseEventImpl(MouseEvent e) {
+            processMouseEvent(e);
+        }
+
+        public void processMouseMotionEventImpl(MouseEvent e) {
+            processMouseMotionEvent(e);
+        }
+
+        // Fix for 4915454 - override the default implementation to avoid
+        // loading SystemFlavorMap and associated classes.
+        public void setTransferHandler(TransferHandler newHandler) {
+            TransferHandler oldHandler = (TransferHandler)
+                getClientProperty(XTextTransferHelper.getTransferHandlerKey());
+            putClientProperty(XTextTransferHelper.getTransferHandlerKey(),
+                              newHandler);
+
+            firePropertyChange("transferHandler", oldHandler, newHandler);
+        }
+
+        public void setEchoChar(char c) {
+            super.setEchoChar(c);
+            ((AWTTextFieldUI)ui).installKeyboardActions();
+        }
+    }
+}