1 /*
2  * Copyright (c) 2002, 2013, 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 java.awt.*;
29 import javax.swing.*;
30 import javax.swing.text.*;
31 import javax.swing.plaf.*;
32 import javax.swing.plaf.basic.BasicEditorPaneUI;
33 import java.beans.PropertyChangeEvent;
34 
35 /**
36  * Provides the Synth L&F UI delegate for
37  * {@link javax.swing.JEditorPane}.
38  *
39  * @author  Shannon Hickey
40  * @since 1.7
41  */
42 public class SynthEditorPaneUI extends BasicEditorPaneUI implements SynthUI {
43     private SynthStyle style;
44     /*
45      * I would prefer to use UIResource instad of this.
46      * Unfortunately Boolean is a final class
47      */
48     private Boolean localTrue = Boolean.TRUE;
49 
50     private boolean updateKBAction = true;
51 
52     /**
53      * Creates a new UI object for the given component.
54      *
55      * @param c component to create UI object for
56      * @return the UI object
57      */
createUI(JComponent c)58     public static ComponentUI createUI(JComponent c) {
59         return new SynthEditorPaneUI();
60     }
61 
62     /**
63      * {@inheritDoc}
64      */
65     @Override
installDefaults()66     protected void installDefaults() {
67         // Installs the text cursor on the component
68         super.installDefaults();
69         JComponent c = getComponent();
70         Object clientProperty =
71             c.getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
72         if (clientProperty == null) {
73             c.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, localTrue);
74         }
75         updateStyle(getComponent(), true);
76     }
77 
78     /**
79      * {@inheritDoc}
80      */
81     @Override
uninstallDefaults()82     protected void uninstallDefaults() {
83         SynthContext context = getContext(getComponent(), ENABLED);
84         JComponent c = getComponent();
85         c.putClientProperty("caretAspectRatio", null);
86 
87         style.uninstallDefaults(context);
88         style = null;
89 
90         Object clientProperty =
91             c.getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
92         if (clientProperty == localTrue) {
93             c.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES,
94                                              Boolean.FALSE);
95         }
96         super.uninstallDefaults();
97     }
98 
99     /**
100      * This method gets called when a bound property is changed
101      * on the associated JTextComponent.  This is a hook
102      * which UI implementations may change to reflect how the
103      * UI displays bound properties of JTextComponent subclasses.
104      * This is implemented to rebuild the ActionMap based upon an
105      * EditorKit change.
106      *
107      * @param evt the property change event
108      */
109     @Override
propertyChange(PropertyChangeEvent evt)110     protected void propertyChange(PropertyChangeEvent evt) {
111 
112         if (evt.getPropertyName().equals("keymap")) {
113             if (evt.getNewValue() != null)
114             {
115                 updateKBAction = false;
116             } else {
117                 updateKBAction = true;
118             }
119         }
120         if (SynthLookAndFeel.shouldUpdateStyle(evt)) {
121             updateStyle((JTextComponent)evt.getSource(), updateKBAction);
122         }
123         super.propertyChange(evt);
124     }
125 
updateStyle(JTextComponent comp, boolean updateKBAction)126     private void updateStyle(JTextComponent comp, boolean updateKBAction) {
127         SynthContext context = getContext(comp, ENABLED);
128         SynthStyle oldStyle = style;
129 
130         style = SynthLookAndFeel.updateStyle(context, this);
131 
132         if (style != oldStyle) {
133             SynthTextFieldUI.updateStyle(comp, context, getPropertyPrefix());
134 
135             if (oldStyle != null && updateKBAction) {
136                 uninstallKeyboardActions();
137                 installKeyboardActions();
138             }
139         }
140     }
141 
142     /**
143      * {@inheritDoc}
144      */
145     @Override
getContext(JComponent c)146     public SynthContext getContext(JComponent c) {
147         return getContext(c, getComponentState(c));
148     }
149 
getContext(JComponent c, int state)150     private SynthContext getContext(JComponent c, int state) {
151         return SynthContext.getContext(c, style, state);
152     }
153 
getComponentState(JComponent c)154     private int getComponentState(JComponent c) {
155         return SynthLookAndFeel.getComponentState(c);
156     }
157 
158     /**
159      * Notifies this UI delegate to repaint the specified component.
160      * This method paints the component background, then calls
161      * the {@link #paint(SynthContext,Graphics)} method.
162      *
163      * <p>In general, this method does not need to be overridden by subclasses.
164      * All Look and Feel rendering code should reside in the {@code paint} method.
165      *
166      * @param g the {@code Graphics} object used for painting
167      * @param c the component being painted
168      * @see #paint(SynthContext,Graphics)
169      */
170     @Override
update(Graphics g, JComponent c)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     }
178 
179     /**
180      * Paints the specified component.
181      *
182      * @param context context for the component being painted
183      * @param g the {@code Graphics} object used for painting
184      * @see #update(Graphics,JComponent)
185      */
paint(SynthContext context, Graphics g)186     protected void paint(SynthContext context, Graphics g) {
187         super.paint(g, getComponent());
188     }
189 
190     /**
191      * {@inheritDoc}
192      */
193     @Override
paintBackground(Graphics g)194     protected void paintBackground(Graphics g) {
195         // Overriden to do nothing, all our painting is done from update/paint.
196     }
197 
paintBackground(SynthContext context, Graphics g, JComponent c)198     void paintBackground(SynthContext context, Graphics g, JComponent c) {
199         context.getPainter().paintEditorPaneBackground(context, g, 0, 0,
200                                                   c.getWidth(), c.getHeight());
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     @Override
paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h)207     public void paintBorder(SynthContext context, Graphics g, int x,
208                             int y, int w, int h) {
209         context.getPainter().paintEditorPaneBorder(context, g, x, y, w, h);
210     }
211 }
212