/******************************************************************************* * 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.Shape; import java.awt.geom.AffineTransform; import java.util.Collections; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; import org.simantics.databoard.Bindings; import org.simantics.db.AsyncReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.primitiverequest.PossibleAdapter; import org.simantics.db.common.procedure.adapter.AsyncProcedureAdapter; import org.simantics.db.common.procedure.adapter.ProcedureAdapter; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.procedure.guarded.GuardedAsyncProcedureWrapper; import org.simantics.db.common.request.BinaryAsyncRead; import org.simantics.db.common.request.SafeName; import org.simantics.db.procedure.AsyncMultiProcedure; import org.simantics.db.procedure.AsyncProcedure; import org.simantics.diagram.content.ResourceTerminal; import org.simantics.diagram.stubs.DiagramResource; 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.IDiagram; import org.simantics.g2d.element.ElementClass; import org.simantics.g2d.element.ElementUtils; import org.simantics.g2d.element.IElement; import org.simantics.g2d.element.handler.impl.DefaultParameters; import org.simantics.g2d.element.handler.impl.DefaultTransform; import org.simantics.g2d.element.handler.impl.ObjectTerminal; 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.PlainElementPropertySetter; import org.simantics.g2d.tooltip.TerminalTooltipProvider; import org.simantics.g2d.tooltip.TooltipParticipant; import org.simantics.g2d.utils.geom.DirectionSet; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.utils.Container; /** * @author Tuukka Lehtonen * * TODO: not merged https://www.simulationsite.net/trac/simantics/changeset/14463/2d/trunk/org.simantics.diagram/src/org/simantics/diagram/adapter/GraphToDiagramSynchronizer.java */ public class DefinedElementFactory extends ElementFactoryAdapter { protected static class ShapeContainer implements Container { private IElement element; private Shape shape = null; public ShapeContainer(IElement element) { this.element = element; } @Override public Shape get() { if(shape == null) { shape = ElementUtils.getElementShapeOrBounds(element); element = null; } return shape; } } static class ClassRequest extends BinaryAsyncRead { final private IDiagram diagram; public ClassRequest(Resource elementType, ICanvasContext canvas, IDiagram diagram) { super(elementType, canvas); this.diagram = diagram; } @Override public void perform(AsyncReadGraph graph, AsyncProcedure procedure) { createzz(graph, parameter2, diagram, parameter, procedure); } } @Override public void create(AsyncReadGraph graph, final ICanvasContext canvas, final IDiagram diagram, final Resource elementType, final AsyncProcedure procedure) { graph.asyncRequest(new ClassRequest(elementType, canvas, diagram), new TransientCacheAsyncListener() { @Override public void exception(AsyncReadGraph graph, Throwable t) { t.printStackTrace(); procedure.exception(graph, t); } @Override public void execute(AsyncReadGraph graph, ElementClass result) { procedure.execute(graph, result); } }); } public static void createzz(AsyncReadGraph graph, final ICanvasContext canvas, final IDiagram diagram, final Resource elementType, final AsyncProcedure procedure) { final StructuralResource2 sr = graph.getService(StructuralResource2.class); final G2DResource g2d = graph.getService(G2DResource.class); final DiagramResource dr = graph.getService(DiagramResource.class); graph.forSingleObject(elementType, sr.IsDefinedBy, new AsyncProcedure() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { graph.asyncRequest(new SafeName(elementType), new ProcedureAdapter() { @Override public void execute(String result) { System.out.println("DefinedElement '" + result + " ' does not have a single IsDefinedBy relation"); } }); procedure.exception(graph, throwable); } @Override public void execute(AsyncReadGraph graph, final Resource definingResource) { graph.asyncRequest(new NodeRequest(canvas, diagram, definingResource, null), new TransientCacheAsyncListener() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { throwable.printStackTrace(); } @Override public void execute(AsyncReadGraph graph, final IElement e) { final CompositeImage img = new CompositeImage(Collections.singletonList(e)); final ConcurrentLinkedQueue terminals = new ConcurrentLinkedQueue(); final AtomicInteger ready = new AtomicInteger(1); graph.forOrderedSet(definingResource, new AsyncMultiProcedure() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { throwable.printStackTrace(); } @Override public void execute(AsyncReadGraph graph, final Resource r) { ready.incrementAndGet(); graph.forIsInstanceOf(r, dr.Terminal, new AsyncProcedure() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { throwable.printStackTrace(); } public void execute(AsyncReadGraph graph, Boolean isTerminal) { if (isTerminal) { graph.asyncRequest(new NodeRequest(canvas, diagram, r, null), new TransientCacheAsyncListener() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { throwable.printStackTrace(); } @Override public void execute(AsyncReadGraph graph, final IElement t) { graph.forPossibleRelatedValue(r, g2d.HasTransform, Bindings.DOUBLE_ARRAY, new AsyncProcedure() { @Override public void exception(AsyncReadGraph graph, Throwable throwable) { throwable.printStackTrace(); } @Override public void execute(AsyncReadGraph graph, double[] mat) { AffineTransform tr = mat != null ? new AffineTransform(mat) : new AffineTransform(); terminals.add(new ResourceTerminal(r, tr, DirectionSet.ANY, new ShapeContainer(t))); worked(graph); } }); } }); } else { worked(graph); } } }); } @Override public void finished(AsyncReadGraph graph) { worked(graph); } void worked(AsyncReadGraph graph) { if (ready.decrementAndGet() == 0) { String id = "DefinedElement: " + elementType.getResourceId(); procedure.execute(graph, ElementClass.compile( TextImpl.INSTANCE, new StaticObjectAdapter(elementType), DefaultTransform.INSTANCE, DefaultParameters.INSTANCE, StaticSymbolImageInitializer.INSTANCE, new StaticSymbolImpl(img), DefinedElementHandler.INSTANCE, new DefinedElementTerminals(terminals), SimpleElementLayers.INSTANCE, PlainElementPropertySetter.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); // FIXME : this just adds test tooltip to the element. //e.setHint(TooltipParticipant.TOOLTIP_KEY, DefinedElementTooltipProvider.INSTANCE); // This is needed for terminal tooltips. e.setHint(TooltipParticipant.TOOLTIP_KEY, TerminalTooltipProvider.INSTANCE); graph.asyncRequest(new PossibleAdapter(element, ElementFactory.class), new AsyncProcedureAdapter() { @Override public void execute(AsyncReadGraph graph, ElementFactory factory) { if (factory != null) { graph.asyncRequest(new GetElementClassRequest(factory, element, canvas, diagram)); } } }); ElementFactoryUtil.readParameters(graph, element, e); GuardedAsyncProcedureWrapper guard = new GuardedAsyncProcedureWrapper(procedure, 1); ElementFactoryUtil.readTransform(graph, element, e, guard); // graph.asyncRequest(new SafeName(resource), new ProcedureAdapter() { // @Override // public void execute(String result) { // System.out.println("DefinedElementFactory.load: " + result); // } // }); } }