001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2014, 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 * ChartTransferable.java 029 * ---------------------- 030 * (C) Copyright 2009-2014, 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 @Override 176 public DataFlavor[] getTransferDataFlavors() { 177 return new DataFlavor[] {this.imageFlavor}; 178 } 179 180 /** 181 * Returns <code>true</code> if the specified flavor is supported. 182 * 183 * @param flavor the flavor. 184 * 185 * @return A boolean. 186 */ 187 @Override 188 public boolean isDataFlavorSupported(DataFlavor flavor) { 189 return this.imageFlavor.equals(flavor); 190 } 191 192 /** 193 * Returns the content for the requested flavor, if it is supported. 194 * 195 * @param flavor the requested flavor. 196 * 197 * @return The content. 198 * 199 * @throws java.awt.datatransfer.UnsupportedFlavorException if the flavor 200 * is not supported. 201 * @throws java.io.IOException if there is an IO problem. 202 */ 203 @Override 204 public Object getTransferData(DataFlavor flavor) 205 throws UnsupportedFlavorException, IOException { 206 if (this.imageFlavor.equals(flavor)) { 207 return createBufferedImage(this.chart, this.width, this.height, 208 this.minDrawWidth, this.minDrawHeight, this.maxDrawWidth, 209 this.maxDrawHeight); 210 } else { 211 throw new UnsupportedFlavorException(flavor); 212 } 213 } 214 215 /** 216 * A utility method that creates an image of a chart, with scaling. 217 * 218 * @param chart the chart. 219 * @param w the image width. 220 * @param h the image height. 221 * @param minDrawW the minimum width for chart drawing. 222 * @param minDrawH the minimum height for chart drawing. 223 * @param maxDrawW the maximum width for chart drawing. 224 * @param maxDrawH the maximum height for chart drawing. 225 * 226 * @return A chart image. 227 * 228 * @since 1.0.14 229 */ 230 private BufferedImage createBufferedImage(JFreeChart chart, int w, int h, 231 int minDrawW, int minDrawH, int maxDrawW, int maxDrawH) { 232 233 BufferedImage image = new BufferedImage(w, h, 234 BufferedImage.TYPE_INT_ARGB); 235 Graphics2D g2 = image.createGraphics(); 236 237 // work out if scaling is required... 238 boolean scale = false; 239 double drawWidth = w; 240 double drawHeight = h; 241 double scaleX = 1.0; 242 double scaleY = 1.0; 243 if (drawWidth < minDrawW) { 244 scaleX = drawWidth / minDrawW; 245 drawWidth = minDrawW; 246 scale = true; 247 } 248 else if (drawWidth > maxDrawW) { 249 scaleX = drawWidth / maxDrawW; 250 drawWidth = maxDrawW; 251 scale = true; 252 } 253 if (drawHeight < minDrawH) { 254 scaleY = drawHeight / minDrawH; 255 drawHeight = minDrawH; 256 scale = true; 257 } 258 else if (drawHeight > maxDrawH) { 259 scaleY = drawHeight / maxDrawH; 260 drawHeight = maxDrawH; 261 scale = true; 262 } 263 264 Rectangle2D chartArea = new Rectangle2D.Double(0.0, 0.0, drawWidth, 265 drawHeight); 266 if (scale) { 267 AffineTransform st = AffineTransform.getScaleInstance(scaleX, 268 scaleY); 269 g2.transform(st); 270 } 271 chart.draw(g2, chartArea, null, null); 272 g2.dispose(); 273 return image; 274 275 } 276 277}