Source for org.jfree.report.util.ComponentDrawable

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
   9:  *
  10:  * This library is free software; you can redistribute it and/or modify it under the terms
  11:  * of the GNU Lesser General Public License as published by the Free Software Foundation;
  12:  * either version 2.1 of the License, or (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  15:  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16:  * See the GNU Lesser General Public License for more details.
  17:  *
  18:  * You should have received a copy of the GNU Lesser General Public License along with this
  19:  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20:  * Boston, MA 02111-1307, USA.
  21:  *
  22:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  23:  * in the United States and other countries.]
  24:  *
  25:  * ------------
  26:  * $Id: ComponentDrawable.java 3525 2007-10-16 11:43:48Z tmorgner $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: 
  32: package org.jfree.report.util;
  33: 
  34: import java.awt.Component;
  35: import java.awt.Dimension;
  36: import java.awt.Graphics2D;
  37: import java.awt.Window;
  38: import java.awt.geom.Rectangle2D;
  39: import javax.swing.JComponent;
  40: import javax.swing.JFrame;
  41: import javax.swing.JPanel;
  42: import javax.swing.RepaintManager;
  43: import javax.swing.SwingUtilities;
  44: 
  45: import org.jfree.ui.ExtendedDrawable;
  46: import org.jfree.util.Log;
  47: 
  48: /**
  49:  * Creation-Date: 11.10.2005, 14:03:15
  50:  *
  51:  * @author Thomas Morgner
  52:  */
  53: public class ComponentDrawable implements ExtendedDrawable
  54: {
  55:   private class PainterRunnable implements Runnable
  56:   {
  57:     private Rectangle2D area;
  58:     private Graphics2D graphics;
  59: 
  60:     private PainterRunnable()
  61:     {
  62:     }
  63: 
  64:     public Graphics2D getGraphics()
  65:     {
  66:       return graphics;
  67:     }
  68: 
  69:     public void setGraphics(final Graphics2D graphics)
  70:     {
  71:       this.graphics = graphics;
  72:     }
  73: 
  74:     public Rectangle2D getArea()
  75:     {
  76:       return area;
  77:     }
  78: 
  79:     public void setArea(final Rectangle2D area)
  80:     {
  81:       this.area = area;
  82:     }
  83: 
  84:     public void run()
  85:     {
  86:       if (component instanceof Window)
  87:       {
  88:         component.addNotify();
  89:       }
  90:       else if (isOwnPeerConnected())
  91:       {
  92:         final Window w = getWindowAncestor(component);
  93:         w.validate();
  94:       }
  95:       else
  96:       {
  97:         peerSupply.pack();
  98:         contentPane.add(component);
  99:       }
 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: }