/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.diagram.adapter; import java.awt.Point; import java.awt.geom.Rectangle2D; import org.simantics.Simantics; import org.simantics.databoard.Bindings; import org.simantics.db.AsyncReadGraph; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.procedure.guarded.GuardedAsyncProcedureWrapper; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.request.UnaryAsyncRead; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.AsyncProcedure; import org.simantics.diagram.elements.SVGImage; import org.simantics.diagram.stubs.G2DResource; import org.simantics.diagram.synchronization.SynchronizationHints; import org.simantics.diagram.synchronization.graph.TransformSynchronizer; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.diagram.DiagramHints; import org.simantics.g2d.diagram.IDiagram; import org.simantics.g2d.element.ElementClass; import org.simantics.g2d.element.ElementHints; import org.simantics.g2d.element.IElement; import org.simantics.g2d.element.handler.impl.DefaultTransform; import org.simantics.g2d.element.handler.impl.SimpleElementLayers; import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; import org.simantics.g2d.element.handler.impl.StaticSymbolImageInitializer; import org.simantics.g2d.element.handler.impl.StaticSymbolImpl; import org.simantics.g2d.element.handler.impl.TextImpl; import org.simantics.g2d.elementclass.ImageClass.ImageElementHandler; import org.simantics.g2d.image.DefaultImages; import org.simantics.g2d.image.Image; import org.simantics.g2d.image.ProviderUtils; import org.simantics.scenegraph.g2d.nodes.SVGNode; import org.simantics.utils.Development; import org.simantics.utils.datastructures.cache.IFactory; import org.simantics.utils.datastructures.cache.ProvisionException; import org.simantics.utils.ui.ErrorLogger; /** * An {@link ElementFactory} for DIA.SVGElement instances. * *

* Loads element layers, transform and SVG document. * * @author Tuukka Lehtonen */ public class SVGElementClassFactory extends ElementFactoryAdapter { public static final ElementFactory INSTANCE = new SVGElementClassFactory(); private static final StaticSymbolImpl STATIC_SYMBOL = new StaticSymbolImpl(DefaultImages.SVG.get()); static class ClassRequest extends UnaryAsyncRead { public ClassRequest(Resource elementType) { super(elementType); } @Override public void perform(AsyncReadGraph graph, AsyncProcedure procedure) { createClass(graph, parameter, procedure); } } @Override public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, final Resource elementType, final AsyncProcedure procedure) { graph.asyncRequest(new ClassRequest(elementType), new TransientCacheAsyncListener() { @Override public void exception(AsyncReadGraph graph, Throwable t) { procedure.exception(graph, t); } @Override public void execute(AsyncReadGraph graph, ElementClass result) { procedure.execute(graph, result); } }); } static void createClass(AsyncReadGraph graph, final Resource elementType, final AsyncProcedure procedure) { String id = "SVGElement: " + elementType.getResourceId(); procedure.execute(graph, ElementClass.compile( TextImpl.INSTANCE, new StaticObjectAdapter(elementType), DefaultTransform.INSTANCE, StaticSymbolImageInitializer.INSTANCE, STATIC_SYMBOL, ImageElementHandler.INSTANCE, SimpleElementLayers.INSTANCE) .setId(id)); } @Override public void load(AsyncReadGraph graph, final ICanvasContext canvas, final IDiagram diagram, final Resource element, final IElement e, final AsyncProcedure procedure) { e.setHint(SynchronizationHints.HINT_SYNCHRONIZER, TransformSynchronizer.INSTANCE); final GuardedAsyncProcedureWrapper guard = new GuardedAsyncProcedureWrapper(procedure, 3); loadSVG(graph, diagram, element, e, guard); ElementFactoryUtil.loadLayersForElement(graph, diagram, e, element, guard); ElementFactoryUtil.readTransform(graph, element, e, guard); } private void loadSVG(AsyncReadGraph graph, final IDiagram diagram, final Resource element, final IElement e, final AsyncProcedure guard) { G2DResource G2D = graph.getService(G2DResource.class); graph.forPossibleRelatedValue(element, G2D.HasSVGDocument, Bindings.STRING, new AsyncProcedure() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { guard.exception(graph, throwable); } @Override public void execute(AsyncReadGraph graph, final String svgDocument) { if (svgDocument != null) { if(Development.DEVELOPMENT) { Rectangle2D bounds = SVGNode.getRealBounds(svgDocument); if(bounds != null && bounds.isEmpty()) { Simantics.async(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { System.err.println("Graphics for element " + NameUtils.getSafeName(graph, element) + " are empty."); } }); } } Point referenceSize = diagram.getHint(DiagramHints.KEY_ELEMENT_RASTER_TARGET_SIZE); IFactory img = SVGImage.createFactoryFromString(String.valueOf(element.getResourceId()), svgDocument, referenceSize); try { img = ProviderUtils.rasterize(img); e.setHint(ElementHints.KEY_IMAGE, img.get()); guard.execute(graph, e); } catch (ProvisionException ex) { ErrorLogger.defaultLogError(ex); e.setHint(ElementHints.KEY_IMAGE, DefaultImages.SVG.get()); guard.execute(graph, e); } } else { e.setHint(ElementHints.KEY_IMAGE, DefaultImages.UNKNOWN.get()); guard.execute(graph, e); } } }); } }