1 /* 2 * Copyright (c) 2002, 2019, 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.plaf.*; 30 import javax.swing.plaf.basic.*; 31 import javax.swing.text.View; 32 import java.awt.Dimension; 33 import java.awt.Rectangle; 34 import java.awt.Insets; 35 import java.awt.Graphics; 36 import java.awt.FontMetrics; 37 import java.beans.PropertyChangeEvent; 38 39 /** 40 * Provides the Synth L&F UI delegate for 41 * {@link javax.swing.JLabel}. 42 * 43 * @author Scott Violet 44 * @since 1.7 45 */ 46 public class SynthLabelUI extends BasicLabelUI implements SynthUI { 47 private SynthStyle style; 48 49 /** 50 * Returns the LabelUI implementation used for the skins look and feel. 51 * 52 * @param c component to create UI object for 53 * @return the UI object 54 */ 55 public static ComponentUI createUI(JComponent c){ 56 return new SynthLabelUI(); 57 } 58 59 /** 60 * {@inheritDoc} 61 */ 62 @Override 63 protected void installDefaults(JLabel c) { 64 updateStyle(c); 65 } 66 67 void updateStyle(JLabel c) { 68 SynthContext context = getContext(c, ENABLED); 69 style = SynthLookAndFeel.updateStyle(context, this); 70 } 71 72 /** 73 * {@inheritDoc} 74 */ 75 @Override 76 protected void uninstallDefaults(JLabel c){ 77 SynthContext context = getContext(c, ENABLED); 78 79 style.uninstallDefaults(context); 80 style = null; 81 } 82 83 /** 84 * {@inheritDoc} 85 */ 86 @Override 87 public SynthContext getContext(JComponent c) { 88 return getContext(c, getComponentState(c)); 89 } 90 91 private SynthContext getContext(JComponent c, int state) { 92 return SynthContext.getContext(c, style, state); 93 } 94 95 private int getComponentState(JComponent c) { 96 int state = SynthLookAndFeel.getComponentState(c); 97 if (SynthLookAndFeel.getSelectedUI() == this && 98 state == SynthConstants.ENABLED) { 99 state = SynthLookAndFeel.getSelectedUIState() | SynthConstants.ENABLED; 100 } 101 return state; 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 @Override 108 public int getBaseline(JComponent c, int width, int height) { 109 if (c == null) { 110 throw new NullPointerException("Component must be non-null"); 111 } 112 if (width < 0 || height < 0) { 113 throw new IllegalArgumentException( 114 "Width and height must be >= 0"); 115 } 116 JLabel label = (JLabel)c; 117 String text = label.getText(); 118 if (text == null || text.isEmpty()) { 119 return -1; 120 } 121 Insets i = label.getInsets(); 122 Rectangle viewRect = new Rectangle(); 123 Rectangle textRect = new Rectangle(); 124 Rectangle iconRect = new Rectangle(); 125 viewRect.x = i.left; 126 viewRect.y = i.top; 127 viewRect.width = width - (i.right + viewRect.x); 128 viewRect.height = height - (i.bottom + viewRect.y); 129 130 // layout the text and icon 131 SynthContext context = getContext(label); 132 FontMetrics fm = context.getComponent().getFontMetrics( 133 context.getStyle().getFont(context)); 134 context.getStyle().getGraphicsUtils(context).layoutText( 135 context, fm, label.getText(), label.getIcon(), 136 label.getHorizontalAlignment(), label.getVerticalAlignment(), 137 label.getHorizontalTextPosition(), label.getVerticalTextPosition(), 138 viewRect, iconRect, textRect, label.getIconTextGap()); 139 View view = (View)label.getClientProperty(BasicHTML.propertyKey); 140 int baseline; 141 if (view != null) { 142 baseline = BasicHTML.getHTMLBaseline(view, textRect.width, 143 textRect.height); 144 if (baseline >= 0) { 145 baseline += textRect.y; 146 } 147 } 148 else { 149 baseline = textRect.y + fm.getAscent(); 150 } 151 return baseline; 152 } 153 154 /** 155 * Notifies this UI delegate to repaint the specified component. 156 * This method paints the component background, then calls 157 * the {@link #paint(SynthContext,Graphics)} method. 158 * 159 * <p>In general, this method does not need to be overridden by subclasses. 160 * All Look and Feel rendering code should reside in the {@code paint} method. 161 * 162 * @param g the {@code Graphics} object used for painting 163 * @param c the component being painted 164 * @see #paint(SynthContext,Graphics) 165 */ 166 @Override 167 public void update(Graphics g, JComponent c) { 168 SynthContext context = getContext(c); 169 170 SynthLookAndFeel.update(context, g); 171 context.getPainter().paintLabelBackground(context, 172 g, 0, 0, c.getWidth(), c.getHeight()); 173 paint(context, g); 174 } 175 176 /** 177 * Paints the specified component according to the Look and Feel. 178 * <p>This method is not used by Synth Look and Feel. 179 * Painting is handled by the {@link #paint(SynthContext,Graphics)} method. 180 * 181 * @param g the {@code Graphics} object used for painting 182 * @param c the component being painted 183 * @see #paint(SynthContext,Graphics) 184 */ 185 @Override 186 public void paint(Graphics g, JComponent c) { 187 SynthContext context = getContext(c); 188 189 paint(context, g); 190 } 191 192 /** 193 * Paints the specified component. 194 * 195 * @param context context for the component being painted 196 * @param g the {@code Graphics} object used for painting 197 * @see #update(Graphics,JComponent) 198 */ 199 protected void paint(SynthContext context, Graphics g) { 200 JLabel label = (JLabel)context.getComponent(); 201 Icon icon = (label.isEnabled()) ? label.getIcon() : 202 label.getDisabledIcon(); 203 204 g.setColor(context.getStyle().getColor(context, 205 ColorType.TEXT_FOREGROUND)); 206 g.setFont(style.getFont(context)); 207 context.getStyle().getGraphicsUtils(context).paintText( 208 context, g, label.getText(), icon, 209 label.getHorizontalAlignment(), label.getVerticalAlignment(), 210 label.getHorizontalTextPosition(), label.getVerticalTextPosition(), 211 label.getIconTextGap(), label.getDisplayedMnemonicIndex(), 0); 212 } 213 214 /** 215 * {@inheritDoc} 216 */ 217 @Override 218 public void paintBorder(SynthContext context, Graphics g, int x, 219 int y, int w, int h) { 220 context.getPainter().paintLabelBorder(context, g, x, y, w, h); 221 } 222 223 /** 224 * {@inheritDoc} 225 */ 226 @Override 227 public Dimension getPreferredSize(JComponent c) { 228 JLabel label = (JLabel)c; 229 Icon icon = (label.isEnabled()) ? label.getIcon() : 230 label.getDisabledIcon(); 231 SynthContext context = getContext(c); 232 Dimension size = context.getStyle().getGraphicsUtils(context). 233 getPreferredSize( 234 context, context.getStyle().getFont(context), label.getText(), 235 icon, label.getHorizontalAlignment(), 236 label.getVerticalAlignment(), label.getHorizontalTextPosition(), 237 label.getVerticalTextPosition(), label.getIconTextGap(), 238 label.getDisplayedMnemonicIndex()); 239 240 return size; 241 } 242 243 /** 244 * {@inheritDoc} 245 */ 246 @Override 247 public Dimension getMinimumSize(JComponent c) { 248 JLabel label = (JLabel)c; 249 Icon icon = (label.isEnabled()) ? label.getIcon() : 250 label.getDisabledIcon(); 251 SynthContext context = getContext(c); 252 Dimension size = context.getStyle().getGraphicsUtils(context). 253 getMinimumSize( 254 context, context.getStyle().getFont(context), label.getText(), 255 icon, label.getHorizontalAlignment(), 256 label.getVerticalAlignment(), label.getHorizontalTextPosition(), 257 label.getVerticalTextPosition(), label.getIconTextGap(), 258 label.getDisplayedMnemonicIndex()); 259 260 return size; 261 } 262 263 /** 264 * {@inheritDoc} 265 */ 266 @Override 267 public Dimension getMaximumSize(JComponent c) { 268 JLabel label = (JLabel)c; 269 Icon icon = (label.isEnabled()) ? label.getIcon() : 270 label.getDisabledIcon(); 271 SynthContext context = getContext(c); 272 Dimension size = context.getStyle().getGraphicsUtils(context). 273 getMaximumSize( 274 context, context.getStyle().getFont(context), label.getText(), 275 icon, label.getHorizontalAlignment(), 276 label.getVerticalAlignment(), label.getHorizontalTextPosition(), 277 label.getVerticalTextPosition(), label.getIconTextGap(), 278 label.getDisplayedMnemonicIndex()); 279 280 return size; 281 } 282 283 /** 284 * {@inheritDoc} 285 */ 286 @Override 287 public void propertyChange(PropertyChangeEvent e) { 288 super.propertyChange(e); 289 if (SynthLookAndFeel.shouldUpdateStyle(e)) { 290 updateStyle((JLabel)e.getSource()); 291 } 292 } 293 }