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