001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
006     *
007     * Project Info:  http://www.jfree.org/jfreechart/index.html
008     *
009     * This library is free software; you can redistribute it and/or modify it 
010     * under the terms of the GNU Lesser General Public License as published by 
011     * the Free Software Foundation; either version 2.1 of the License, or 
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but 
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
022     * USA.  
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025     * in the United States and other countries.]
026     *
027     * ---------------
028     * ImageTitle.java
029     * ---------------
030     * (C) Copyright 2000-2007, by David Berry and Contributors;
031     *
032     * Original Author:  David Berry;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *
035     * $Id: ImageTitle.java,v 1.8.2.3 2007/02/02 15:03:19 mungady Exp $
036     *
037     * Changes (from 18-Sep-2001)
038     * --------------------------
039     * 18-Sep-2001 : Added standard header (DG);
040     * 07-Nov-2001 : Separated the JCommon Class Library classes, JFreeChart now 
041     *               requires jcommon.jar (DG);
042     * 09-Jan-2002 : Updated Javadoc comments (DG);
043     * 07-Feb-2002 : Changed blank space around title from Insets --> Spacer, to 
044     *               allow for relative or absolute spacing (DG);
045     * 25-Jun-2002 : Updated import statements (DG);
046     * 23-Sep-2002 : Fixed errors reported by Checkstyle (DG);
047     * 26-Nov-2002 : Added method for drawing images at left or right (DG);
048     * 22-Sep-2003 : Added checks that the Image can never be null (TM).
049     * 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0 
050     *               release (DG);    
051     * 02-Feb-2005 : Changed padding mechanism for all titles (DG);
052     * 20-Apr-2005 : Added new draw() method (DG);   
053     * ------------- JFREECHART 1.0.x ---------------------------------------------
054     * 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
055     * 
056     */
057    
058    package org.jfree.chart.title;
059    
060    import java.awt.Graphics2D;
061    import java.awt.Image;
062    import java.awt.geom.Rectangle2D;
063    
064    import org.jfree.chart.event.TitleChangeEvent;
065    import org.jfree.ui.HorizontalAlignment;
066    import org.jfree.ui.RectangleEdge;
067    import org.jfree.ui.RectangleInsets;
068    import org.jfree.ui.Size2D;
069    import org.jfree.ui.VerticalAlignment;
070    
071    /**
072     * A chart title that displays an image.  This is useful, for example, if you
073     * have an image of your corporate logo and want to use as a footnote or part
074     * of a title in a chart you create.
075     * <P>
076     * ImageTitle needs an image passed to it in the constructor.  For ImageTitle
077     * to work, you must have already loaded this image from its source (disk or
078     * URL).  It is recomended you use something like
079     * Toolkit.getDefaultToolkit().getImage() to get the image.  Then, use
080     * MediaTracker or some other message to make sure the image is fully loaded
081     * from disk.
082     */
083    public class ImageTitle extends Title {
084    
085        /** The title image. */
086        private Image image;
087    
088        /**
089         * Creates a new image title.
090         *
091         * @param image  the image (<code>null</code> not permitted).
092         */
093        public ImageTitle(Image image) {
094            this(image, image.getHeight(null), image.getWidth(null), 
095                    Title.DEFAULT_POSITION, Title.DEFAULT_HORIZONTAL_ALIGNMENT,
096                    Title.DEFAULT_VERTICAL_ALIGNMENT, Title.DEFAULT_PADDING);
097        }
098    
099        /**
100         * Creates a new image title.
101         *
102         * @param image  the image (<code>null</code> not permitted).
103         * @param position  the title position.
104         * @param horizontalAlignment  the horizontal alignment.
105         * @param verticalAlignment  the vertical alignment.
106         */
107        public ImageTitle(Image image, RectangleEdge position, 
108                          HorizontalAlignment horizontalAlignment, 
109                          VerticalAlignment verticalAlignment) {
110    
111            this(image, image.getHeight(null), image.getWidth(null),
112                    position, horizontalAlignment, verticalAlignment, 
113                    Title.DEFAULT_PADDING);
114        }
115    
116        /**
117         * Creates a new image title with the given image scaled to the given
118         * width and height in the given location.
119         *
120         * @param image  the image (<code>null</code> not permitted).
121         * @param height  the height used to draw the image.
122         * @param width  the width used to draw the image.
123         * @param position  the title position.
124         * @param horizontalAlignment  the horizontal alignment.
125         * @param verticalAlignment  the vertical alignment.
126         * @param padding  the amount of space to leave around the outside of the 
127         *                 title.
128         */
129        public ImageTitle(Image image, int height, int width, 
130                          RectangleEdge position,
131                          HorizontalAlignment horizontalAlignment, 
132                          VerticalAlignment verticalAlignment,
133                          RectangleInsets padding) {
134    
135            super(position, horizontalAlignment, verticalAlignment, padding);
136            if (image == null) {
137                throw new NullPointerException("Null 'image' argument.");
138            }
139            this.image = image;
140            setHeight(height);
141            setWidth(width);
142    
143        }
144    
145        /**
146         * Returns the image for the title.
147         *
148         * @return The image for the title (never <code>null</code>).
149         */
150        public Image getImage() {
151            return this.image;
152        }
153    
154        /**
155         * Sets the image for the title and notifies registered listeners that the
156         * title has been modified.
157         *
158         * @param image  the new image (<code>null</code> not permitted).
159         */
160        public void setImage(Image image) {
161            if (image == null) {
162                throw new NullPointerException("Null 'image' argument.");
163            }
164            this.image = image;
165            notifyListeners(new TitleChangeEvent(this));
166        }
167    
168        /**
169         * Draws the title on a Java 2D graphics device (such as the screen or a 
170         * printer).
171         *
172         * @param g2  the graphics device.
173         * @param titleArea  the area within which the title (and plot) should be 
174         *                   drawn.
175         */
176        public void draw(Graphics2D g2, Rectangle2D titleArea) {
177    
178            RectangleEdge position = getPosition();
179            if (position == RectangleEdge.TOP || position == RectangleEdge.BOTTOM) {
180                drawHorizontal(g2, titleArea);
181            }
182            else if (position == RectangleEdge.LEFT 
183                         || position == RectangleEdge.RIGHT) {
184                drawVertical(g2, titleArea);
185            }
186            else {
187                throw new RuntimeException("Invalid title position.");
188            }
189        }
190    
191        /**
192         * Draws the title on a Java 2D graphics device (such as the screen or a 
193         * printer).
194         *
195         * @param g2  the graphics device.
196         * @param chartArea  the area within which the title (and plot) should be 
197         *                   drawn.
198         *
199         * @return The size of the area used by the title.
200         */
201        protected Size2D drawHorizontal(Graphics2D g2, Rectangle2D chartArea) {
202    
203            double startY = 0.0;
204            double topSpace = 0.0;
205            double bottomSpace = 0.0;
206            double leftSpace = 0.0;
207            double rightSpace = 0.0;
208    
209            double w = getWidth();
210            double h = getHeight();
211            RectangleInsets padding = getPadding();
212            topSpace = padding.calculateTopOutset(h);
213            bottomSpace = padding.calculateBottomOutset(h);
214            leftSpace = padding.calculateLeftOutset(w);
215            rightSpace = padding.calculateRightOutset(w);
216    
217            if (getPosition() == RectangleEdge.TOP) {
218                startY = chartArea.getY() + topSpace;
219            }
220            else {
221                startY = chartArea.getY() + chartArea.getHeight() - bottomSpace - h;
222            }
223    
224            // what is our alignment?
225            HorizontalAlignment horizontalAlignment = getHorizontalAlignment();
226            double startX = 0.0;
227            if (horizontalAlignment == HorizontalAlignment.CENTER) {
228                startX = chartArea.getX() + leftSpace + chartArea.getWidth() / 2.0 
229                         - w / 2.0;
230            }
231            else if (horizontalAlignment == HorizontalAlignment.LEFT) {
232                startX = chartArea.getX() + leftSpace;
233            }
234            else if (horizontalAlignment == HorizontalAlignment.RIGHT) {
235                startX = chartArea.getX() + chartArea.getWidth() - rightSpace - w;
236            }
237            g2.drawImage(this.image, (int) startX, (int) startY, (int) w, (int) h, 
238                    null);
239    
240            return new Size2D(chartArea.getWidth() + leftSpace + rightSpace,
241                h + topSpace + bottomSpace);
242    
243        }
244    
245        /**
246         * Draws the title on a Java 2D graphics device (such as the screen or a 
247         * printer).
248         *
249         * @param g2  the graphics device.
250         * @param chartArea  the area within which the title (and plot) should be 
251         *                   drawn.
252         *
253         * @return The size of the area used by the title.
254         */
255        protected Size2D drawVertical(Graphics2D g2, Rectangle2D chartArea) {
256    
257            double startX = 0.0;
258            double topSpace = 0.0;
259            double bottomSpace = 0.0;
260            double leftSpace = 0.0;
261            double rightSpace = 0.0;
262    
263            double w = getWidth();
264            double h = getHeight();
265            
266            RectangleInsets padding = getPadding();
267            if (padding != null) {
268                topSpace = padding.calculateTopOutset(h);
269                bottomSpace = padding.calculateBottomOutset(h);
270                leftSpace = padding.calculateLeftOutset(w);
271                rightSpace = padding.calculateRightOutset(w);
272            }
273    
274            if (getPosition() == RectangleEdge.LEFT) {
275                startX = chartArea.getX() + leftSpace;
276            }
277            else {
278                startX = chartArea.getMaxX() - rightSpace - w;
279            }
280    
281            // what is our alignment?
282            VerticalAlignment alignment = getVerticalAlignment();
283            double startY = 0.0;
284            if (alignment == VerticalAlignment.CENTER) {
285                startY = chartArea.getMinY() + topSpace 
286                         + chartArea.getHeight() / 2.0 - h / 2.0;
287            }
288            else if (alignment == VerticalAlignment.TOP) {
289                startY = chartArea.getMinY() + topSpace;
290            }
291            else if (alignment == VerticalAlignment.BOTTOM) {
292                startY = chartArea.getMaxY() - bottomSpace - h;
293            }
294    
295            g2.drawImage(this.image, (int) startX, (int) startY, (int) w, (int) h, 
296                    null);
297    
298            return new Size2D(chartArea.getWidth() + leftSpace + rightSpace,
299                h + topSpace + bottomSpace);
300    
301        }
302        
303        /**
304         * Draws the block within the specified area.
305         * 
306         * @param g2  the graphics device.
307         * @param area  the area.
308         * @param params  ignored (<code>null</code> permitted).
309         * 
310         * @return Always <code>null</code>.
311         */
312        public Object draw(Graphics2D g2, Rectangle2D area, Object params) {
313            draw(g2, area);
314            return null;
315        }
316    
317    }