001 /** 002 * ======================================== 003 * JFreeReport : a free Java report library 004 * ======================================== 005 * 006 * Project Info: http://reporting.pentaho.org/ 007 * 008 * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors. 009 * 010 * This library is free software; you can redistribute it and/or modify it under the terms 011 * of the GNU Lesser General Public License as published by the Free Software Foundation; 012 * either version 2.1 of the License, or (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 016 * See the GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public License along with this 019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 020 * Boston, MA 02111-1307, USA. 021 * 022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 023 * in the United States and other countries.] 024 * 025 * ------------ 026 * $Id: ComponentDrawable.java 3525 2007-10-16 11:43:48Z tmorgner $ 027 * ------------ 028 * (C) Copyright 2000-2005, by Object Refinery Limited. 029 * (C) Copyright 2005-2007, by Pentaho Corporation. 030 */ 031 032 package org.jfree.report.util; 033 034 import java.awt.Component; 035 import java.awt.Dimension; 036 import java.awt.Graphics2D; 037 import java.awt.Window; 038 import java.awt.geom.Rectangle2D; 039 import javax.swing.JComponent; 040 import javax.swing.JFrame; 041 import javax.swing.JPanel; 042 import javax.swing.RepaintManager; 043 import javax.swing.SwingUtilities; 044 045 import org.jfree.ui.ExtendedDrawable; 046 import org.jfree.util.Log; 047 048 /** 049 * Creation-Date: 11.10.2005, 14:03:15 050 * 051 * @author Thomas Morgner 052 */ 053 public class ComponentDrawable implements ExtendedDrawable 054 { 055 private class PainterRunnable implements Runnable 056 { 057 private Rectangle2D area; 058 private Graphics2D graphics; 059 060 private PainterRunnable() 061 { 062 } 063 064 public Graphics2D getGraphics() 065 { 066 return graphics; 067 } 068 069 public void setGraphics(final Graphics2D graphics) 070 { 071 this.graphics = graphics; 072 } 073 074 public Rectangle2D getArea() 075 { 076 return area; 077 } 078 079 public void setArea(final Rectangle2D area) 080 { 081 this.area = area; 082 } 083 084 public void run() 085 { 086 if (component instanceof Window) 087 { 088 component.addNotify(); 089 } 090 else if (isOwnPeerConnected()) 091 { 092 final Window w = getWindowAncestor(component); 093 w.validate(); 094 } 095 else 096 { 097 peerSupply.pack(); 098 contentPane.add(component); 099 } 100 101 component.setBounds 102 ((int) area.getX(), (int) area.getY(), 103 (int) area.getWidth(), (int) area.getHeight()); 104 component.validate(); 105 component.paint(graphics); 106 107 } 108 } 109 110 private boolean preserveAspectRatio; 111 private Component component; 112 private JFrame peerSupply; 113 private JPanel contentPane; 114 private PainterRunnable runnable; 115 private boolean paintSynchronously; 116 private boolean allowOwnPeer; 117 118 public ComponentDrawable() 119 { 120 peerSupply = new JFrame(); 121 peerSupply.pack(); // add a peer ... 122 contentPane = new JPanel(); 123 contentPane.setLayout(null); 124 peerSupply.setContentPane(contentPane); 125 runnable = new PainterRunnable(); 126 } 127 128 public boolean isAllowOwnPeer() 129 { 130 return allowOwnPeer; 131 } 132 133 public void setAllowOwnPeer(final boolean allowOwnPeer) 134 { 135 this.allowOwnPeer = allowOwnPeer; 136 } 137 138 public boolean isPaintSynchronously() 139 { 140 return paintSynchronously; 141 } 142 143 public void setPaintSynchronously(final boolean paintSynchronously) 144 { 145 this.paintSynchronously = paintSynchronously; 146 } 147 148 private void cleanUp () 149 { 150 if (component instanceof JComponent && isOwnPeerConnected() == false) 151 { 152 final JComponent jc = (JComponent) component; 153 RepaintManager.currentManager(jc).removeInvalidComponent(jc); 154 RepaintManager.currentManager(jc).markCompletelyClean(jc); 155 } 156 contentPane.removeAll(); 157 RepaintManager.currentManager(contentPane).removeInvalidComponent(contentPane); 158 RepaintManager.currentManager(contentPane).markCompletelyClean(contentPane); 159 peerSupply.dispose(); 160 } 161 162 public Component getComponent() 163 { 164 return component; 165 } 166 167 public void setComponent(final Component component) 168 { 169 this.component = component; 170 prepareComponent(component); 171 } 172 173 public synchronized Dimension getPreferredSize() 174 { 175 if (component == null) 176 { 177 return new Dimension(0,0); 178 } 179 if (component instanceof Window == false && 180 isOwnPeerConnected() == false) 181 { 182 peerSupply.pack(); 183 contentPane.add(component); 184 contentPane.validate(); 185 component.validate(); 186 } 187 else if (isOwnPeerConnected()) 188 { 189 return component.getSize(); 190 } 191 else 192 { 193 component.validate(); 194 } 195 final Dimension retval = component.getPreferredSize(); 196 cleanUp(); 197 return retval; 198 } 199 200 private boolean isOwnPeerConnected() 201 { 202 if (allowOwnPeer == false) 203 { 204 return false; 205 } 206 final Window windowAncestor = getWindowAncestor(component); 207 return (windowAncestor != null && windowAncestor != peerSupply); 208 } 209 210 protected static Window getWindowAncestor(final Component component) 211 { 212 Component parent = component.getParent(); 213 while (parent != null) 214 { 215 if (parent instanceof Window) 216 { 217 return (Window) parent; 218 } 219 parent = parent.getParent(); 220 } 221 return null; 222 } 223 224 public void setPreserveAspectRatio(final boolean preserveAspectRatio) 225 { 226 this.preserveAspectRatio = preserveAspectRatio; 227 } 228 229 public boolean isPreserveAspectRatio() 230 { 231 return preserveAspectRatio; 232 } 233 234 public synchronized void draw(final Graphics2D g2, final Rectangle2D area) 235 { 236 if (component == null) 237 { 238 return; 239 } 240 241 runnable.setArea(area); 242 runnable.setGraphics(g2); 243 244 if (SwingUtilities.isEventDispatchThread() || paintSynchronously == false) 245 { 246 runnable.run(); 247 } 248 else 249 { 250 try 251 { 252 SwingUtilities.invokeAndWait(runnable); 253 } 254 catch (Exception e) 255 { 256 Log.warn ("Failed to redraw the component."); 257 } 258 } 259 260 cleanUp(); 261 } 262 263 private void prepareComponent (final Component c) 264 { 265 if (c instanceof JComponent) 266 { 267 final JComponent jc = (JComponent) c; 268 jc.setDoubleBuffered(false); 269 final Component[] childs = jc.getComponents(); 270 for (int i = 0; i < childs.length; i++) 271 { 272 final Component child = childs[i]; 273 prepareComponent(child); 274 } 275 } 276 } 277 }