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