001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2011, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * ------------------- 028 * ChartSelection.java 029 * ------------------- 030 * (C) Copyright 2009, by Object Refinery Limited. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * Changes 036 * ------- 037 * 08-Apr-2009 : Version 1, with inspiration from patch 1460845 (DG); 038 * 05-May-2009 : Match the scaling options provided by the ChartPanel 039 * class (DG); 040 * 041 */ 042 043package org.jfree.chart; 044 045import java.awt.Graphics2D; 046import java.awt.datatransfer.DataFlavor; 047import java.awt.datatransfer.Transferable; 048import java.awt.datatransfer.UnsupportedFlavorException; 049import java.awt.geom.AffineTransform; 050import java.awt.geom.Rectangle2D; 051import java.awt.image.BufferedImage; 052import java.io.IOException; 053 054/** 055 * A class used to represent a chart on the clipboard. 056 * 057 * @since 1.0.13 058 */ 059public class ChartTransferable implements Transferable { 060 061 /** The data flavor. */ 062 final DataFlavor imageFlavor = new DataFlavor( 063 "image/x-java-image; class=java.awt.Image", "Image"); 064 065 /** The chart. */ 066 private JFreeChart chart; 067 068 /** The width of the chart on the clipboard. */ 069 private int width; 070 071 /** The height of the chart on the clipboard. */ 072 private int height; 073 074 /** 075 * The smallest width at which the chart will be drawn (if necessary, the 076 * chart will then be scaled down to fit the requested width). 077 * 078 * @since 1.0.14 079 */ 080 private int minDrawWidth; 081 082 /** 083 * The smallest height at which the chart will be drawn (if necessary, the 084 * chart will then be scaled down to fit the requested height). 085 * 086 * @since 1.0.14 087 */ 088 private int minDrawHeight; 089 090 /** 091 * The largest width at which the chart will be drawn (if necessary, the 092 * chart will then be scaled up to fit the requested width). 093 * 094 * @since 1.0.14 095 */ 096 private int maxDrawWidth; 097 098 /** 099 * The largest height at which the chart will be drawn (if necessary, the 100 * chart will then be scaled up to fit the requested height). 101 * 102 * @since 1.0.14 103 */ 104 private int maxDrawHeight; 105 106 /** 107 * Creates a new chart selection. 108 * 109 * @param chart the chart. 110 * @param width the chart width. 111 * @param height the chart height. 112 */ 113 public ChartTransferable(JFreeChart chart, int width, int height) { 114 this(chart, width, height, true); 115 } 116 117 /** 118 * Creates a new chart selection. 119 * 120 * @param chart the chart. 121 * @param width the chart width. 122 * @param height the chart height. 123 * @param cloneData clone the dataset(s)? 124 */ 125 public ChartTransferable(JFreeChart chart, int width, int height, 126 boolean cloneData) { 127 this(chart, width, height, 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, 128 true); 129 } 130 131 /** 132 * Creates a new chart selection. The minimum and maximum drawing 133 * dimensions are used to match the scaling behaviour in the 134 * {@link ChartPanel} class. 135 * 136 * @param chart the chart. 137 * @param width the chart width. 138 * @param height the chart height. 139 * @param minDrawW the minimum drawing width. 140 * @param minDrawH the minimum drawing height. 141 * @param maxDrawW the maximum drawing width. 142 * @param maxDrawH the maximum drawing height. 143 * @param cloneData clone the dataset(s)? 144 * 145 * @since 1.0.14 146 */ 147 public ChartTransferable(JFreeChart chart, int width, int height, 148 int minDrawW, int minDrawH, int maxDrawW, int maxDrawH, 149 boolean cloneData) { 150 151 // we clone the chart because presumably there can be some delay 152 // between putting this instance on the system clipboard and 153 // actually having the getTransferData() method called... 154 try { 155 this.chart = (JFreeChart) chart.clone(); 156 } 157 catch (CloneNotSupportedException e) { 158 this.chart = chart; 159 } 160 // FIXME: we've cloned the chart, but the dataset(s) aren't cloned 161 // and we should do that 162 this.width = width; 163 this.height = height; 164 this.minDrawWidth = minDrawW; 165 this.minDrawHeight = minDrawH; 166 this.maxDrawWidth = maxDrawW; 167 this.maxDrawHeight = maxDrawH; 168 } 169 170 /** 171 * Returns the data flavors supported. 172 * 173 * @return The data flavors supported. 174 */ 175 public DataFlavor[] getTransferDataFlavors() { 176 return new DataFlavor[] {this.imageFlavor}; 177 } 178 179 /** 180 * Returns <code>true</code> if the specified flavor is supported. 181 * 182 * @param flavor the flavor. 183 * 184 * @return A boolean. 185 */ 186 public boolean isDataFlavorSupported(DataFlavor flavor) { 187 return this.imageFlavor.equals(flavor); 188 } 189 190 /** 191 * Returns the content for the requested flavor, if it is supported. 192 * 193 * @param flavor the requested flavor. 194 * 195 * @return The content. 196 * 197 * @throws java.awt.datatransfer.UnsupportedFlavorException 198 * @throws java.io.IOException 199 */ 200 public Object getTransferData(DataFlavor flavor) 201 throws UnsupportedFlavorException, IOException { 202 203 if (this.imageFlavor.equals(flavor)) { 204 return createBufferedImage(this.chart, this.width, this.height, 205 this.minDrawWidth, this.minDrawHeight, this.maxDrawWidth, 206 this.maxDrawHeight); 207 } 208 else { 209 throw new UnsupportedFlavorException(flavor); 210 } 211 } 212 213 /** 214 * A utility method that creates an image of a chart, with scaling. 215 * 216 * @param chart the chart. 217 * @param w the image width. 218 * @param h the image height. 219 * @param minDrawW the minimum width for chart drawing. 220 * @param minDrawH the minimum height for chart drawing. 221 * @param maxDrawW the maximum width for chart drawing. 222 * @param maxDrawH the maximum height for chart drawing. 223 * 224 * @return A chart image. 225 * 226 * @since 1.0.14 227 */ 228 private BufferedImage createBufferedImage(JFreeChart chart, int w, int h, 229 int minDrawW, int minDrawH, int maxDrawW, int maxDrawH) { 230 231 BufferedImage image = new BufferedImage(w, h, 232 BufferedImage.TYPE_INT_ARGB); 233 Graphics2D g2 = image.createGraphics(); 234 235 // work out if scaling is required... 236 boolean scale = false; 237 double drawWidth = w; 238 double drawHeight = h; 239 double scaleX = 1.0; 240 double scaleY = 1.0; 241 if (drawWidth < minDrawW) { 242 scaleX = drawWidth / minDrawW; 243 drawWidth = minDrawW; 244 scale = true; 245 } 246 else if (drawWidth > maxDrawW) { 247 scaleX = drawWidth / maxDrawW; 248 drawWidth = maxDrawW; 249 scale = true; 250 } 251 if (drawHeight < minDrawH) { 252 scaleY = drawHeight / minDrawH; 253 drawHeight = minDrawH; 254 scale = true; 255 } 256 else if (drawHeight > maxDrawH) { 257 scaleY = drawHeight / maxDrawH; 258 drawHeight = maxDrawH; 259 scale = true; 260 } 261 262 Rectangle2D chartArea = new Rectangle2D.Double(0.0, 0.0, drawWidth, 263 drawHeight); 264 if (scale) { 265 AffineTransform st = AffineTransform.getScaleInstance(scaleX, 266 scaleY); 267 g2.transform(st); 268 } 269 chart.draw(g2, chartArea, null, null); 270 g2.dispose(); 271 return image; 272 273 } 274 275}