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 java.beans.PropertyChangeEvent;
  32 import java.awt.*;
  33 
  34 /**
  35  * Provides the look and feel for a styled text editor in the
  36  * Synth look and feel.
  37  * <p>
  38  * <strong>Warning:</strong>
  39  * Serialized objects of this class will not be compatible with
  40  * future Swing releases. The current serialization support is
  41  * appropriate for short term storage or RMI between applications running
  42  * the same version of Swing.  As of 1.4, support for long term storage
  43  * of all JavaBeans
  44  * has been added to the <code>java.beans</code> package.
  45  * Please see {@link java.beans.XMLEncoder}.
  46  *
  47  * @author  Shannon Hickey
  48  * @since 1.7
  49  */
  50 @SuppressWarnings("serial") // Same-version serialization only
  51 public class SynthTextPaneUI extends SynthEditorPaneUI {
  52 
  53     /**
  54      * Creates a UI for the JTextPane.
  55      *
  56      * @param c the JTextPane object
  57      * @return the UI object
  58      */
  59     public static ComponentUI createUI(JComponent c) {
  60         return new SynthTextPaneUI();
  61     }
  62 
  63     /**
  64      * Fetches the name used as a key to lookup properties through the
  65      * UIManager.  This is used as a prefix to all the standard
  66      * text properties.
  67      *
  68      * @return the name ("TextPane")
  69      */
  70     @Override
  71     protected String getPropertyPrefix() {
  72         return "TextPane";
  73     }
  74 
  75     /**
  76      * Installs the UI for a component.  This does the following
  77      * things.
  78      * <ol>
  79      * <li>
  80      * Sets opaqueness of the associated component according to its style,
  81      * if the opaque property has not already been set by the client program.
  82      * <li>
  83      * Installs the default caret and highlighter into the
  84      * associated component. These properties are only set if their
  85      * current value is either {@code null} or an instance of
  86      * {@link UIResource}.
  87      * <li>
  88      * Attaches to the editor and model.  If there is no
  89      * model, a default one is created.
  90      * <li>
  91      * Creates the view factory and the view hierarchy used
  92      * to represent the model.
  93      * </ol>
  94      *
  95      * @param c the editor component
  96      * @see javax.swing.plaf.basic.BasicTextUI#installUI
  97      * @see ComponentUI#installUI
  98      */
  99     @Override
 100     public void installUI(JComponent c) {
 101         super.installUI(c);
 102         updateForeground(c.getForeground());
 103         updateFont(c.getFont());
 104     }
 105 
 106     /**
 107      * This method gets called when a bound property is changed
 108      * on the associated JTextComponent.  This is a hook
 109      * which UI implementations may change to reflect how the
 110      * UI displays bound properties of JTextComponent subclasses.
 111      * If the font, foreground or document has changed, the
 112      * the appropriate property is set in the default style of
 113      * the document.
 114      *
 115      * @param evt the property change event
 116      */
 117     @Override
 118     protected void propertyChange(PropertyChangeEvent evt) {
 119         super.propertyChange(evt);
 120 
 121         String name = evt.getPropertyName();
 122 
 123         if (name.equals("foreground")) {
 124             updateForeground((Color)evt.getNewValue());
 125         } else if (name.equals("font")) {
 126             updateFont((Font)evt.getNewValue());
 127         } else if (name.equals("document")) {
 128             JComponent comp = getComponent();
 129             updateForeground(comp.getForeground());
 130             updateFont(comp.getFont());
 131         }
 132     }
 133 
 134     /**
 135      * Update the color in the default style of the document.
 136      *
 137      * @param color the new color to use or null to remove the color attribute
 138      *              from the document's style
 139      */
 140     private void updateForeground(Color color) {
 141         StyledDocument doc = (StyledDocument)getComponent().getDocument();
 142         Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
 143 
 144         if (style == null) {
 145             return;
 146         }
 147 
 148         if (color == null) {
 149             style.removeAttribute(StyleConstants.Foreground);
 150         } else {
 151             StyleConstants.setForeground(style, color);
 152         }
 153     }
 154 
 155     /**
 156      * Update the font in the default style of the document.
 157      *
 158      * @param font the new font to use or null to remove the font attribute
 159      *             from the document's style
 160      */
 161     private void updateFont(Font font) {
 162         StyledDocument doc = (StyledDocument)getComponent().getDocument();
 163         Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
 164 
 165         if (style == null) {
 166             return;
 167         }
 168 
 169         if (font == null) {
 170             style.removeAttribute(StyleConstants.FontFamily);
 171             style.removeAttribute(StyleConstants.FontSize);
 172             style.removeAttribute(StyleConstants.Bold);
 173             style.removeAttribute(StyleConstants.Italic);
 174         } else {
 175             StyleConstants.setFontFamily(style, font.getName());
 176             StyleConstants.setFontSize(style, font.getSize());
 177             StyleConstants.setBold(style, font.isBold());
 178             StyleConstants.setItalic(style, font.isItalic());
 179         }
 180     }
 181 
 182     @Override
 183     void paintBackground(SynthContext context, Graphics g, JComponent c) {
 184         context.getPainter().paintTextPaneBackground(context, g, 0, 0,
 185                                                   c.getWidth(), c.getHeight());
 186     }
 187 
 188     /**
 189      * {@inheritDoc}
 190      */
 191     @Override
 192     public void paintBorder(SynthContext context, Graphics g, int x,
 193                             int y, int w, int h) {
 194         context.getPainter().paintTextPaneBorder(context, g, x, y, w, h);
 195     }
 196 }