1 /*
2 * Copyright (c) 2002, 2014, 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.plaf.*;
31 import javax.swing.plaf.basic.BasicTextFieldUI;
32 import java.awt.*;
33 import java.awt.event.FocusEvent;
34 import java.awt.event.FocusListener;
35 import java.beans.PropertyChangeEvent;
36
37
38 /**
39 * Provides the Synth L&F UI delegate for {@link javax.swing.JTextField}.
40 * <p>
41 * <strong>Warning:</strong>
42 * Serialized objects of this class will not be compatible with
43 * future Swing releases. The current serialization support is
44 * appropriate for short term storage or RMI between applications running
45 * the same version of Swing. As of 1.4, support for long term storage
46 * of all JavaBeans™
47 * has been added to the <code>java.beans</code> package.
48 * Please see {@link java.beans.XMLEncoder}.
49 *
50 * @author Shannon Hickey
51 * @since 1.7
52 */
53 @SuppressWarnings("serial") // Same-version serialization only
54 public class SynthTextFieldUI extends BasicTextFieldUI implements SynthUI {
55 private Handler handler = new Handler();
56 private SynthStyle style;
57
58 /**
59 * Creates a UI for a JTextField.
60 *
61 * @param c the text field
62 * @return the UI object
63 */
64 public static ComponentUI createUI(JComponent c) {
65 return new SynthTextFieldUI();
66 }
67
68 private void updateStyle(JTextComponent comp) {
69 SynthContext context = getContext(comp, ENABLED);
70 SynthStyle oldStyle = style;
71
72 style = SynthLookAndFeel.updateStyle(context, this);
73
74 if (style != oldStyle) {
75 SynthTextFieldUI.updateStyle(comp, context, getPropertyPrefix());
76
77 if (oldStyle != null) {
78 uninstallKeyboardActions();
79 installKeyboardActions();
80 }
81 }
82 context.dispose();
83 }
84
85 static void updateStyle(JTextComponent comp, SynthContext context,
86 String prefix) {
87 SynthStyle style = context.getStyle();
88
89 Color color = comp.getCaretColor();
90 if (color == null || color instanceof UIResource) {
91 comp.setCaretColor(
92 (Color)style.get(context, prefix + ".caretForeground"));
93 }
94
95 Color fg = comp.getForeground();
96 if (fg == null || fg instanceof UIResource) {
97 fg = style.getColorForState(context, ColorType.TEXT_FOREGROUND);
98 if (fg != null) {
99 comp.setForeground(fg);
100 }
101 }
102
103 Object ar = style.get(context, prefix + ".caretAspectRatio");
104 if (ar instanceof Number) {
105 comp.putClientProperty("caretAspectRatio", ar);
106 }
107
108 context.setComponentState(SELECTED | FOCUSED);
109
110 Color s = comp.getSelectionColor();
111 if (s == null || s instanceof UIResource) {
112 comp.setSelectionColor(
113 style.getColor(context, ColorType.TEXT_BACKGROUND));
114 }
115
116 Color sfg = comp.getSelectedTextColor();
117 if (sfg == null || sfg instanceof UIResource) {
118 comp.setSelectedTextColor(
119 style.getColor(context, ColorType.TEXT_FOREGROUND));
120 }
121
122 context.setComponentState(DISABLED);
123
124 Color dfg = comp.getDisabledTextColor();
125 if (dfg == null || dfg instanceof UIResource) {
126 comp.setDisabledTextColor(
127 style.getColor(context, ColorType.TEXT_FOREGROUND));
128 }
129
130 Insets margin = comp.getMargin();
131 if (margin == null || margin instanceof UIResource) {
132 margin = (Insets)style.get(context, prefix + ".margin");
133
134 if (margin == null) {
135 // Some places assume margins are non-null.
136 margin = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
137 }
138 comp.setMargin(margin);
139 }
140
141 Caret caret = comp.getCaret();
142 if (caret instanceof UIResource) {
143 Object o = style.get(context, prefix + ".caretBlinkRate");
144 if (o != null && o instanceof Integer) {
145 Integer rate = (Integer)o;
146 caret.setBlinkRate(rate.intValue());
147 }
148 }
149 }
150
151 /**
152 * {@inheritDoc}
153 */
154 @Override
155 public SynthContext getContext(JComponent c) {
156 return getContext(c, SynthLookAndFeel.getComponentState(c));
157 }
158
159 private SynthContext getContext(JComponent c, int state) {
160 return SynthContext.getContext(c, style, state);
161 }
162
163 /**
164 * Notifies this UI delegate to repaint the specified component.
165 * This method paints the component background, then calls
166 * the {@link #paint(SynthContext,Graphics)} method.
167 *
168 * <p>In general, this method does not need to be overridden by subclasses.
169 * All Look and Feel rendering code should reside in the {@code paint} method.
170 *
171 * @param g the {@code Graphics} object used for painting
172 * @param c the component being painted
173 * @see #paint(SynthContext,Graphics)
174 */
175 @Override
176 public void update(Graphics g, JComponent c) {
177 SynthContext context = getContext(c);
178
179 SynthLookAndFeel.update(context, g);
180 paintBackground(context, g, c);
181 paint(context, g);
182 context.dispose();
183 }
184
185 /**
186 * Paints the specified component.
187 * <p>This is routed to the {@link #paintSafely} method under
188 * the guarantee that the model does not change from the view of this
189 * thread while it is rendering (if the associated model is
190 * derived from {@code AbstractDocument}). This enables the
191 * model to potentially be updated asynchronously.
192 *
193 * @param context context for the component being painted
194 * @param g the {@code Graphics} object used for painting
195 * @see #update(Graphics,JComponent)
196 */
197 protected void paint(SynthContext context, Graphics g) {
198 super.paint(g, getComponent());
199 }
200
201 void paintBackground(SynthContext context, Graphics g, JComponent c) {
202 context.getPainter().paintTextFieldBackground(context, g, 0, 0,
203 c.getWidth(), c.getHeight());
204 }
205
206 /**
207 * {@inheritDoc}
208 */
209 @Override
210 public void paintBorder(SynthContext context, Graphics g, int x,
211 int y, int w, int h) {
212 context.getPainter().paintTextFieldBorder(context, g, x, y, w, h);
213 }
214
215 /**
216 * {@inheritDoc}
217 * Overridden to do nothing.
218 */
219 @Override
220 protected void paintBackground(Graphics g) {
221 // Overriden to do nothing, all our painting is done from update/paint.
222 }
223
224 /**
225 * This method gets called when a bound property is changed
226 * on the associated JTextComponent. This is a hook
227 * which UI implementations may change to reflect how the
228 * UI displays bound properties of JTextComponent subclasses.
229 * This is implemented to do nothing (i.e. the response to
230 * properties in JTextComponent itself are handled prior
231 * to calling this method).
232 *
233 * @param evt the property change event
234 */
235 @Override
236 protected void propertyChange(PropertyChangeEvent evt) {
237 if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
238 updateStyle((JTextComponent)evt.getSource());
239 }
240 super.propertyChange(evt);
241 }
242
243 /**
244 * {@inheritDoc}
245 */
246 @Override
247 protected void installDefaults() {
248 // Installs the text cursor on the component
249 super.installDefaults();
250 updateStyle(getComponent());
251 getComponent().addFocusListener(handler);
252 }
253
254 /**
255 * {@inheritDoc}
256 */
257 @Override
258 protected void uninstallDefaults() {
259 SynthContext context = getContext(getComponent(), ENABLED);
260
261 getComponent().putClientProperty("caretAspectRatio", null);
262 getComponent().removeFocusListener(handler);
263
264 style.uninstallDefaults(context);
265 context.dispose();
266 style = null;
267 super.uninstallDefaults();
268 }
269
270 private final class Handler implements FocusListener {
271 public void focusGained(FocusEvent e) {
272 getComponent().repaint();
273 }
274
275 public void focusLost(FocusEvent e) {
276 getComponent().repaint();
277 }
278 }
279 }
--- EOF ---