001    /*
002     * $Id: TextPainter.java 3288 2009-03-10 14:36:28Z kschaefe $
003     *
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     *
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     *
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    
022    package org.jdesktop.swingx.painter;
023    
024    import org.jdesktop.swingx.painter.effects.AreaEffect;
025    
026    import javax.swing.*;
027    import javax.swing.text.JTextComponent;
028    import java.awt.*;
029    import java.awt.font.GlyphVector;
030    
031    /**
032     * A painter which draws text. If the font, text, and paint are not provided they will be
033     * obtained from the object being painted if it is a Swing text component.
034     *
035     * @author rbair
036     */
037    public class TextPainter extends AbstractAreaPainter<Object> {
038        private String text = "";
039        private Font font = null;
040        
041        /** Creates a new instance of TextPainter */
042        public TextPainter() {
043            this("");
044        }
045        
046        /**
047         * Create a new TextPainter which will paint the specified text
048         * @param text the text to paint
049         */
050        public TextPainter(String text) {
051            this(text, null, null);
052        }
053        
054        /**
055         * Create a new TextPainter which will paint the specified text with the specified font.
056         * @param text the text to paint
057         * @param font the font to paint the text with
058         */
059        public TextPainter(String text, Font font) {
060            this(text, font, null);
061        }
062        
063        /**
064         * Create a new TextPainter which will paint the specified text with the specified paint.
065         * @param text the text to paint
066         * @param paint the paint to paint with
067         */
068        public TextPainter(String text, Paint paint) {
069            this(text, null, paint);
070        }
071        
072        /**
073         * Create a new TextPainter which will paint the specified text with the specified font and paint.
074         * @param text the text to paint
075         * @param font the font to paint the text with
076         * @param paint the paint to paint with
077         */
078        public TextPainter(String text, Font font, Paint paint) {
079            this.text = text;
080            this.font = font;
081            setFillPaint(paint);
082        }
083        
084        /**
085         * Set the font (and font size and style) to be used when drawing the text
086         * @param f the new font
087         */
088        public void setFont(Font f) {
089            Font old = getFont();
090            this.font = f;
091            setDirty(true);
092            firePropertyChange("font", old, getFont());
093        }
094        
095        /**
096         * gets the font (and font size and style) to be used when drawing the text
097         * @return the current font
098         */
099        public Font getFont() {
100            return font;
101        }
102        
103        /**
104         * Sets the text to draw
105         * @param text the text to draw
106         */
107        public void setText(String text) {
108            String old = getText();
109            this.text = text == null ? "" : text;
110            setDirty(true);
111            firePropertyChange("text", old, getText());
112        }
113        
114        /**
115         * gets the text currently used to draw
116         * @return the text to be drawn
117         */
118        public String getText() {
119            return text;
120        }
121    
122        /**
123         * {@inheritDoc}
124         */
125        @Override
126        protected void doPaint(Graphics2D g, Object component, int width, int height) {
127            Font font = calculateFont(component);
128            if (font != null) {
129                g.setFont(font);
130            }
131            
132            Paint paint = getFillPaint();
133            if(paint == null) {
134                if(component instanceof JComponent) {
135                    paint = ((JComponent)component).getForeground();
136                }
137            }
138            
139            String text = calculateText(component);
140            
141            // get the font metrics
142            FontMetrics metrics = g.getFontMetrics(g.getFont());
143            //Rectangle2D rect = metrics.getStringBounds(text,g);
144            
145            int tw = metrics.stringWidth(text);
146            int th = metrics.getHeight();
147            Rectangle res = calculateLayout(tw, th, width, height);
148            
149            g.translate(res.x, res.y);
150            
151            if(isPaintStretched()) {
152                paint = calculateSnappedPaint(paint, res.width, res.height);
153            }
154            
155            if (paint != null) {
156                g.setPaint(paint);
157            }
158            
159            g.drawString(text, 0, 0 + metrics.getAscent());
160            if(getAreaEffects() != null) {
161                Shape shape = provideShape(g, component, width, height);
162                for(AreaEffect ef : getAreaEffects()) {
163                    ef.apply(g, shape, width, height);
164                }
165            }
166            g.translate(-res.x,-res.y);
167        }
168        
169        private String calculateText(final Object component) {
170            // prep the text
171            String text = getText();
172            //make components take priority if(text == null || text.trim().equals("")) {
173            if(text != null && !text.trim().equals("")) {
174                return text;
175            }
176            if(component instanceof JTextComponent) {
177                text = ((JTextComponent)component).getText();
178            }
179            if(component instanceof JLabel) {
180                text = ((JLabel)component).getText();
181            }
182            if(component instanceof AbstractButton) {
183                text = ((AbstractButton)component).getText();
184            }
185            return text;
186        }
187        
188        private Font calculateFont(final Object component) {
189            // prep the various text attributes
190            Font font = getFont();
191            if (font == null) {
192                if(component instanceof JComponent) {
193                    font = ((JComponent)component).getFont();
194                }
195            }
196            if (font == null) {
197                font = new Font("Dialog", Font.PLAIN, 18);
198            }
199            return font;
200        }
201    
202        /**
203         * {@inheritDoc}
204         */
205        @Override
206        protected Shape provideShape(Graphics2D g2, Object comp, int width, int height) {
207            Font font = calculateFont(comp);
208            String text = calculateText(comp);
209            FontMetrics metrics = g2.getFontMetrics(font);
210            GlyphVector vect = font.createGlyphVector(g2.getFontRenderContext(),text);
211            return vect.getOutline(0f,0f+ metrics.getAscent());
212        }
213    }