package net.xoetrope.optional.svg.batik;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Dimension2D;
import java.net.URL;
import java.util.Iterator;
import javax.swing.ButtonModel;
import javax.swing.JComponent;
import net.xoetrope.optional.svg.HitTester;
import org.apache.batik.swing.gvt.Overlay;
import org.apache.batik.swing.svg.GVTTreeBuilderAdapter;
import org.apache.batik.swing.svg.GVTTreeBuilderEvent;
import org.apache.batik.swing.svg.JSVGComponent;
import org.jdesktop.swingx.painter.Painter;
/**
* A painter that renders an SVG image
* @author luano
*/
public class XSvgPainter extends JSVGComponent implements Painter, HitTester
{
private AffineTransform originalTransform;
private boolean isLoaded;
private Dimension initialDim;
private Component parentComp;
// protected SVGDiagram diagram;
// protected int oldWidth, oldHeight;
//
// protected Color bkColor;
//
// protected Group mask;
// protected SVGElement rollover, rolloverp;
// protected SVGElement pressed, pressedp;
//
// protected double scaleX, scaleY;
//
// private JComponent component;
// private boolean oldRc, oldPressed;
// private boolean rolloverRemoved, pressedRemoved;
private ButtonModel bm;
/**
* Creates a new instance of XSvgPainter
*/
public XSvgPainter()
{
this.initialDim = initialDim;
this.isLoaded = false;
this.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() {
public void gvtBuildCompleted(GVTTreeBuilderEvent e) {
originalTransform = getRenderingTransform();
Dimension2D fileContentsDim = getSVGDocumentSize();
if ( initialDim != null ) {
double coef = initialDim.getWidth() / fileContentsDim.getWidth();
AffineTransform at = AffineTransform.getScaleInstance(coef, coef);
setSize( initialDim) ;
if (at != null) {
at.concatenate(originalTransform);
setRenderingTransform(at, true);
isLoaded = true;
if ( getParent() != null ) {
parentComp.doLayout();
parentComp.repaint();
}
}
}
else
parentComp.repaint();
}
});
this.setOpaque(false);
// Apparently the JGVTComponent doesn't respect the
// opacity in paintComponent.
this.setBackground(new Color(0x0, true));
}
/**
* Creates a new instance of XSvgPainter
*/
public XSvgPainter( Component host )
{
parentComp = host;
this.initialDim = initialDim;
this.isLoaded = false;
this.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() {
public void gvtBuildCompleted(GVTTreeBuilderEvent e) {
originalTransform = getRenderingTransform();
Dimension2D fileContentsDim = getSVGDocumentSize();
if ( initialDim != null ) {
double coef = initialDim.getWidth() / fileContentsDim.getWidth();
AffineTransform at = AffineTransform.getScaleInstance(coef, coef);
setSize( initialDim) ;
if (at != null) {
at.concatenate(originalTransform);
//setRenderingTransform(at, true);
isLoaded = true;
if ( parentComp != null ) {
//parentComp.doLayout();
;//parentComp.repaint();
}
}
}
else
parentComp.repaint();
}
});
this.setOpaque(false);
// Apparently the JGVTComponent doesn't respect the
// opacity in paintComponent.
this.setBackground(new Color(0x0, true));
}
public void setImage( URL imageURL )
{
try {
loadSVGDocument( imageURL.toString());
// diagram = SVGCache.getSVGUniverse().getDiagram( new URI( imageURL.toExternalForm()));
}
catch ( Exception ex )
{
ex.printStackTrace();
}
}
public void paint(Graphics2D g, Object object, int width, int height)
{
paint( g, (JComponent)object, width, height );
}
/**
* <p>Paints on the given Graphics2D object some effect which may or may not
* be related to the given component. For example, BackgroundPainter will
* use the background property of the component and the width/height of the
* component to perform a fill rect. Most other Painters will disregard the
* component entirely, except to get the component width/height.</p>
*
* <p>The Graphics2D object must be returned to the same state it started
* at by the end of the method. For example, if "setColor(c)" was called
* on the graphics object, it should be reset to the original color before
* the method returns.</p>
*
*
* @param g The Graphics2D object in which to paint
* @param component The JComponent that the Painter is delegate for. This
* must not be null.
* @param width
* @param height
*/
public void paint( Graphics2D g, JComponent component, int width, int height )
{
parentComp = component;
Dimension dim = new Dimension( width, height );
initialDim = dim;
if ( !isLoaded )
return;
setSize( dim );
Dimension2D fileContentsDim = getSVGDocumentSize();
double coef = dim.getWidth() / fileContentsDim.getWidth();
AffineTransform at = AffineTransform.getScaleInstance(coef, coef);
if ( at != null ) {
at.concatenate( originalTransform );
//setRenderingTransform(at);
}
if ( !isLoaded )
return;
//g.setTransform( AffineTransform.getTranslateInstance( -x, -y ));
// super.paintComponent( g );
Graphics2D g2d = (Graphics2D)g;
// Rectangle visRect = getRenderRect();
// g2d.setComposite(AlphaComposite.SrcOver);
// g2d.setPaint(getBackground());
// g2d.fillRect(visRect.x, visRect.y,
// visRect.width, visRect.height);
if (image != null) {
if (paintingTransform != null) {
g2d.transform(paintingTransform);
}
g2d.drawRenderedImage(image, null);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
Iterator it = overlays.iterator();
while (it.hasNext()) {
((Overlay)it.next()).paint(g);
}
}
// this.component = component;
// if ( component instanceof AbstractButton )
// bm = ((AbstractButton)component).getModel();
// try {
// if ( bkColor != null ) {
// g.setColor( bkColor );
// g.fillRect( 0, 0, width, height );
// }
//
// //if ( diagram != null ) {
// SVGRoot root = diagram.getRoot();
// // if (( oldWidth != width ) || ( oldHeight != height )) {
// root.setAttribute( "width", AnimationElement.AT_XML, Double.toString( width ));
// root.setAttribute( "height", AnimationElement.AT_XML, Double.toString( height ));
// root.build();
// oldWidth = width;
// oldHeight = height;
//
// mask = (Group)diagram.getElement( "mask" );
// rollover = diagram.getElement( "rollover" );
// if ( rollover != null )
// rolloverp = rollover.getParent();
// pressed = diagram.getElement( "pressed" );
// if ( pressed != null )
// pressedp = pressed.getParent();
// double bbox[] = root.getPresAbsolute( "viewBox" ).getDoubleList();
// scaleX = bbox[ 2 ] / root.getPresAbsolute( "width" ).getDoubleValue();
// scaleY = bbox[ 3 ] / root.getPresAbsolute( "height" ).getDoubleValue();
// //}
//
// diagram.render( g );
// //}
// }
// catch ( Exception ex ) {
// ex.printStackTrace();
// }
}
public void setBackground( Color c )
{
// bkColor = c;
}
public boolean contains( int x, int y )
{
// boolean rc = true;
// if ( mask != null )
// rc = mask.getShape().contains( scaleX * x, scaleY * y );
//
// try {
// if ( rollover != null ) {
// if ( !rc && !rolloverRemoved ) {
// rollover.setAttribute( "visibility", AnimationElement.AT_XML, "hidden" );
// rolloverRemoved = true;
// }
// else if ( rc && rolloverRemoved ) {
// rollover.setAttribute( "visibility", AnimationElement.AT_XML, "visible" );
// rolloverRemoved = false;
// }
// if ( rc != oldRc )
// component.repaint();
// }
// }
// catch ( Exception ex )
// {
// ex.printStackTrace();
// }
//
// if ( bm != null ) {
// try {
// if ( bm.isPressed() && !pressedRemoved ) {
// pressed.setAttribute( "visibility", AnimationElement.AT_XML, "hidden" );
// pressedRemoved = true;
// }
// else if ( !bm.isPressed() && pressedRemoved ) {
// pressed.setAttribute( "visibility", AnimationElement.AT_XML, "visible" );
// pressedRemoved = false;
// }
// if ( bm.isPressed() != oldPressed )
// component.repaint();
// }
// catch ( Exception ex )
// {
// ex.printStackTrace();
// }
// oldPressed = bm.isPressed();
// oldRc = rc;
// }
//
// return rc;
return false;
}
}