1 /* 2 * Copyright (c) 2002, 2010, 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 java.beans.PropertyChangeEvent; 30 import java.beans.PropertyChangeListener; 31 32 import javax.swing.*; 33 import javax.swing.plaf.basic.BasicHTML; 34 import javax.swing.plaf.basic.BasicToolTipUI; 35 import javax.swing.plaf.ComponentUI; 36 import javax.swing.text.View; 37 38 39 /** 40 * Provides the Synth L&F UI delegate for 41 * {@link javax.swing.JToolTip}. 42 * 43 * @author Joshua Outwater 44 * @since 1.7 45 */ 46 public class SynthToolTipUI extends BasicToolTipUI 47 implements PropertyChangeListener, SynthUI { 48 private SynthStyle style; 49 50 /** 51 * Creates a new UI object for the given component. 52 * 53 * @param c component to create UI object for 54 * @return the UI object 55 */ 56 public static ComponentUI createUI(JComponent c) { 57 return new SynthToolTipUI(); 58 } 59 60 /** 61 * @inheritDoc 62 */ 63 @Override 64 protected void installDefaults(JComponent c) { 65 updateStyle(c); 66 } 67 68 private void updateStyle(JComponent c) { 69 SynthContext context = getContext(c, ENABLED); 70 style = SynthLookAndFeel.updateStyle(context, this); 71 context.dispose(); 72 } 73 74 /** 75 * @inheritDoc 76 */ 77 @Override 78 protected void uninstallDefaults(JComponent c) { 79 SynthContext context = getContext(c, ENABLED); 80 style.uninstallDefaults(context); 81 context.dispose(); 82 style = null; 83 } 84 85 /** 86 * @inheritDoc 87 */ 88 @Override 89 protected void installListeners(JComponent c) { 90 c.addPropertyChangeListener(this); 91 } 92 93 /** 94 * @inheritDoc 95 */ 96 @Override 97 protected void uninstallListeners(JComponent c) { 98 c.removePropertyChangeListener(this); 99 } 100 101 /** 102 * @inheritDoc 103 */ 104 @Override 105 public SynthContext getContext(JComponent c) { 106 return getContext(c, getComponentState(c)); 107 } 108 109 private SynthContext getContext(JComponent c, int state) { 110 return SynthContext.getContext(SynthContext.class, c, 111 SynthLookAndFeel.getRegion(c), style, state); 112 } 113 114 private int getComponentState(JComponent c) { 115 JComponent comp = ((JToolTip)c).getComponent(); 116 117 if (comp != null && !comp.isEnabled()) { 118 return DISABLED; 119 } 120 return SynthLookAndFeel.getComponentState(c); 121 } 122 123 /** 124 * Notifies this UI delegate to repaint the specified component. 125 * This method paints the component background, then calls 126 * the {@link #paint(SynthContext,Graphics)} method. 127 * 128 * <p>In general, this method does not need to be overridden by subclasses. 129 * All Look and Feel rendering code should reside in the {@code paint} method. 130 * 131 * @param g the {@code Graphics} object used for painting 132 * @param c the component being painted 133 * @see #paint(SynthContext,Graphics) 134 */ 135 @Override 136 public void update(Graphics g, JComponent c) { 137 SynthContext context = getContext(c); 138 139 SynthLookAndFeel.update(context, g); 140 context.getPainter().paintToolTipBackground(context, 141 g, 0, 0, c.getWidth(), c.getHeight()); 142 paint(context, g); 143 context.dispose(); 144 } 145 146 /** 147 * @inheritDoc 148 */ 149 @Override 150 public void paintBorder(SynthContext context, Graphics g, int x, 151 int y, int w, int h) { 152 context.getPainter().paintToolTipBorder(context, g, x, y, w, h); 153 } 154 155 /** 156 * Paints the specified component according to the Look and Feel. 157 * <p>This method is not used by Synth Look and Feel. 158 * Painting is handled by the {@link #paint(SynthContext,Graphics)} method. 159 * 160 * @param g the {@code Graphics} object used for painting 161 * @param c the component being painted 162 * @see #paint(SynthContext,Graphics) 163 */ 164 @Override 165 public void paint(Graphics g, JComponent c) { 166 SynthContext context = getContext(c); 167 168 paint(context, g); 169 context.dispose(); 170 } 171 172 /** 173 * Paints the specified component. 174 * 175 * @param context context for the component being painted 176 * @param g the {@code Graphics} object used for painting 177 * @see #update(Graphics,JComponent) 178 */ 179 protected void paint(SynthContext context, Graphics g) { 180 JToolTip tip = (JToolTip)context.getComponent(); 181 182 Insets insets = tip.getInsets(); 183 View v = (View)tip.getClientProperty(BasicHTML.propertyKey); 184 if (v != null) { 185 Rectangle paintTextR = new Rectangle(insets.left, insets.top, 186 tip.getWidth() - (insets.left + insets.right), 187 tip.getHeight() - (insets.top + insets.bottom)); 188 v.paint(g, paintTextR); 189 } else { 190 g.setColor(context.getStyle().getColor(context, 191 ColorType.TEXT_FOREGROUND)); 192 g.setFont(style.getFont(context)); 193 context.getStyle().getGraphicsUtils(context).paintText( 194 context, g, tip.getTipText(), insets.left, insets.top, -1); 195 } 196 } 197 198 /** 199 * @inheritDoc 200 */ 201 @Override 202 public Dimension getPreferredSize(JComponent c) { 203 SynthContext context = getContext(c); 204 Insets insets = c.getInsets(); 205 Dimension prefSize = new Dimension(insets.left+insets.right, 206 insets.top+insets.bottom); 207 String text = ((JToolTip)c).getTipText(); 208 209 if (text != null) { 210 View v = (c != null) ? (View) c.getClientProperty("html") : null; 211 if (v != null) { 212 prefSize.width += (int) v.getPreferredSpan(View.X_AXIS); 213 prefSize.height += (int) v.getPreferredSpan(View.Y_AXIS); 214 } else { 215 Font font = context.getStyle().getFont(context); 216 FontMetrics fm = c.getFontMetrics(font); 217 prefSize.width += context.getStyle().getGraphicsUtils(context). 218 computeStringWidth(context, font, fm, text); 219 prefSize.height += fm.getHeight(); 220 } 221 } 222 context.dispose(); 223 return prefSize; 224 } 225 226 /** 227 * @inheritDoc 228 */ 229 @Override 230 public void propertyChange(PropertyChangeEvent e) { 231 if (SynthLookAndFeel.shouldUpdateStyle(e)) { 232 updateStyle((JToolTip)e.getSource()); 233 } 234 String name = e.getPropertyName(); 235 if (name.equals("tiptext") || "font".equals(name) || 236 "foreground".equals(name)) { 237 // remove the old html view client property if one 238 // existed, and install a new one if the text installed 239 // into the JLabel is html source. 240 JToolTip tip = ((JToolTip) e.getSource()); 241 String text = tip.getTipText(); 242 BasicHTML.updateRenderer(tip, text); 243 } 244 } 245 }