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,v 1.9 2007/04/01 18:49:33 taqua Exp $
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 public 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 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 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(Graphics2D g2, 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 (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 }