001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package org.jvnet.substance;
031:
032: import java.awt.*;
033: import java.beans.PropertyChangeEvent;
034: import java.beans.PropertyChangeListener;
035:
036: import javax.swing.*;
037: import javax.swing.plaf.ComponentUI;
038: import javax.swing.plaf.basic.BasicHTML;
039: import javax.swing.plaf.basic.BasicLabelUI;
040: import javax.swing.text.View;
041:
042: import org.jvnet.lafwidget.layout.TransitionLayout;
043: import org.jvnet.substance.painter.text.SubstanceTextPainter;
044: import org.jvnet.substance.utils.*;
045:
046: /**
047: * UI for labels in <b>Substance</b> look and feel.
048: *
049: * @author Kirill Grouchnikov
050: */
051: public class SubstanceLabelUI extends BasicLabelUI {
052: /**
053: * Background delegate.
054: */
055: private SubstanceFillBackgroundDelegate bgDelegate;
056:
057: /**
058: * Name of the client property that points to the original icon.
059: */
060: private final static String ORIG_ICON = "substancelaf.internal.label.origIcon";
061:
062: /**
063: * Name of the client property that marks the label during icon replacement.
064: */
065: private final static String REPLACING_ICON = "substancelaf.internal.label.replacingIcon";
066:
067: /**
068: * Property change listener.
069: */
070: protected PropertyChangeListener substancePropertyChangeListener;
071:
072: /*
073: * (non-Javadoc)
074: *
075: * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
076: */
077: public static ComponentUI createUI(JComponent b) {
078: return new SubstanceLabelUI();
079: }
080:
081: /**
082: * Creates a new UI delegate for labels.
083: */
084: public SubstanceLabelUI() {
085: super ();
086: bgDelegate = new SubstanceFillBackgroundDelegate();
087: }
088:
089: /**
090: * Replaces the label icon with a themed version of that icon.
091: *
092: * @param label
093: * Label.
094: */
095: protected void replaceThemedIcon(final JLabel label) {
096: if (!SubstanceCoreUtilities.useThemedDefaultIcon(label))
097: return;
098:
099: final Icon icon = label.getIcon();
100: if ((icon != null)
101: && (!Boolean.TRUE.equals(label
102: .getClientProperty(REPLACING_ICON)))) {
103: SwingUtilities.invokeLater(new Runnable() {
104: public void run() {
105: label.putClientProperty(ORIG_ICON, label.getIcon());
106: label.putClientProperty(REPLACING_ICON,
107: Boolean.TRUE);
108: label.setIcon(new ImageIcon(SubstanceImageCreator
109: .getThemeImage(label, icon,
110: SubstanceThemeUtilities.getTheme(
111: label,
112: ComponentState.DEFAULT),
113: false)));
114: label.putClientProperty(REPLACING_ICON, null);
115: }
116: });
117: }
118: }
119:
120: /*
121: * (non-Javadoc)
122: *
123: * @see javax.swing.plaf.basic.BasicLabelUI#installDefaults(javax.swing.JLabel)
124: */
125: @Override
126: protected void installDefaults(JLabel c) {
127: super .installDefaults(c);
128: this .replaceThemedIcon(c);
129: }
130:
131: /*
132: * (non-Javadoc)
133: *
134: * @see javax.swing.plaf.basic.BasicLabelUI#uninstallDefaults(javax.swing.JLabel)
135: */
136: @Override
137: protected void uninstallDefaults(JLabel c) {
138: Icon origIcon = (Icon) c.getClientProperty(ORIG_ICON);
139: if (origIcon != null) {
140: c.putClientProperty(REPLACING_ICON, Boolean.TRUE);
141: c.setIcon(origIcon);
142: c.putClientProperty(REPLACING_ICON, null);
143: }
144:
145: super .uninstallDefaults(c);
146: }
147:
148: /*
149: * (non-Javadoc)
150: *
151: * @see javax.swing.plaf.basic.BasicLabelUI#installListeners(javax.swing.JLabel)
152: */
153: @Override
154: protected void installListeners(final JLabel c) {
155: super .installListeners(c);
156:
157: this .substancePropertyChangeListener = new PropertyChangeListener() {
158: public void propertyChange(PropertyChangeEvent evt) {
159: if ("icon".equals(evt.getPropertyName())) {
160: replaceThemedIcon(c);
161: }
162:
163: if (SubstanceLookAndFeel.USE_THEMED_DEFAULT_ICONS
164: .equals(evt.getPropertyName())) {
165: replaceThemedIcon(c);
166: }
167:
168: if ("opaque".equals(evt.getPropertyName())) {
169: if (!Boolean.TRUE
170: .equals(c
171: .getClientProperty(SubstanceButtonUI.LOCK_OPACITY))) {
172: c.putClientProperty(
173: SubstanceButtonUI.OPACITY_ORIGINAL, evt
174: .getNewValue());
175: // System.out
176: // .println("PCL: "
177: // + b.getText()
178: // + "->"
179: // + b
180: // .getClientProperty(SubstanceButtonUI.OPACITY_ORIGINAL));
181: }
182: }
183:
184: }
185: };
186: c
187: .addPropertyChangeListener(this .substancePropertyChangeListener);
188: }
189:
190: /*
191: * (non-Javadoc)
192: *
193: * @see javax.swing.plaf.basic.BasicLabelUI#uninstallListeners(javax.swing.JLabel)
194: */
195: @Override
196: protected void uninstallListeners(JLabel c) {
197: c
198: .removePropertyChangeListener(this .substancePropertyChangeListener);
199: this .substancePropertyChangeListener = null;
200:
201: super .uninstallListeners(c);
202: }
203:
204: @Override
205: public void paint(Graphics g, final JComponent c) {
206:
207: JLabel label = (JLabel) c;
208: String text = label.getText();
209: final Icon icon = (label.isEnabled()) ? label.getIcon() : label
210: .getDisabledIcon();
211:
212: if ((icon == null) && (text == null)) {
213: return;
214: }
215:
216: final Rectangle paintIconR = new Rectangle();
217: final Rectangle paintTextR = new Rectangle();
218: Rectangle paintViewR = new Rectangle();
219: Insets paintViewInsets = new Insets(0, 0, 0, 0);
220:
221: Insets insets = label.getInsets(paintViewInsets);
222: paintViewR.x = insets.left;
223: paintViewR.y = insets.top;
224: paintViewR.width = c.getWidth() - (insets.left + insets.right);
225: paintViewR.height = c.getHeight()
226: - (insets.top + insets.bottom);
227: paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
228: paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
229:
230: String clippedText = SwingUtilities.layoutCompoundLabel(label,
231: g.getFontMetrics(), text, icon, label
232: .getVerticalAlignment(), label
233: .getHorizontalAlignment(), label
234: .getVerticalTextPosition(), label
235: .getHorizontalTextPosition(), paintViewR,
236: paintIconR, paintTextR, label.getIconTextGap());
237:
238: SubstanceTextPainter textPainter = SubstanceLookAndFeel
239: .getCurrentTextPainter();
240:
241: Graphics2D g2d = (Graphics2D) g.create();
242:
243: textPainter.init(label, null, true);
244: if (textPainter.needsBackgroundImage()) {
245: Color color = (label.isOpaque() || (label.getParent() == null)) ? label
246: .getBackground()
247: : label.getParent().getBackground();
248: textPainter.setBackgroundFill(label, color, true, 0, 0);
249: textPainter
250: .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
251: public void paintBackground(Graphics g) {
252: if (icon != null) {
253: icon.paintIcon(c, g, paintIconR.x,
254: paintIconR.y);
255: }
256: }
257: });
258: } else {
259: // Special case - support for applications that use default
260: // core renderers on lists and combo boxes.
261: if (!DefaultListCellRenderer.class.isAssignableFrom(c
262: .getClass())) {
263: bgDelegate.updateIfOpaque(g2d, c);
264: }
265: if (icon != null) {
266: icon.paintIcon(c, g2d, paintIconR.x, paintIconR.y);
267: }
268: }
269: float textAlpha = 1.0f;
270: if (text != null) {
271: final View v = (View) c
272: .getClientProperty(BasicHTML.propertyKey);
273: if (v != null) {
274: if (textPainter.needsBackgroundImage()) {
275: textPainter
276: .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
277: public void paintBackground(Graphics g) {
278: v.paint(g, paintTextR);
279: }
280: });
281: } else {
282: v.paint(g2d, paintTextR);
283: }
284: } else {
285: ComponentState labelState = label.isEnabled() ? ComponentState.DEFAULT
286: : ComponentState.DISABLED_UNSELECTED;
287: textAlpha = SubstanceCoreUtilities.paintText(label,
288: paintTextR, clippedText, label
289: .getDisplayedMnemonicIndex(),
290: labelState, labelState);
291: }
292: }
293: g2d.setComposite(TransitionLayout.getAlphaComposite(label,
294: textAlpha, g));
295: textPainter.renderSurface(g2d);
296: g2d.dispose();
297:
298: }
299:
300: /*
301: * (non-Javadoc)
302: *
303: * @see javax.swing.plaf.ComponentUI#update(java.awt.Graphics,
304: * javax.swing.JComponent)
305: */
306: @Override
307: public void update(Graphics g, JComponent c) {
308: // failsafe for LAF change
309: if (!(UIManager.getLookAndFeel() instanceof SubstanceLookAndFeel))
310: return;
311: this.paint(g, c);
312: }
313: }
|