1 /*
   2  * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing.plaf.synth;
  27 
  28 import javax.swing.*;
  29 import javax.swing.text.*;
  30 import javax.swing.event.*;
  31 import javax.swing.plaf.*;
  32 import javax.swing.plaf.basic.BasicTextFieldUI;
  33 import java.awt.*;
  34 import java.awt.event.FocusEvent;
  35 import java.awt.event.FocusListener;
  36 import java.beans.PropertyChangeEvent;
  37 
  38 import sun.swing.plaf.synth.SynthUI;
  39 
  40 /**
  41  * Basis of a look and feel for a JTextField in the Synth
  42  * look and feel.
  43  * <p>
  44  * <strong>Warning:</strong>
  45  * Serialized objects of this class will not be compatible with
  46  * future Swing releases. The current serialization support is
  47  * appropriate for short term storage or RMI between applications running
  48  * the same version of Swing.  As of 1.4, support for long term storage
  49  * of all JavaBeans<sup><font size="-2">TM</font></sup>
  50  * has been added to the <code>java.beans</code> package.
  51  * Please see {@link java.beans.XMLEncoder}.
  52  *
  53  * @author  Shannon Hickey
  54  */
  55 class SynthTextFieldUI
  56     extends BasicTextFieldUI
  57     implements SynthUI, FocusListener
  58 {
  59     private SynthStyle style;
  60 
  61     /**
  62      * Creates a UI for a JTextField.
  63      *
  64      * @param c the text field
  65      * @return the UI
  66      */
  67     public static ComponentUI createUI(JComponent c) {
  68         return new SynthTextFieldUI();
  69     }
  70 
  71     public SynthTextFieldUI() {
  72         super();
  73     }
  74 
  75     private void updateStyle(JTextComponent comp) {
  76         SynthContext context = getContext(comp, ENABLED);
  77         SynthStyle oldStyle = style;
  78 
  79         style = SynthLookAndFeel.updateStyle(context, this);
  80 
  81         if (style != oldStyle) {
  82             SynthTextFieldUI.updateStyle(comp, context, getPropertyPrefix());
  83 
  84             if (oldStyle != null) {
  85                 uninstallKeyboardActions();
  86                 installKeyboardActions();
  87             }
  88         }
  89         context.dispose();
  90     }
  91 
  92     static void updateStyle(JTextComponent comp, SynthContext context,
  93             String prefix) {
  94         SynthStyle style = context.getStyle();
  95 
  96         Color color = comp.getCaretColor();
  97         if (color == null || color instanceof UIResource) {
  98             comp.setCaretColor(
  99                 (Color)style.get(context, prefix + ".caretForeground"));
 100         }
 101 
 102         Color fg = comp.getForeground();
 103         if (fg == null || fg instanceof UIResource) {
 104             fg = style.getColorForState(context, ColorType.TEXT_FOREGROUND);
 105             if (fg != null) {
 106                 comp.setForeground(fg);
 107             }
 108         }
 109 
 110         Object ar = style.get(context, prefix + ".caretAspectRatio");
 111         if (ar instanceof Number) {
 112             comp.putClientProperty("caretAspectRatio", ar);
 113         }
 114 
 115         context.setComponentState(SELECTED | FOCUSED);
 116 
 117         Color s = comp.getSelectionColor();
 118         if (s == null || s instanceof UIResource) {
 119             comp.setSelectionColor(
 120                 style.getColor(context, ColorType.TEXT_BACKGROUND));
 121         }
 122 
 123         Color sfg = comp.getSelectedTextColor();
 124         if (sfg == null || sfg instanceof UIResource) {
 125             comp.setSelectedTextColor(
 126                 style.getColor(context, ColorType.TEXT_FOREGROUND));
 127         }
 128 
 129         context.setComponentState(DISABLED);
 130 
 131         Color dfg = comp.getDisabledTextColor();
 132         if (dfg == null || dfg instanceof UIResource) {
 133             comp.setDisabledTextColor(
 134                 style.getColor(context, ColorType.TEXT_FOREGROUND));
 135         }
 136 
 137         Insets margin = comp.getMargin();
 138         if (margin == null || margin instanceof UIResource) {
 139             margin = (Insets)style.get(context, prefix + ".margin");
 140 
 141             if (margin == null) {
 142                 // Some places assume margins are non-null.
 143                 margin = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
 144             }
 145             comp.setMargin(margin);
 146         }
 147 
 148         Caret caret = comp.getCaret();
 149         if (caret instanceof UIResource) {
 150             Object o = style.get(context, prefix + ".caretBlinkRate");
 151             if (o != null && o instanceof Integer) {
 152                 Integer rate = (Integer)o;
 153                 caret.setBlinkRate(rate.intValue());
 154             }
 155         }
 156     }
 157 
 158     public SynthContext getContext(JComponent c) {
 159         return getContext(c, getComponentState(c));
 160     }
 161 
 162     private SynthContext getContext(JComponent c, int state) {
 163         return SynthContext.getContext(SynthContext.class, c,
 164                     SynthLookAndFeel.getRegion(c), style, state);
 165     }
 166 
 167     private int getComponentState(JComponent c) {
 168         return SynthLookAndFeel.getComponentState(c);
 169     }
 170 
 171     public void update(Graphics g, JComponent c) {
 172         SynthContext context = getContext(c);
 173 
 174         SynthLookAndFeel.update(context, g);
 175         paintBackground(context, g, c);
 176         paint(context, g);
 177         context.dispose();
 178     }
 179 
 180     /**
 181      * Paints the interface.  This is routed to the
 182      * paintSafely method under the guarantee that
 183      * the model won't change from the view of this thread
 184      * while it's rendering (if the associated model is
 185      * derived from AbstractDocument).  This enables the
 186      * model to potentially be updated asynchronously.
 187      */
 188     protected void paint(SynthContext context, Graphics g) {
 189         super.paint(g, getComponent());
 190     }
 191 
 192     void paintBackground(SynthContext context, Graphics g, JComponent c) {
 193         context.getPainter().paintTextFieldBackground(context, g, 0, 0,
 194                                                 c.getWidth(), c.getHeight());
 195     }
 196 
 197     public void paintBorder(SynthContext context, Graphics g, int x,
 198                             int y, int w, int h) {
 199         context.getPainter().paintTextFieldBorder(context, g, x, y, w, h);
 200     }
 201 
 202     protected void paintBackground(Graphics g) {
 203         // Overriden to do nothing, all our painting is done from update/paint.
 204     }
 205 
 206     /**
 207      * This method gets called when a bound property is changed
 208      * on the associated JTextComponent.  This is a hook
 209      * which UI implementations may change to reflect how the
 210      * UI displays bound properties of JTextComponent subclasses.
 211      * This is implemented to do nothing (i.e. the response to
 212      * properties in JTextComponent itself are handled prior
 213      * to calling this method).
 214      *
 215      * @param evt the property change event
 216      */
 217     protected void propertyChange(PropertyChangeEvent evt) {
 218         if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
 219             updateStyle((JTextComponent)evt.getSource());
 220         }
 221         super.propertyChange(evt);
 222     }
 223 
 224     public void focusGained(FocusEvent e) {
 225         getComponent().repaint();
 226     }
 227 
 228     public void focusLost(FocusEvent e) {
 229         getComponent().repaint();
 230     }
 231 
 232     protected void installDefaults() {
 233         // Installs the text cursor on the component
 234         super.installDefaults();
 235         updateStyle((JTextComponent)getComponent());
 236         getComponent().addFocusListener(this);
 237     }
 238 
 239     protected void uninstallDefaults() {
 240         SynthContext context = getContext(getComponent(), ENABLED);
 241 
 242         getComponent().putClientProperty("caretAspectRatio", null);
 243         getComponent().removeFocusListener(this);
 244 
 245         style.uninstallDefaults(context);
 246         context.dispose();
 247         style = null;
 248         super.uninstallDefaults();
 249     }
 250 
 251     public void installUI(JComponent c) {
 252         super.installUI(c);
 253     }
 254 }