From: lempinen Date: Wed, 11 Aug 2010 07:02:56 +0000 (+0000) Subject: Hopefully undoing the little "upsista" X-Git-Tag: simantics-1.2.0~122 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=fdbbe73147682fbf584376f89a7f5e13b2ee6595;p=simantics%2Fsysdyn.git Hopefully undoing the little "upsista" git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@17080 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/Activator.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/Activator.java new file mode 100644 index 00000000..988e479d --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/Activator.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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.sysdyn.ui; + +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.SimpleLayout; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.resource.ResourceManager; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.simantics.sysdyn.ui"; + + // The shared instance + private static Activator plugin; + + private static LocalResourceManager resourceManager; + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + ConsoleAppender appender = + new ConsoleAppender(new SimpleLayout()); + BasicConfigurator.configure(appender); + Logger.getRootLogger().setLevel(Level.WARN); + plugin = this; + } + + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + public static Activator getDefault() { + return plugin; + } + + public static ResourceManager initializeResourceManager(Display display) { + if (resourceManager == null) { + resourceManager = new LocalResourceManager(JFaceResources.getResources(display)); + } + return resourceManager; + } + + public static ResourceManager getResources() { + if (resourceManager == null) + throw new IllegalStateException("ResourceManager of bundle '" + PLUGIN_ID + "' is not initialized."); + return resourceManager; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/TestDiagramEditor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/TestDiagramEditor.java new file mode 100644 index 00000000..b85a32c3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/TestDiagramEditor.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.sysdyn.ui; + +import javax.swing.JFrame; + +import org.simantics.h2d.canvas.EditorCanvas; +import org.simantics.h2d.diagram.Diagram; +import org.simantics.h2d.editor.impl.DiagramEditor; +import org.simantics.h2d.event.handler.DefaultEventHandlers; +import org.simantics.sysdyn.ui.actions.Connect; +import org.simantics.sysdyn.ui.actions.CreateAuxiliary; +import org.simantics.sysdyn.ui.actions.CreateCloud; +import org.simantics.sysdyn.ui.actions.CreateStock; +import org.simantics.sysdyn.ui.actions.CreateValve; + +public class TestDiagramEditor extends JFrame { + + public TestDiagramEditor() { + super("Test Canvas"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + Diagram diagram = new Diagram(); + final DiagramEditor editor = new DiagramEditor(getRootPane(), diagram); + + DefaultEventHandlers.configure(editor); + editor.addEventHandler(1, "key(A)", new CreateAuxiliary()); + editor.addEventHandler(1, "key(S)", new CreateStock()); + editor.addEventHandler(1, "key(V)", new CreateValve()); + editor.addEventHandler(1, "key(C)", new CreateCloud()); + editor.addEventHandler(1, "drag(alt+left)", new Connect()); + + getContentPane().add(new EditorCanvas(editor)); + + setSize(800, 600); + } + + public static void main(String[] args) { + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + new TestDiagramEditor().setVisible(true); + } + }); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/Connect.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/Connect.java new file mode 100644 index 00000000..fb379331 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/Connect.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.element.IElement; +import org.simantics.h2d.element.handler.Connectable; +import org.simantics.h2d.event.DragEvent; +import org.simantics.h2d.event.handler.DragEventHandler; +import org.simantics.h2d.node.RectangleNode; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.sysdyn.ui.elements.AuxiliaryElement; +import org.simantics.sysdyn.ui.elements.CloudElement; +import org.simantics.sysdyn.ui.elements.DependencyElement; +import org.simantics.sysdyn.ui.elements.FlowElement; +import org.simantics.sysdyn.ui.elements.StockElement; +import org.simantics.sysdyn.ui.elements.ValveElement; + +public class Connect extends DragEventHandler { + + Connectable from; + Connectable to; + + RectangleNode fromNode = new RectangleNode(); + RectangleNode toNode = new RectangleNode(); + + @Override + protected boolean begin(IDiagramEditor editor, DragEvent event) { + for(IElement element : event.pickedElements) { + Connectable connectable = element.getInterface(Connectable.class); + if(connectable != null) { + this.from = connectable; + return true; + } + } + return false; + } + + @Override + protected void update(IDiagramEditor editor, DragEvent event) { + for(IElement element : editor.pickElements(event.current)) { + Connectable connectable = element.getInterface(Connectable.class); + if(connectable != null && connectable != from) { + if(connectable == to) + return; + to = connectable; + + Rectangle2D bounds = new Rectangle2D.Double(); + to.getBounds(bounds); + bounds.setFrame( + bounds.getX()-2.0, + bounds.getY()-2.0, + bounds.getWidth()+4.0, + bounds.getHeight()+4.0); + toNode.init(bounds); + + editor.requestRepaint(); + return; + } + } + to = null; + toNode.init(fromNode.getBounds()); + editor.requestRepaint(); + } + + @Override + protected void end(IDiagramEditor editor, DragEvent event) { + if(to != null) { + IElement newElement; + if(from instanceof ValveElement && to instanceof StockElement) + newElement = new FlowElement(from, to); + else if(from instanceof StockElement && to instanceof ValveElement) + newElement = new FlowElement(from, to); + else if( (from instanceof StockElement || from instanceof CloudElement) + && (to instanceof StockElement || to instanceof CloudElement)) { + Point2D fromOrigo = from.getOrigo(); + Point2D toOrigo = to.getOrigo(); + newElement = new ValveElement( + 0.5 * (fromOrigo.getX() + toOrigo.getX()), + 0.5 * (fromOrigo.getY() + toOrigo.getY()) + ); + editor.getDiagram().addElement(new FlowElement(from, (ValveElement)newElement)); + editor.getDiagram().addElement(new FlowElement((ValveElement)newElement, to)); + } + else if(from instanceof ValveElement && to instanceof AuxiliaryElement) + newElement = new DependencyElement(to, from); + else if(from instanceof AuxiliaryElement && to instanceof StockElement) + newElement = new DependencyElement(to, from); + else + newElement = new DependencyElement(from, to); + editor.getDiagram().addElement(newElement); + if(newElement instanceof ValveElement) + ((ValveElement)newElement).beginRenameAction(editor); + } + + from = null; + to = null; + } + + @Override + public void init(G2DParentNode parent) { + fromNode = parent.addNode(RectangleNode.class); + toNode = parent.addNode(RectangleNode.class); + + Rectangle2D bounds = new Rectangle2D.Double(); + from.getBounds(bounds); + bounds.setFrame( + bounds.getX()-2.0, + bounds.getY()-2.0, + bounds.getWidth()+4.0, + bounds.getHeight()+4.0); + + fromNode.init(bounds); + toNode.init(bounds); + } + + @Override + public void remove() { + fromNode.remove(); + toNode.remove(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectBase.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectBase.java new file mode 100644 index 00000000..d1cde772 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectBase.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import java.awt.geom.Rectangle2D; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.element.IElement; +import org.simantics.h2d.element.handler.Connectable; +import org.simantics.h2d.event.DragEvent; +import org.simantics.h2d.event.handler.DragEventHandler; +import org.simantics.h2d.node.RectangleNode; +import org.simantics.scenegraph.g2d.G2DParentNode; + +public abstract class ConnectBase extends DragEventHandler { + + protected Connectable from; + protected Connectable to; + + RectangleNode fromNode = new RectangleNode(); + RectangleNode toNode = new RectangleNode(); + + /** + * This is called when starting to make a connection. + */ + protected abstract boolean isAllowedTail(Connectable tail); + + /** + * This is called when the mouse hovers over another connection point. + */ + protected abstract boolean isAllowedHead(Connectable head); + + protected abstract void connect(IDiagramEditor editor); + + @Override + protected boolean begin(IDiagramEditor editor, DragEvent event) { + for(IElement element : event.pickedElements) { + Connectable connectable = element.getInterface(Connectable.class); + if(connectable != null && isAllowedTail(connectable)) { + this.from = connectable; + return true; + } + } + return false; + } + + @Override + protected void update(IDiagramEditor editor, DragEvent event) { + for(IElement element : editor.pickElements(event.current)) { + Connectable connectable = element.getInterface(Connectable.class); + if(connectable != null && connectable != from) { + if(connectable == to) + return; + if(!isAllowedHead(connectable)) + continue; + to = connectable; + + Rectangle2D bounds = new Rectangle2D.Double(); + to.getBounds(bounds); + bounds.setFrame( + bounds.getX()-2.0, + bounds.getY()-2.0, + bounds.getWidth()+4.0, + bounds.getHeight()+4.0); + toNode.init(bounds); + + editor.requestRepaint(); + return; + } + } + to = null; + toNode.init(fromNode.getBounds()); + editor.requestRepaint(); + } + + @Override + protected void end(IDiagramEditor editor, DragEvent event) { + if(to != null) + connect(editor); + + from = null; + to = null; + } + + @Override + public void init(G2DParentNode parent) { + fromNode = parent.addNode(RectangleNode.class); + toNode = parent.addNode(RectangleNode.class); + + Rectangle2D bounds = new Rectangle2D.Double(); + from.getBounds(bounds); + bounds.setFrame( + bounds.getX()-2.0, + bounds.getY()-2.0, + bounds.getWidth()+4.0, + bounds.getHeight()+4.0); + + fromNode.init(bounds); + toNode.init(bounds); + } + + @Override + public void remove() { + fromNode.remove(); + toNode.remove(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectDependency.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectDependency.java new file mode 100644 index 00000000..1392fc48 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectDependency.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.element.handler.Connectable; +import org.simantics.sysdyn.ui.elements.AuxiliaryElement; +import org.simantics.sysdyn.ui.elements.DependencyElement; +import org.simantics.sysdyn.ui.elements.StockElement; +import org.simantics.sysdyn.ui.elements.ValveElement; + +public class ConnectDependency extends ConnectBase { + + @Override + protected boolean isAllowedTail(Connectable tail) { + return tail instanceof AuxiliaryElement + || tail instanceof StockElement + || tail instanceof ValveElement + ; + } + + @Override + protected boolean isAllowedHead(Connectable head) { + return head instanceof AuxiliaryElement + || head instanceof ValveElement + ; + } + + @Override + protected void connect(IDiagramEditor editor) { + editor.getDiagram().addElement(new DependencyElement(from, to)); + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectFlow.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectFlow.java new file mode 100644 index 00000000..4885f7ad --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ConnectFlow.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import java.awt.geom.Point2D; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.element.handler.Connectable; +import org.simantics.sysdyn.ui.elements.CloudElement; +import org.simantics.sysdyn.ui.elements.FlowElement; +import org.simantics.sysdyn.ui.elements.StockElement; +import org.simantics.sysdyn.ui.elements.ValveElement; + +public class ConnectFlow extends ConnectBase { + + @Override + protected boolean isAllowedTail(Connectable tail) { + return tail instanceof CloudElement + || tail instanceof StockElement + || tail instanceof ValveElement + ; + } + + @Override + protected boolean isAllowedHead(Connectable head) { + return head instanceof CloudElement + || head instanceof StockElement + || (head instanceof ValveElement && !(from instanceof ValveElement)) + ; + } + + @Override + protected void connect(IDiagramEditor editor) { + if(from instanceof ValveElement || to instanceof ValveElement) + editor.getDiagram().addElement(new FlowElement(from, to)); + else { + Point2D fromOrigo = from.getOrigo(); + Point2D toOrigo = to.getOrigo(); + ValveElement valveElement = new ValveElement( + 0.5 * (fromOrigo.getX() + toOrigo.getX()), + 0.5 * (fromOrigo.getY() + toOrigo.getY()) + ); + editor.getDiagram().addElement(valveElement); + editor.getDiagram().addElement(new FlowElement(from, valveElement)); + editor.getDiagram().addElement(new FlowElement(valveElement, to)); + + valveElement.beginRenameAction(editor); + } + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateAuxiliary.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateAuxiliary.java new file mode 100644 index 00000000..4bde7cc6 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateAuxiliary.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.h2d.event.ILocatableEvent; +import org.simantics.h2d.event.handler.IEventHandler; +import org.simantics.sysdyn.ui.elements.AuxiliaryElement; + +public class CreateAuxiliary implements IEventHandler { + + @Override + public boolean handle(IDiagramEditor editor, IEvent _event) { + ILocatableEvent event = (ILocatableEvent)_event; + AuxiliaryElement element = new AuxiliaryElement("Auxiliary", + event.getLocation().getX(), + event.getLocation().getY()); + editor.getDiagram().addElement(element); + element.beginRenameAction(editor); + editor.requestRepaint(); + return true; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateCloud.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateCloud.java new file mode 100644 index 00000000..ec03cca2 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateCloud.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.h2d.event.ILocatableEvent; +import org.simantics.h2d.event.handler.IEventHandler; +import org.simantics.sysdyn.ui.elements.CloudElement; + +public class CreateCloud implements IEventHandler { + + @Override + public boolean handle(IDiagramEditor editor, IEvent _event) { + ILocatableEvent event = (ILocatableEvent)_event; + CloudElement element = new CloudElement( + event.getLocation().getX(), + event.getLocation().getY()); + editor.getDiagram().addElement(element); + editor.requestRepaint(); + return true; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateStock.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateStock.java new file mode 100644 index 00000000..104852e5 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateStock.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.h2d.event.ILocatableEvent; +import org.simantics.h2d.event.handler.IEventHandler; +import org.simantics.sysdyn.ui.elements.StockElement; + +public class CreateStock implements IEventHandler { + + @Override + public boolean handle(IDiagramEditor editor, IEvent _event) { + ILocatableEvent event = (ILocatableEvent)_event; + StockElement element = new StockElement("Stock", + event.getLocation().getX(), + event.getLocation().getY()); + editor.getDiagram().addElement(element); + element.beginRenameAction(editor); + editor.requestRepaint(); + return true; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateValve.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateValve.java new file mode 100644 index 00000000..20a8c85d --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/CreateValve.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.h2d.event.ILocatableEvent; +import org.simantics.h2d.event.handler.IEventHandler; +import org.simantics.sysdyn.ui.elements.ValveElement; + +public class CreateValve implements IEventHandler { + + @Override + public boolean handle(IDiagramEditor editor, IEvent _event) { + ILocatableEvent event = (ILocatableEvent)_event; + editor.getDiagram().addElement(new ValveElement( + event.getLocation().getX(), + event.getLocation().getY())); + editor.requestRepaint(); + return true; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/DiagramContextMenuData.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/DiagramContextMenuData.java new file mode 100644 index 00000000..c5c45d9b --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/DiagramContextMenuData.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; + +public class DiagramContextMenuData { + public final IDiagramEditor diagramEditor; + public final IEvent event; + + public DiagramContextMenuData(IDiagramEditor diagramEditor, IEvent event) { + this.diagramEditor = diagramEditor; + this.event = event; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/OpenContextMenu.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/OpenContextMenu.java new file mode 100644 index 00000000..53f89ffa --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/OpenContextMenu.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + +import org.eclipse.jface.action.GroupMarker; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPartSite; +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.h2d.event.ReleaseEvent; +import org.simantics.h2d.event.handler.IEventHandler; + +public class OpenContextMenu implements IEventHandler { + + Control control; + IWorkbenchPartSite site; + String menuId; + + MenuManager menuManager; + + public OpenContextMenu(Control control, IWorkbenchPartSite site, + String menuId) { + super(); + this.control = control; + this.site = site; + this.menuId = menuId; + menuManager = createPopupMenu(); + if (menuManager != null) { + Menu menu = menuManager.createContextMenu(control); + control.setMenu(menu); + if (site != null) { + site.registerContextMenu(menuManager.getId(), menuManager, + site.getSelectionProvider()); + } + } + } + + @Override + public boolean handle(final IDiagramEditor editor, IEvent _event) { + final ReleaseEvent event = (ReleaseEvent)_event; + control.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if (control.isDisposed()) + return; + //Point p = control.toDisplay(event.getLocation().get(int) cp.getX(), (int) cp.getY()); + menuManager.getMenu().setLocation( + new Point((int)event.dispPoint.getX(), (int)event.dispPoint.getY())); + menuManager.getMenu().setData( + new DiagramContextMenuData(editor, event) + ); + menuManager.getMenu().setVisible(true); + } + + }); + return true; + } + + protected MenuManager createPopupMenu() { + final MenuManager mm = new MenuManager("Diagram Popup", menuId); + mm.setRemoveAllWhenShown(true); + mm.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + mm.add(new GroupMarker(IWorkbenchActionConstants.WB_START)); + mm.add(new GroupMarker(IWorkbenchActionConstants.NEW_EXT)); + mm.add(new GroupMarker(IWorkbenchActionConstants.IMPORT_EXT)); + mm.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + mm.add(new GroupMarker(IWorkbenchActionConstants.WB_END)); + } + }); + return mm; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ToggleSimulation.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ToggleSimulation.java new file mode 100644 index 00000000..d92a2de7 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ToggleSimulation.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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.sysdyn.ui.actions; + + +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.State; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.commands.IElementUpdater; +import org.eclipse.ui.menus.UIElement; +import org.simantics.simulation.experiment.IDynamicExperiment; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.sysdyn.manager.SysdynExperiment; +import org.simantics.sysdyn.ui.handlers.RunBasicExperiment; +import org.simantics.ui.SimanticsUI; + +public class ToggleSimulation extends AbstractHandler implements IElementUpdater { + + public static final String COMMAND = "org.simantics.sysdyn.ui.toggleSimulation"; + public static final String STATE = "org.simantics.sysdyn.ui.toggleSimulation.state"; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ICommandService service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = service.getCommand(COMMAND); + State state = command.getState(STATE); + Boolean value = (Boolean) state.getValue(); + value = !value; + state.setValue(value); + service.refreshElements(RunBasicExperiment.COMMAND, null); + + IExperimentManager manager = + SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); + IExperiment experiment = manager.getActiveExperiment(); + if(experiment instanceof SysdynExperiment) { + if(getState()) { + ((SysdynExperiment)experiment).toggleSimulation(true); + } else { + ((SysdynExperiment)experiment).toggleSimulation(false); + } + } + + + return null; + } + + public static Boolean getState() { + ICommandService service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = service.getCommand(COMMAND); + State state = command.getState(STATE); + return (Boolean)state.getValue(); + } + + @SuppressWarnings("unchecked") + @Override + public void updateElement(UIElement element, Map parameters) { + ICommandService commandService = + (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = commandService.getCommand(COMMAND); + boolean checked = (Boolean) command.getState(STATE).getValue(); + element.setChecked(checked); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/SysdynBrowser.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/SysdynBrowser.java new file mode 100644 index 00000000..3fae63c2 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/SysdynBrowser.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.swt.widgets.Composite; +import org.simantics.browsing.ui.swt.ContextMenuInitializer; +import org.simantics.browsing.ui.swt.GraphExplorerView; +import org.simantics.browsing.ui.swt.IContextMenuInitializer; +import org.simantics.browsing.ui.swt.IPropertyPage; +import org.simantics.sysdyn.ui.Activator; +import org.simantics.sysdyn.ui.properties.SysdynPropertyPage; + + +public class SysdynBrowser extends GraphExplorerView { + + private static final Set browseContexts = Collections.singleton("http://www.simantics.org/Sysdyn-1.0/Browser"); + + @Override + protected IContextMenuInitializer getContextMenuInitializer() { + return new ContextMenuInitializer("#SysdynBrowserPopup"); + } + + @Override + protected Set getBrowseContexts() { + return browseContexts; + } + + @Override + protected void createControls(Composite parent) { + // Make sure the resource manager of this plug-in is initialized + // properly before using it in this browser. + Activator.initializeResourceManager(parent.getDisplay()); + + super.createControls(parent); + //IToolBarManager toolBar = getViewSite().getActionBars().getToolBarManager(); + //toolBar.add(new HomeAction()); + } + + @SuppressWarnings("unchecked") + @Override + public Object getAdapter(Class adapter) { + if (adapter == IPropertyPage.class) + return new SysdynPropertyPage(getSite(), Collections.singleton("http://www.simantics.org/Sysdyn-1.0/Browser")); + return super.getAdapter(adapter); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeImager.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeImager.java new file mode 100644 index 00000000..21ae321a --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeImager.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.simantics.browsing.ui.swt.ImagerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.Activator; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; +import org.simantics.sysdyn.ui.browser.nodes.ConfigurationNode; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentNode; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentsFolder; +import org.simantics.sysdyn.ui.browser.nodes.InputNode; +import org.simantics.sysdyn.ui.browser.nodes.ModelNode; +import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; +import org.simantics.sysdyn.ui.browser.nodes.ModuleTypeNode; +import org.simantics.sysdyn.ui.browser.nodes.ModulesNode; +import org.simantics.sysdyn.ui.browser.nodes.OperatingInterfacesFolder; +import org.simantics.sysdyn.ui.browser.nodes.VariableNode; + +public class AbstractNodeImager extends ImagerContributor { + + @Override + public ImageDescriptor getDescriptor(ReadGraph graph, AbstractNode node) throws DatabaseException { + + String image = null; + if (node instanceof ExperimentsFolder || + node instanceof OperatingInterfacesFolder || + node instanceof ModulesNode) + image = "icons/folder.png"; + else if (node instanceof ModuleTypeNode || node instanceof ModuleNode || node instanceof ConfigurationNode) + image = "icons/bricks.png"; + else if (node instanceof ExperimentNode) + image = "icons/time.png"; + else if (node instanceof InputNode) + image = "icons/brick_link.png"; + else if (node instanceof ModelNode) + image = "icons/chart_organisation.png"; + else if (node instanceof VariableNode) + image = "icons/brick.png"; + + if (image != null) + return ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource(image)); + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeLabeler.java new file mode 100644 index 00000000..813365cb --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/AbstractNodeLabeler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; + +public class AbstractNodeLabeler extends LabelerContributor { + + @Override + public String getLabel(ReadGraph graph, AbstractNode node) throws DatabaseException { + if (!graph.hasStatement(node.resource)) + return ""; + return graph.adapt(node.resource, String.class); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java new file mode 100644 index 00000000..086ccde0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java @@ -0,0 +1,51 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; +import org.simantics.sysdyn.ui.browser.nodes.ConfigurationNode; + +public class Configuration extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, ConfigurationNode configuration) throws DatabaseException { + ArrayList result = new ArrayList(); + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + for(Resource r : graph.syncRequest(new ObjectsWithType(configuration.resource, b.ConsistsOf, sr.IndependentVariable))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + for(Resource r : graph.syncRequest(new ObjectsWithType(configuration.resource, b.ConsistsOf, sr.Input))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + for(Resource r : graph.syncRequest(new ObjectsWithType(configuration.resource, b.ConsistsOf, sr.Module))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + return result; + } + + @Override + public String getViewpointId() { + return "Standard"; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ConfigurationLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ConfigurationLabeler.java new file mode 100644 index 00000000..2161aaee --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ConfigurationLabeler.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.ConfigurationNode; + +public class ConfigurationLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, ConfigurationNode conf) throws DatabaseException { + return "Configuration"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Experiment.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Experiment.java new file mode 100644 index 00000000..34bc6adc --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Experiment.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentsFolder; + +public class Experiment extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, ExperimentsFolder experimentsFolder) throws DatabaseException { + ArrayList result = new ArrayList(); + Builtins b = graph.getBuiltins(); + for(Resource r : graph.syncRequest(new ObjectsWithType(experimentsFolder.resource, b.ConsistsOf, b.Experiment))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + return result; + } + + @Override + public String getViewpointId() { + return "Standard"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentLabelDecorator.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentLabelDecorator.java new file mode 100644 index 00000000..b38c9f68 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentLabelDecorator.java @@ -0,0 +1,32 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.eclipse.jface.resource.FontDescriptor; +import org.eclipse.swt.SWT; +import org.simantics.browsing.ui.content.LabelDecorator; +import org.simantics.browsing.ui.graph.contributor.labeler.LabelDecoratorContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentNode; + +public class ExperimentLabelDecorator extends LabelDecoratorContributor { + + @Override + public LabelDecorator getDecorator(ReadGraph graph, ExperimentNode experimentNode) throws DatabaseException { + if (graph.hasStatement(experimentNode.resource, graph.getBuiltins().IsActive)) { + return new LabelDecorator.Stub() { + @Override + public String decorateLabel(String label, String column, int itemIndex) { + return label + " [ACTIVE]"; + } + + @SuppressWarnings("unchecked") + @Override + public F decorateFont(F font, String column, int itemIndex) { + return (F) ((FontDescriptor) font).withStyle(SWT.BOLD); + } + }; + } + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentLabeler.java new file mode 100644 index 00000000..7779cc83 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentLabeler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentNode; + +public class ExperimentLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, ExperimentNode experiment) throws DatabaseException { + String name = graph.getPossibleRelatedValue(experiment.resource, graph.getBuiltins().HasLabel); + return name == null ? "Experiment (no name)" : name; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentsLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentsLabeler.java new file mode 100644 index 00000000..f301ce2c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ExperimentsLabeler.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentsFolder; + +public class ExperimentsLabeler extends LabelerContributor { + + @Override + public String getLabel(ReadGraph graph, ExperimentsFolder experiments) throws DatabaseException { + return "Experiments"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/InputLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/InputLabeler.java new file mode 100644 index 00000000..3e042c6e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/InputLabeler.java @@ -0,0 +1,27 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.InputNode; + +public class InputLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, InputNode var) throws DatabaseException { + Builtins b = graph.getBuiltins(); + Resource varres = var.resource; + StringBuilder sb = new StringBuilder(); + for(Resource r : graph.getObjects(varres, b.HasName)) + sb.append(graph.getValue(r)); + sb.append(" : "); + for(Resource t : graph.getObjects(varres, b.InstanceOf)) + for(Resource r : graph.getObjects(t, b.HasName)) + sb.append(graph.getValue(r)); + return sb.toString(); + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryViewpointContributor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryViewpointContributor.java new file mode 100644 index 00000000..7eea1213 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryViewpointContributor.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; + +/** + * @author Tuukka Lehtonen + * + * @param input library node type + */ +public abstract class LibraryViewpointContributor extends ViewpointContributor { + + protected abstract Read> getChildRequest(ReadGraph graph, T lib) throws DatabaseException; + + @Override + public final Collection getContribution(ReadGraph graph, T lib) throws DatabaseException { + ArrayList result = new ArrayList(); + for (Resource r : graph.syncRequest(getChildRequest(graph, lib))) { + try { + AbstractNode n = graph.adapt(r, AbstractNode.class); + result.add(n); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + return result; + } + + @Override + public String getViewpointId() { + return "Standard"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Model.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Model.java new file mode 100644 index 00000000..eb2d5a0f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Model.java @@ -0,0 +1,36 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; +import org.simantics.sysdyn.ui.browser.nodes.ConfigurationNode; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentsFolder; +import org.simantics.sysdyn.ui.browser.nodes.ModelNode; +import org.simantics.sysdyn.ui.browser.nodes.ModulesNode; +import org.simantics.sysdyn.ui.browser.nodes.OperatingInterfacesFolder; + +public class Model extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, ModelNode model) + throws DatabaseException { + ArrayList result = new ArrayList(); + result.add(new ConfigurationNode( + graph.getSingleObject( + model.resource, + graph.getBuiltins().HasConfiguration)) + ); + result.add(new ExperimentsFolder(model.resource)); + result.add(new OperatingInterfacesFolder(model.resource)); + result.add(new ModulesNode(model.resource)); + return result; + } + + @Override + public String getViewpointId() { + return "Standard"; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModelLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModelLabeler.java new file mode 100644 index 00000000..bb53b594 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModelLabeler.java @@ -0,0 +1,15 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.ModelNode; + +public class ModelLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, ModelNode model) throws DatabaseException { + String label = graph.getPossibleRelatedValue(model.resource, graph.getBuiltins().HasLabel); + return label == null ? "Model (no name)" : label; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Module.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Module.java new file mode 100644 index 00000000..59945da3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Module.java @@ -0,0 +1,57 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; +import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; + +public class Module extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, ModuleNode module) throws DatabaseException { + ArrayList result = new ArrayList(); + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + StructuralResource2 str = StructuralResource2.getInstance(graph); + Resource instance = graph.getPossibleObject(module.resource, b.InstanceOf); + if(instance == null) return result; + Resource conf = graph.getSingleObject(instance, str.IsDefinedBy); + for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.IndependentVariable))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.Input))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + for(Resource r : graph.syncRequest(new ObjectsWithType(conf, b.ConsistsOf, sr.Module))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + return result; + } + + @Override + public String getViewpointId() { + return "Standard"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleLabeler.java new file mode 100644 index 00000000..78e02ffe --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleLabeler.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; + +public class ModuleLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, ModuleNode module) throws DatabaseException { + Builtins b = graph.getBuiltins(); + Resource resource = module.resource; + StringBuilder sb = new StringBuilder(); + for(Resource r : graph.getObjects(resource, b.HasName)) + sb.append(graph.getValue(r)); + sb.append(" : "); + for(Resource t : graph.getObjects(resource, b.InstanceOf)) + for(Resource r : graph.getObjects(t, b.HasName)) + sb.append(graph.getValue(r)); + return sb.toString(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleTypeLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleTypeLabeler.java new file mode 100644 index 00000000..74adf591 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleTypeLabeler.java @@ -0,0 +1,20 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.modeling.ModelingResources; +import org.simantics.sysdyn.ui.browser.nodes.ModuleTypeNode; + +public class ModuleTypeLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, ModuleTypeNode moduleType) throws DatabaseException { + ModelingResources mr = ModelingResources.getInstance(graph); + Resource typeResource = graph.getPossibleObject(moduleType.resource, mr.SymbolToComponentType); + String label = graph.getPossibleRelatedValue(typeResource, graph.getBuiltins().HasName); + return label == null ? "ModuleType (no name)" : label; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Modules.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Modules.java new file mode 100644 index 00000000..4399de9b --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Modules.java @@ -0,0 +1,40 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.modeling.ModelingResources; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; +import org.simantics.sysdyn.ui.browser.nodes.ModuleTypeNode; +import org.simantics.sysdyn.ui.browser.nodes.ModulesNode; + +public class Modules extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, ModulesNode model) + throws DatabaseException { + + ArrayList result = new ArrayList(); + Builtins b = graph.getBuiltins(); + StructuralResource2 st = StructuralResource2.getInstance(graph); + for(Resource r : graph.syncRequest(new ObjectsWithType(model.resource, b.ConsistsOf, st.ComponentType))) { + Resource symbol = graph.getPossibleObject(r,ModelingResources.getInstance(graph).ComponentTypeToSymbol); + result.add(new ModuleTypeNode(symbol)); + } + return result; + + } + + @Override + public String getViewpointId() { + return "Standard"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModulesLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModulesLabeler.java new file mode 100644 index 00000000..9bc154c9 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModulesLabeler.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.ModulesNode; + +public class ModulesLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, ModulesNode input) throws DatabaseException { + return "Modules"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/OperatingInterfacesLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/OperatingInterfacesLabeler.java new file mode 100644 index 00000000..13cc2d38 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/OperatingInterfacesLabeler.java @@ -0,0 +1,15 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.OperatingInterfacesFolder; + +public class OperatingInterfacesLabeler extends LabelerContributor { + + @Override + public String getLabel(ReadGraph graph, OperatingInterfacesFolder input) throws DatabaseException { + return "Operating interfaces"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Project.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Project.java new file mode 100644 index 00000000..83ef90d0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Project.java @@ -0,0 +1,40 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; + +public class Project extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, Resource project) + throws DatabaseException { + + ArrayList result = new ArrayList(); + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + for(Resource r : graph.syncRequest(new ObjectsWithType(project, b.ConsistsOf, sr.SysdynModel))) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + return result; + + } + + @Override + public String getViewpointId() { + return "Standard"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResult.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResult.java new file mode 100644 index 00000000..cf5bfb1d --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResult.java @@ -0,0 +1,53 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.browser.nodes.AbstractNode; +import org.simantics.sysdyn.ui.browser.nodes.ExperimentNode; + +public class SimulationResult extends ViewpointContributor { + + @Override + public Collection getContribution(ReadGraph graph, ExperimentNode experiment) throws DatabaseException { + ArrayList result = new ArrayList(); + SysdynResource sr = SysdynResource.getInstance(graph); + for(final Resource r : graph.syncRequest(new ObjectsWithType(experiment.resource, sr.HasResult, sr.Result))) { + String resultPath = (String)graph.getPossibleRelatedValue(r, sr.HasResultFile); + File file = new File(resultPath); + if(file.exists()) { + try { + result.add(graph.adapt(r, AbstractNode.class)); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } else { + graph.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + graph.deny(r, b.PartOf); + graph.deny(r, graph.getInverse(SysdynResource.getInstance(graph).HasResult)); + + } + }); + } + } + return result; + } + + @Override + public String getViewpointId() { + return "Standard"; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultDecorator.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultDecorator.java new file mode 100644 index 00000000..69469628 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultDecorator.java @@ -0,0 +1,30 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.eclipse.jface.resource.FontDescriptor; +import org.eclipse.swt.SWT; +import org.simantics.browsing.ui.content.LabelDecorator; +import org.simantics.browsing.ui.graph.contributor.labeler.LabelDecoratorContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode; + +public class SimulationResultDecorator extends LabelDecoratorContributor{ + + @Override + public LabelDecorator getDecorator(ReadGraph graph, SimulationResultNode result) throws DatabaseException { + Builtins b = graph.getBuiltins(); + if (graph.hasStatement(result.resource, b.IsActive)) { + return new LabelDecorator.Stub() { + + @SuppressWarnings("unchecked") + @Override + public F decorateFont(F font, String column, int itemIndex) { + return (F) ((FontDescriptor) font).withStyle(SWT.BOLD); + } + }; + } + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultImager.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultImager.java new file mode 100644 index 00000000..1bc94307 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultImager.java @@ -0,0 +1,20 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.simantics.browsing.ui.swt.ImagerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.Activator; +import org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode; + +public class SimulationResultImager extends ImagerContributor{ + + @Override + public ImageDescriptor getDescriptor(ReadGraph graph, SimulationResultNode result) throws DatabaseException { + if(graph.hasStatement(result.resource, graph.getBuiltins().IsActive)) + return ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/chart_bar.png")); + else + return ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/chart_bar_blackAndWhite.png")); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultLabeler.java new file mode 100644 index 00000000..c74bb404 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/SimulationResultLabeler.java @@ -0,0 +1,16 @@ +package org.simantics.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.SimulationResultNode; + +public class SimulationResultLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, SimulationResultNode result) throws DatabaseException { + String name = graph.getPossibleRelatedValue(result.resource, graph.getBuiltins().HasLabel); + return name == null ? "Experiment (no name)" : name; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/VariableLabeler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/VariableLabeler.java new file mode 100644 index 00000000..14b675a9 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/VariableLabeler.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.contributions; + +import org.simantics.browsing.ui.graph.contributor.labeler.LabelerContributor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.ui.browser.nodes.VariableNode; + +public class VariableLabeler extends LabelerContributor{ + + @Override + public String getLabel(ReadGraph graph, VariableNode var) throws DatabaseException { + Builtins b = graph.getBuiltins(); + Resource varres = var.resource; + StringBuilder sb = new StringBuilder(); + for(Resource r : graph.getObjects(varres, b.HasName)) + sb.append(graph.getValue(r)); + sb.append(" : "); + for(Resource t : graph.getObjects(varres, b.InstanceOf)) + for(Resource r : graph.getObjects(t, b.HasName)) + sb.append(graph.getValue(r)); + return sb.toString(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/AbstractNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/AbstractNode.java new file mode 100644 index 00000000..bf56020b --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/AbstractNode.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.nodes; + +import org.eclipse.core.runtime.IAdaptable; +import org.simantics.db.Resource; + +public abstract class AbstractNode implements IAdaptable { + public final Resource resource; + + public AbstractNode(Resource resource) { + assert(resource != null); + this.resource = resource; + } + + @Override + public int hashCode() { + return resource.hashCode() + getClass().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AbstractNode other = (AbstractNode) obj; + return resource.equals(other.resource); + } + + @SuppressWarnings("unchecked") + @Override + public Object getAdapter(Class adapter) { + if(adapter.equals(Resource.class)) + return resource; + return null; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ConfigurationNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ConfigurationNode.java new file mode 100644 index 00000000..1f44cfd1 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ConfigurationNode.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.nodes; + +import org.simantics.browsing.ui.common.node.IDeletable; +import org.simantics.db.Resource; + +public class ConfigurationNode extends AbstractNode implements IDeletable { + + public ConfigurationNode(Resource resource) { + super(resource); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ExperimentNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ExperimentNode.java new file mode 100644 index 00000000..a04e5968 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ExperimentNode.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.nodes; + +import org.simantics.browsing.ui.common.node.IDeletable; +import org.simantics.browsing.ui.common.node.IDoubleClickableNode; +import org.simantics.browsing.ui.common.node.IModifiableNode; +import org.simantics.browsing.ui.content.Labeler.Modifier; +import org.simantics.browsing.ui.graph.impl.LabelModifier; +import org.simantics.db.Resource; +import org.simantics.project.IProject; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.sysdyn.ui.handlers.SysdynExperimentActivator; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ErrorLogger; + +public class ExperimentNode extends AbstractNode implements IDoubleClickableNode, IDeletable, IModifiableNode{ + + public ExperimentNode(Resource resource) { + super(resource); + } + + @Override + public boolean handleDoubleClick() { + if (resource == null) + return false; + IProject project = SimanticsUI.getProject(); + IExperimentManager experimentManager = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); + if (experimentManager == null) { + ErrorLogger.defaultLogWarning("Experiment manager not available.", new Exception()); + return false; + } + SysdynExperimentActivator.scheduleActivation(SimanticsUI.getSession(), project, experimentManager, resource); + return true; + } + + @Override + public Modifier getModifier(String columnId) { + LabelModifier modifier = new LabelModifier(SimanticsUI.getSession(), resource) { + @Override + public String isValid(String label) { + if (label.isEmpty()) + return "Empty label not allowed"; + return null; + } + }; + return modifier; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ExperimentsFolder.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ExperimentsFolder.java new file mode 100644 index 00000000..b68b5394 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ExperimentsFolder.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.nodes; + +import org.simantics.db.Resource; + +public class ExperimentsFolder extends AbstractNode { + + public ExperimentsFolder(Resource resource) { + super(resource); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/InputNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/InputNode.java new file mode 100644 index 00000000..b0efeb7b --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/InputNode.java @@ -0,0 +1,10 @@ +package org.simantics.sysdyn.ui.browser.nodes; + +import org.simantics.db.Resource; + +public class InputNode extends AbstractNode { + + public InputNode(Resource resource) { + super(resource); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModelNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModelNode.java new file mode 100644 index 00000000..b79582cc --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModelNode.java @@ -0,0 +1,31 @@ +package org.simantics.sysdyn.ui.browser.nodes; + +import org.simantics.browsing.ui.common.node.IDeletable; +import org.simantics.browsing.ui.common.node.IModifiableNode; +import org.simantics.browsing.ui.content.Labeler.Modifier; +import org.simantics.browsing.ui.graph.impl.LabelModifier; +import org.simantics.db.Resource; +import org.simantics.ui.SimanticsUI; + +public class ModelNode extends AbstractNode implements IDeletable, IModifiableNode { + + public ModelNode(Resource resource) { + super(resource); + } + + @Override + public Modifier getModifier(String columnId) { + LabelModifier modifier = new LabelModifier(SimanticsUI.getSession(), resource) { + @Override + public String isValid(String label) { + if (label.isEmpty()) + return "Empty label not allowed"; + if (label.contains(" ")) + return "Spaces are not allowed"; + return null; + } + }; + return modifier; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleNode.java new file mode 100644 index 00000000..1689c075 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleNode.java @@ -0,0 +1,11 @@ +package org.simantics.sysdyn.ui.browser.nodes; + +import org.simantics.browsing.ui.common.node.IDeletable; +import org.simantics.db.Resource; + +public class ModuleNode extends AbstractNode implements IDeletable { + + public ModuleNode(Resource resource) { + super(resource); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleTypeNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleTypeNode.java new file mode 100644 index 00000000..fdbad703 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModuleTypeNode.java @@ -0,0 +1,11 @@ +package org.simantics.sysdyn.ui.browser.nodes; + +import org.simantics.browsing.ui.common.node.IDeletable; +import org.simantics.db.Resource; + +public class ModuleTypeNode extends AbstractNode implements IDeletable { + + public ModuleTypeNode(Resource resource) { + super(resource); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModulesNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModulesNode.java new file mode 100644 index 00000000..1536a4c3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/ModulesNode.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.nodes; + +import org.simantics.db.Resource; + +public class ModulesNode extends AbstractNode { + + public ModulesNode(Resource resource) { + super(resource); + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/OperatingInterfacesFolder.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/OperatingInterfacesFolder.java new file mode 100644 index 00000000..94ecb3f3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/OperatingInterfacesFolder.java @@ -0,0 +1,11 @@ +package org.simantics.sysdyn.ui.browser.nodes; + +import org.simantics.db.Resource; + +public class OperatingInterfacesFolder extends AbstractNode { + + public OperatingInterfacesFolder(Resource resource) { + super(resource); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/SimulationResultNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/SimulationResultNode.java new file mode 100644 index 00000000..ef28f83e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/SimulationResultNode.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.ui.browser.nodes; + +import org.simantics.browsing.ui.common.node.IDeletable; +import org.simantics.browsing.ui.common.node.IModifiableNode; +import org.simantics.browsing.ui.content.Labeler.Modifier; +import org.simantics.browsing.ui.graph.impl.LabelModifier; +import org.simantics.db.Resource; +import org.simantics.ui.SimanticsUI; + +public class SimulationResultNode extends AbstractNode implements IDeletable, IModifiableNode { + + public SimulationResultNode(Resource resource) { + super(resource); + } + + + @Override + public Modifier getModifier(String columnId) { + LabelModifier modifier = new LabelModifier(SimanticsUI.getSession(), resource) { + @Override + public String isValid(String label) { + if (label.isEmpty()) + return "Empty label not allowed"; + return null; + } + }; + return modifier; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/SymbolNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/SymbolNode.java new file mode 100644 index 00000000..90fb5337 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/SymbolNode.java @@ -0,0 +1,11 @@ +package org.simantics.sysdyn.ui.browser.nodes; + +import org.simantics.browsing.ui.common.node.IDeletable; +import org.simantics.db.Resource; + +public class SymbolNode extends AbstractNode implements IDeletable { + + public SymbolNode(Resource resource) { + super(resource); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/VariableNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/VariableNode.java new file mode 100644 index 00000000..1480bb64 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/nodes/VariableNode.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.sysdyn.ui.browser.nodes; + +import org.simantics.db.Resource; + +public class VariableNode extends AbstractNode { + + public VariableNode(Resource resource) { + super(resource); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/CreateDependencyGraph.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/CreateDependencyGraph.java new file mode 100644 index 00000000..4a287d55 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/CreateDependencyGraph.java @@ -0,0 +1,116 @@ +package org.simantics.sysdyn.ui.dependencies; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.graphviz.Edge; +import org.simantics.graphviz.Graph; +import org.simantics.graphviz.IGraph; +import org.simantics.graphviz.Node; +import org.simantics.modeling.ModelingResources; +import org.simantics.sysdyn.SysdynResource; + +public class CreateDependencyGraph implements Read { + + Resource root; + HashMap nodes; + boolean isInverted; + int levels; + + public CreateDependencyGraph(Resource root, int levels, boolean isInverted) { + this.root = root; + this.isInverted = isInverted; + this.levels = levels; + } + + @Override + public Graph perform(ReadGraph g) throws DatabaseException { + nodes = new HashMap(); + Graph graph = new Graph(); + graph.setRankdir("LR"); + ModelingResources mr = ModelingResources.getInstance(g); + Resource element = g.getPossibleObject(root, mr.ElementToComponent); + if (element != null) { + root = element; + } + SysdynResource sr = SysdynResource.getInstance(g); + if (g.isInstanceOf(root, sr.IndependentVariable) || g.isInstanceOf(root, sr.Input)) { + Collection resources = new ArrayList(); + resources.add(root); + for (int i = 0; i < levels && !resources.isEmpty(); i++) { + Collection newResources = new ArrayList(); + for(Resource r : resources) { + newResources.addAll(getDependencies(g, graph, r)); + } + resources = new ArrayList(newResources); + } + } + return graph; + } + + private Collection getDependencies(ReadGraph g, IGraph graph, Resource r) throws DatabaseException{ + Collection dependants = new ArrayList(); + SysdynResource sr = SysdynResource.getInstance(g); + Node n; + if (!nodes.containsKey(r)) { + n = new Node(graph, getName(g, r)); + setShape(g, r, n); + n.set("style", "filled"); + n.setFillColor("#d3d3d3"); + nodes.put(r, n); + } + // stop here if element is a module + if (g.isInstanceOf(r, sr.Module)) + return dependants; + + Resource headRelation = sr.IsHeadOf; + Resource tailRelation = sr.HasTail; + if(isInverted) { + headRelation = sr.IsTailOf; + tailRelation = sr.HasHead; + } + + Collection dependencies = g.getObjects(r, headRelation); + for(Resource d : dependencies) { + Resource dependant = g.getPossibleObject(d, tailRelation); + if(dependant == null) + continue; + if(g.isInstanceOf(dependant, sr.Cloud)) { + break; + } + if( !nodes.containsKey(dependant)) { + n= new Node(graph, getName(g, dependant)); + setShape(g, dependant, n); + nodes.put(dependant, n); + dependants.add(dependant); + } else { + n = nodes.get(dependant); + } + if(isInverted) + new Edge(graph, nodes.get(r), n); + else + new Edge(graph, n, nodes.get(r)); + } + return dependants; + } + + private void setShape(ReadGraph g, Resource r, Node n) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + if(g.isInstanceOf(r, sr.Stock)) + n.setShape("rectangle"); + else if(g.isInstanceOf(r, sr.Module)) + n.setShape("rectangle"); + else + n.setShape("ellipse"); + } + + private String getName(ReadGraph g, Resource r) throws DatabaseException { + return (String)g.getRelatedValue(r, g.getBuiltins().HasName); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/DependencyView.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/DependencyView.java new file mode 100644 index 00000000..280f9977 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/DependencyView.java @@ -0,0 +1,191 @@ +package org.simantics.sysdyn.ui.dependencies; + +import java.util.Set; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Spinner; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.part.ViewPart; +import org.simantics.db.Resource; +import org.simantics.db.procedure.Listener; +import org.simantics.graphviz.Graph; +import org.simantics.graphviz.ui.GraphvizComponent; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; + +public class DependencyView extends ViewPart { + + private GraphvizComponent component; + private boolean disposed, isInverted = false; + private Button bButton, fButton; + private Resource currentSelection; + private int levels = 3; + private ISelectionListener selectionListener; + private Composite baseComposite; + + static int MAXLEVELS = 4; + static int MINLEVELS = 1; + + @Override + public void createPartControl(Composite parent) { + disposed = false; + GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(parent); + baseComposite = new Composite(parent, + SWT.NO_BACKGROUND | SWT.EMBEDDED); + GridLayoutFactory.fillDefaults().applyTo(baseComposite); + GridDataFactory.fillDefaults().grab(true, true).applyTo(baseComposite); + + component = new GraphvizComponent(baseComposite, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, true).applyTo(component); + + Composite composite = new Composite(parent, SWT.NULL); + RowLayout layout = new RowLayout(); + layout.center = true; + composite.setLayout(layout); + + Label label = new Label(composite, SWT.NULL); + label.setText("Direction: "); + + bButton = new Button(composite, SWT.RADIO); + bButton.setText("Backward"); + bButton.setSelection(true); + bButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + if(bButton.getSelection()) + isInverted = false; + else + isInverted = true; + if(currentSelection != null) { + readGraph(currentSelection); + } + } + }); + + fButton = new Button(composite, SWT.RADIO); + fButton.setText("Forward"); + + label = new Label(composite, SWT.NULL); + label.setText("Steps: "); + + Spinner spinner = new Spinner(composite, SWT.BORDER); + spinner.setMaximum(MAXLEVELS); + spinner.setMinimum(MINLEVELS); + spinner.setTextLimit(1); + spinner.setSelection(levels); + + spinner.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + Spinner s = (Spinner)e.widget; + int lvls = Integer.parseInt(s.getText()); + if(lvls > MAXLEVELS) + levels = MAXLEVELS; + else if (lvls < MINLEVELS) + levels = MINLEVELS; + levels = lvls; + if(currentSelection != null) { + readGraph(currentSelection); + } + + } + }); + + drawSelection(getSite().getWorkbenchWindow().getSelectionService().getSelection()); + + selectionListener = new ISelectionListener() { + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + drawSelection(selection); + } + }; + getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(selectionListener); + } + + private void drawSelection(ISelection selection) { + if(selection == null || selection.isEmpty()) + return; + if(selection instanceof IStructuredSelection) { + Object[] els = ((IStructuredSelection) selection).toArray(); + if(els.length == 1) { + Set ress = ISelectionUtils.filterSetSelection(selection, Resource.class); + if(ress.isEmpty()) return; + Resource r = (ress.toArray(Resource.NONE))[0]; + if(r != null && !r.equals(currentSelection)) { + currentSelection = r; + readGraph(currentSelection); + } + } + } + } + + private void readGraph(Resource resource) { + SimanticsUI.getSession().asyncRequest(new CreateDependencyGraph( + resource, levels, isInverted), + new Listener() { + + @Override + public void exception(Throwable e) { + e.printStackTrace(); + } + + @Override + public void execute(final Graph graph) { + Job job = new Job("Layout composite graph") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + if(!isDisposed()) { + component.setGraph(graph, "dot"); + component.fit(); + } + return Status.OK_STATUS; + } + }; + job.schedule(); + } + + @Override + public boolean isDisposed() { + return disposed; + } + }); + } + + + @Override + public void setFocus() { + if(baseComposite != null && !baseComposite.isDisposed()) { + baseComposite.setFocus(); + component.setFocus(); + } + } + + + + + @Override + public void dispose() { + super.dispose(); + getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(selectionListener); + disposed = true; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramToCompositeMapping3.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramToCompositeMapping3.java new file mode 100644 index 00000000..cf7fbc51 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramToCompositeMapping3.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * 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.sysdyn.ui.editor; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.utils.binaryPredicates.InversePredicate; +import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate; +import org.simantics.mapping.constraint.instructions.IInstruction; +import org.simantics.mapping.constraint.instructions.TypedBracketInstruction.CreationInstruction; +import org.simantics.mapping.rule.instructions.IRuleInstruction; +import org.simantics.sysdyn.SysdynResource; + +public class DiagramToCompositeMapping3 extends org.simantics.modeling.mapping.DiagramToCompositeMapping3 { + + private SysdynResource sdr; + + public DiagramToCompositeMapping3(ReadGraph g, Resource mapping) + throws DatabaseException { + super(g, mapping); + } + + @Override + protected void setup(ReadGraph graph) { + sdr = SysdynResource.getInstance(graph); + } + + @Override + protected Resource getConfigurationConnectionType() { + return sdr.DependencyConnection; + } + + @Override + public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) { + return new SysdynCreationInstruction(project, configurationRoot, component, componentType, configuration); + } + + @Override + protected IRuleInstruction additiveRule() { + return + + if_(bf(OrderedSetElementsPredicate.INSTANCE, Diagram, Element), + query( + if_(and(bf(b.InstanceOf, Element, ElementType), + bf(mr.SymbolToComponentType, ElementType, ComponentType) + ), + // If element type of the element has a corresponding component type + createComponentRule(), + + if_(and(b(dr.Connection, Element), bf(b.InstanceOf, Element, ElementType), bf(mr.DiagramConnectionTypeToConnectionType, ElementType, ComponentType)), + createNormalConnectionRule(), + + if_(b(dr.Flag, Element), + createFlagRule() + ) + ) + ) + ) + ); + } + + @Override + protected IRuleInstruction destructiveRule() { + return + if_(and(bf(b.ConsistsOf, Configuration, Component), + b(mapped, Component) // handle only mapped components + ), + query( + if_(and(bf(mr.ComponentToElement, Component, Element), + bf(new InversePredicate(OrderedSetElementsPredicate.INSTANCE), Element, Diagram) + ), + // If component has a corresponding element in the diagram + if_(and(statement_bff(Component, ConnectionRelation, Connection, sr.IsConnectedTo), + b(mapped, Connection) + ), + // If component has a mapped connection + unless( + bf(mr.ConnectionToDiagramConnection, Connection, DiagramConnectionRelation), + // If the configuration connection does not have a correspondence in the diagram remove it + and(deny(exists(Connection))) + ) + ), + + unless( + bf(mr.ConnectionToDiagramConnection, Component, Element), + // If the configuration connection does not have a correspondence in the diagram remove it + and(deny(exists(Component))) + ) + + ) + ) + ); + } + + @Override + protected IInstruction claimBasicConnection() { + return and(exists( + bf(mr.DiagramConnectionToConnection, Element, Connection), + Connection + ), + bb(b.InstanceOf, Connection, ComponentType), + bb(b.PartOf, Connection, Configuration), + b(mapped, Connection) + + ); + } + +// @Override +// protected IInstruction claimBasicConnection() { +// return and(exists( +// bf(mr.DiagramConnectionToConnection, Element, Connection), +// Connection +// ), +// bb(b.InstanceOf, Connection, ComponentType), +// b(mapped, Connection), +// bb(b.PartOf, Connection, Configuration) +// ); +// } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java new file mode 100644 index 00000000..fa546979 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java @@ -0,0 +1,151 @@ +package org.simantics.sysdyn.ui.editor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IWorkbenchPartSite; +import org.simantics.browsing.ui.swt.AdaptableHintContext; +import org.simantics.browsing.ui.swt.IPropertyPage; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.layer0.SelectionHints; +import org.simantics.diagram.adapter.FlagClassFactory; +import org.simantics.diagram.handler.CopyPasteHandler; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.diagram.synchronization.IModifiableSynchronizationContext; +import org.simantics.diagram.ui.DiagramModelHints; +import org.simantics.diagram.ui.WorkbenchSelectionProvider; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.canvas.impl.CanvasContext; +import org.simantics.g2d.connection.IConnectionAdvisor; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.participant.DeleteHandler; +import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor; +import org.simantics.g2d.element.ElementClassProviders; +import org.simantics.g2d.element.ElementClasses; +import org.simantics.g2d.element.ElementHints; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.IElementClassProvider; +import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; +import org.simantics.modeling.ui.diagramEditor.handlers.LinkBrowsingHandler; +import org.simantics.structural2.modelingRules.IModelingRules; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses; +import org.simantics.sysdyn.ui.elements2.connections.SysdynConnectionClass; +import org.simantics.sysdyn.ui.properties.SysdynPropertyPage; +import org.simantics.utils.datastructures.hints.HintContext; +import org.simantics.utils.datastructures.hints.IHintContext; + +/** + * @author Tuukka Lehtonen + */ +public class DiagramViewer extends org.simantics.modeling.ui.diagramEditor.DiagramViewer { + + protected String getPopupId() { + return "#SysdynDiagramPopup"; + } + + @Override + protected Set getPropertyPageContexts() { + return Collections.singleton("http://www.simantics.org/Sysdyn-1.0/Browser"); + } + + @Override + protected IPropertyPage createPropertyPage(IWorkbenchPartSite site, Set contexts) { + return new SysdynPropertyPage(site, contexts); + } + + @Override + protected IElementClassProvider createElementClassProvider(ReadGraph graph) { + DiagramResource dr = DiagramResource.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + + return ElementClassProviders.mappedProvider( + ElementClasses.CONNECTION, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)), + ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag), + ConnectionClasses.FLOW, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.FlowConnection)), + ConnectionClasses.DEPENDENCY, SysdynConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(sr.DependencyConnection)) + ); + + + } + + @Override + protected void onCreated() { + sourceDiagram.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.FALSE); + } + + @Override + protected void addKeyBindingParticipants(CanvasContext ctx) { + ctx.add(new DeleteHandler(getEditorSite().getActionBars().getStatusLineManager())); + ctx.add(new CopyPasteHandler(getEditorSite().getActionBars().getStatusLineManager())); + } + + @Override + protected void initializeSynchronizationContext(ReadGraph graph, IModifiableSynchronizationContext context) { + super.initializeSynchronizationContext(graph, context); + + // Make sure SysdynResource is available. + SysdynResource.getInstance(graph); + } + + @Override + protected void addStructureParticipants(ICanvasContext ctx) { + + ctx.add(new WorkbenchSelectionProvider(swt, getSite()) { + + @Override + protected ISelection constructAdaptableSelection(Iterable selection) { + ArrayList objects = new ArrayList(); + Resource runtime = sourceDiagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE); + for (Object o : selection) { + if (o instanceof IElement) { + IElement e = (IElement) o; + Object object = e.getHint(ElementHints.KEY_OBJECT); + if (object != null && runtime != null) { + IHintContext context = new AdaptableHintContext(SelectionHints.KEY_MAIN); + context.setHint(SelectionHints.KEY_MAIN, object); + if (runtime != null) + context.setHint(SelectionHints.KEY_VARIABLE_RESOURCE, runtime); + objects.add(context); + } + } else { + System.out.println(" unrecognized selection: " + o.getClass() + ": " + o); + } + } + if(objects.isEmpty() && runtime != null) { + HintContext context = new HintContext(); + context.setHint(SelectionHints.KEY_VARIABLE_RESOURCE, runtime); + objects.add(context); + } + return new StructuredSelection(objects); + } + + }); + // Add visual browsing capabilities for structural models + +// Remove double click handler, because it is not working properly +// ctx.add(new StructuralBrowsingHandler(getSite(), sessionContext, getResourceInput2())); + ctx.add(new LinkBrowsingHandler(getSite(), this, sessionContext)); + + } + + @Override + protected void addOtherParticipants(CanvasContext ctx) { + } + + @Override + protected PointerInteractor getPointerInteractor() { + return new org.simantics.sysdyn.ui.editor.participant.PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider()); + } + + @Override + protected IConnectionAdvisor getConnectionAdvisor(IModelingRules modelingRules, Session session) { + return new SysdynConnectionAdvisor(modelingRules, sessionContext.getSession()); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/OpenDiagramFromConfigurationAdapter.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/OpenDiagramFromConfigurationAdapter.java new file mode 100644 index 00000000..c2fcda8e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/OpenDiagramFromConfigurationAdapter.java @@ -0,0 +1,17 @@ +package org.simantics.sysdyn.ui.editor; + + +public class OpenDiagramFromConfigurationAdapter extends org.simantics.modeling.ui.diagramEditor.OpenDiagramFromConfigurationAdapter { + + private static final String EDITOR_ID = "org.simantics.sysdyn.ui.diagramViewer"; + + public OpenDiagramFromConfigurationAdapter() { + super(); + } + + @Override + protected String getEditorId() { + return EDITOR_ID; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynConnectionAdvisor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynConnectionAdvisor.java new file mode 100644 index 00000000..e289eddf --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynConnectionAdvisor.java @@ -0,0 +1,129 @@ +package org.simantics.sysdyn.ui.editor; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.diagram.content.ConnectionUtil; +import org.simantics.diagram.content.ResourceTerminal; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.g2d.connection.IConnectionAdvisor; +import org.simantics.g2d.diagram.handler.Topology.Terminal; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.elementclass.FlagHandler; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.structural2.modelingRules.CPFlag; +import org.simantics.structural2.modelingRules.ConnectionJudgement; +import org.simantics.structural2.modelingRules.ConnectionJudgementType; +import org.simantics.structural2.modelingRules.IConnectionPoint; +import org.simantics.structural2.modelingRules.IModelingRules; +import org.simantics.sysdyn.SysdynResource; + +public class SysdynConnectionAdvisor implements IConnectionAdvisor { + + IModelingRules modelingRules; + RequestProcessor processor; + + public SysdynConnectionAdvisor(IModelingRules modelingRules, + RequestProcessor processor) { + this.modelingRules = modelingRules; + this.processor = processor; + } + + IConnectionPoint getConnectionPoint(ReadGraph g, IElement element, Terminal term) throws DatabaseException { + Object obj = null; + if (element != null) + obj = ElementUtils.getObject(element); + + if (obj instanceof Resource) { + Resource elementResource = (Resource) obj; + return ConnectionUtil.toConnectionPoint(g, elementResource, term); + } + + if(element.getElementClass().containsClass(FlagHandler.class)) { + return new CPFlag(null); + } + + return null; + } + + @Override + public Object canBeConnected(Object backend, + final IElement element1, final Terminal term1, + final IElement element2, final Terminal term2) { + try { + if(backend == null) + backend = processor; + return ((RequestProcessor)backend).syncRequest(new Read() { + + @Override + public Object perform(ReadGraph g) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + DiagramResource dr = DiagramResource.getInstance(g); + StructuralResource2 str2 = StructuralResource2.getInstance(g); + Resource terminal2 = ((ResourceTerminal) term2).getResource(); + Resource connectionVariable = g.getPossibleObject(terminal2, dr.HasConnectionVariable); + if(!g.hasStatement(connectionVariable, str2.Binds, sr.IsHeadOfTerminal)) { + return null; + } + + // Only one incoming dependency allowed in inputs. That dependency must be from a module + Object obj1 = ElementUtils.getObject(element1); + Object obj2 = ElementUtils.getObject(element2); + if(obj2 instanceof Resource) { + Resource startElementResource = (Resource)obj1; + Resource endElementResource = (Resource)obj2; + if(g.isInstanceOf(endElementResource, sr.InputSymbol)) { + if(g.isInheritedFrom(startElementResource, sr.ModuleSymbol)) return null; + if(g.getObjects(endElementResource, sr.IsHeadOfTerminal).size() > 0) return null; + } + } + + ArrayList cps = new ArrayList(); + cps.add(getConnectionPoint(g, element1, term1)); + if(element2 != null) + cps.add(getConnectionPoint(g, element2, term2)); + ConnectionJudgement judgement = + modelingRules.judgeConnection(g, cps); + + if(judgement.type == ConnectionJudgementType.LEGAL) + return judgement.connectionType; + else + return null; + } + + }); + } catch(DatabaseException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public boolean canBeginConnection(Object backend, + final IElement element, final Terminal term) { + try { + if(backend == null) + backend = processor; + return ((RequestProcessor)backend).syncRequest(new Read() { + + @Override + public Boolean perform(ReadGraph g) throws DatabaseException { + return modelingRules.judgeConnection(g, + Arrays.asList(getConnectionPoint(g, element, term))) + .type != ConnectionJudgementType.ILLEGAL; + } + + }); + } catch(DatabaseException e) { + e.printStackTrace(); + return false; + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynCreationInstruction.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynCreationInstruction.java new file mode 100644 index 00000000..ac3a25b7 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynCreationInstruction.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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.sysdyn.ui.editor; + +import gnu.trove.TIntIntHashMap; + +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.URIStringUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.mapping.constraint.instructions.TypedBracketInstruction.CreationInstruction; +import org.simantics.modeling.services.ComponentNamingUtil; +import org.simantics.modeling.services.NamingException; +import org.simantics.project.IProject; + +public class SysdynCreationInstruction extends CreationInstruction { + + IProject project; + Resource configurationRoot; + int lComponentType; + int lConfiguration; + + public SysdynCreationInstruction(IProject project, Resource configurationRoot, int variableId, int componentType, + int configuration) { + super(variableId); + this.project = project; + this.configurationRoot = configurationRoot; + lComponentType = componentType; + lConfiguration = configuration; + } + + @Override + public Resource create(WriteGraph g, Object[] bindings) throws DatabaseException { + Resource componentType = (Resource) bindings[lComponentType]; + Resource configuration = (Resource) bindings[lConfiguration]; + + try { + String proposition = URIStringUtils.escape(ComponentNamingUtil.findFreshInstanceName(g, project, configurationRoot, configuration, componentType)); + Resource result = GraphUtils.create(g, + g.getBuiltins().HasName, proposition + ); + return result; + } catch (NamingException e1) { + throw new DatabaseException(e1); + } + } + + @Override + public void mapVariables(TIntIntHashMap map) { + super.mapVariables(map); + lComponentType = map.get(lComponentType); + lConfiguration = map.get(lConfiguration); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynDiagramEditor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynDiagramEditor.java new file mode 100644 index 00000000..d57867f1 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynDiagramEditor.java @@ -0,0 +1,331 @@ +/******************************************************************************* + * 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.sysdyn.ui.editor; + +import java.awt.Frame; +import java.util.ArrayList; +import java.util.Collections; + +import javax.swing.SwingUtilities; + +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.awt.SWT_AWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.simantics.browsing.ui.swt.IPropertyPage; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.management.ISessionContextProvider; +import org.simantics.diagram.DiagramTypeUtils; +import org.simantics.diagram.symbolcontribution.ISymbolProvider; +import org.simantics.h2d.canvas.EditorCanvas; +import org.simantics.h2d.diagram.IDiagram; +import org.simantics.h2d.diagram.IDiagramListener; +import org.simantics.h2d.editor.ISelection; +import org.simantics.h2d.editor.ISelectionListener; +import org.simantics.h2d.editor.impl.DiagramEditor; +import org.simantics.h2d.element.IElement; +import org.simantics.h2d.element.IElementListener; +import org.simantics.h2d.event.handler.DefaultEventHandlers; +import org.simantics.layer0.utils.triggers.IActivation; +import org.simantics.modeling.ModelingResources; +import org.simantics.objmap.IMapping; +import org.simantics.objmap.IMappingListener; +import org.simantics.objmap.MappingException; +import org.simantics.objmap.Mappings; +import org.simantics.scenegraph.INode; +import org.simantics.sysdyn.ui.actions.ConnectDependency; +import org.simantics.sysdyn.ui.actions.ConnectFlow; +import org.simantics.sysdyn.ui.actions.CreateAuxiliary; +import org.simantics.sysdyn.ui.actions.CreateCloud; +import org.simantics.sysdyn.ui.actions.CreateStock; +import org.simantics.sysdyn.ui.actions.CreateValve; +import org.simantics.sysdyn.ui.actions.OpenContextMenu; +import org.simantics.sysdyn.ui.properties.SysdynPropertyPage; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.workbench.ResourceEditorPart; +import org.simantics.ui.workbench.TitleRequest; +import org.simantics.ui.workbench.TitleUpdater; +import org.simantics.utils.datastructures.Callable; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.ui.ErrorLogger; +import org.simantics.utils.ui.jface.ActiveSelectionProvider; + +public class SysdynDiagramEditor extends ResourceEditorPart { + + EditorCanvas canvas; + IDiagram diagram; + IMapping mapping; + Frame frame; + boolean disposed = false; + Composite frameComposite; + Resource diagramResource; + protected ISessionContextProvider sessionContextProvider; + protected ISessionContext sessionContext; + protected IActivation activation; + + IElementListener elementUpdateListener = new IElementListener() { + + @Override + public void elementUpdated(IElement element) { + mapping.rangeModified(element); + } + + @Override + public void elementRemoved(IElement element) { + } + }; + + protected void readDiagram(ReadGraph g) throws DatabaseException { + SysdynDiagramSchema schema = new SysdynDiagramSchema(g); + mapping = Mappings.createWithListening(schema); + + try { + diagram = (IDiagram)mapping.map(g, getInputResource()); + for(IElement element : diagram.getElements()) + element.addListener(elementUpdateListener); + } catch (MappingException e) { + e.printStackTrace(); + } + + final Session session = g.getSession(); + mapping.addMappingListener(new IMappingListener() { + + @Override + public void rangeModified() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + try { + session.syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) + throws DatabaseException { + mapping.updateDomain(graph); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + }); + } + + @Override + public void domainModified() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + try { + session.syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + mapping.updateRange(graph); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + }); + } + + }); + + diagram.addDiagramListener(new IDiagramListener() { + + @Override + public void elementAdded(IElement element) { + mapping.rangeModified(diagram); + element.addListener(elementUpdateListener); + } + + @Override + public void elementRemoved(IElement element) { + mapping.rangeModified(element); + mapping.rangeModified(diagram); + } + + }); + } + + @Override + public void init(IEditorSite site, IEditorInput input) + throws PartInitException { + super.init(site, input); + + try { + SimanticsUI.getSession().syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph g) throws DatabaseException { + diagramResource = g.getSingleObject(getInputResource(), ModelingResources.getInstance(g).CompositeToDiagram); + readDiagram(g); + } + + }); + + SimanticsUI.getSession().asyncRequest( + new TitleRequest(site.getId(), getResourceInput()) { + @Override + public String perform(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + Resource r = graph.getSingleObject( + getResourceInput().getResource(), + b.IsConfigurationOf); + String label = graph.getPossibleRelatedValue(r, b.HasLabel); + return label; + } + }, + new TitleUpdater(site.getShell().getDisplay(), new Callback() { + @Override + public void run(String partName) { + setPartName(partName); + } + }, new Callable() { + @Override + public Boolean call() { + return disposed; + } + })); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + @Override + public void createPartControl(final Composite parent) { + frameComposite = new Composite(parent, + SWT.NO_BACKGROUND | SWT.EMBEDDED); + frame = SWT_AWT.new_Frame(frameComposite); + + + /// KOKEILLAAN + + /* + sessionContextProvider = SimanticsUI.getSessionContextProvider(); + sessionContext = sessionContextProvider.getSessionContext(); + + IActivationManager activationManager = sessionContext.getSession().peekService(IActivationManager.class); + if (activationManager != null) { + activation = activationManager.activate(diagramResource); + } + */ + /// LOPPUU + + final ActiveSelectionProvider selectionProvider = new ActiveSelectionProvider(); + getSite().setSelectionProvider(selectionProvider); + + final OpenContextMenu openContextMenu = new OpenContextMenu( + parent, getSite(), "#SysdynDiagramPopup"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + DiagramEditor editor = new DiagramEditor(null, diagram); + + DefaultEventHandlers.configure(editor); + editor.addEventHandler(1, "key(A)", new CreateAuxiliary()); + editor.addEventHandler(1, "key(S)", new CreateStock()); + editor.addEventHandler(1, "key(V)", new CreateValve()); + editor.addEventHandler(1, "key(C)", new CreateCloud()); + editor.addEventHandler(1, "drag(alt+left)", new ConnectDependency()); + editor.addEventHandler(1, "drag(alt+right)", new ConnectFlow()); + editor.addEventHandler(1, "release(right)", openContextMenu); + + canvas = new EditorCanvas(editor); + frame.add(canvas); + + frameComposite.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + setFocus(); + } + }); + + + editor.getSelection().addSelectionListener(new ISelectionListener() { + + @Override + public void selectionChanged(ISelection selection) { + final ArrayList resources = new ArrayList(selection.size()); + for(IElement element : selection) + resources.add(mapping.inverseGet(element)); + frameComposite.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if(!frameComposite.isDisposed()) + selectionProvider.setSelection(new StructuredSelection(resources)); + } + + }); + } + + }); + } + + }); + } + + @Override + public void setFocus() { + if(frameComposite != null && !frameComposite.isDisposed()) { + frameComposite.setFocus(); + if(canvas!=null) + canvas.requestFocus(); + } + } + + @Override + public void dispose() { + mapping.dispose(); + frame.dispose(); + disposed = true; + } + + @SuppressWarnings("unchecked") + @Override + public Object getAdapter(Class adapter) { + if (adapter == INode.class) { + return canvas.getEditor().getSceneGraph(); + } + if (adapter == ISymbolProvider.class) { + try { + + return DiagramTypeUtils.readSymbolContributions(SimanticsUI.getSession(), diagramResource); + } catch (DatabaseException e) { + ErrorLogger.defaultLogError(getClass() + " failed to adapt to ISymbolProvider, see exception for details.", e); + return null; + } + } + if (adapter == IPropertyPage.class) { + return new SysdynPropertyPage(getSite(), Collections.singleton("http://www.simantics.org/Sysdyn-1.0/Browser")); + } + return super.getAdapter(adapter); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynDiagramSchema.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynDiagramSchema.java new file mode 100644 index 00000000..d0d2b3ec --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynDiagramSchema.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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.sysdyn.ui.editor; + +import java.util.Collection; + +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.h2d.diagram.Diagram; +import org.simantics.objmap.rules.MappedElementsRule; +import org.simantics.objmap.rules.domain.RelatedObjectsAccessor; +import org.simantics.objmap.rules.range.FieldAccessor; +import org.simantics.objmap.schema.MappingSchemas; +import org.simantics.objmap.schema.SimpleLinkType; +import org.simantics.objmap.schema.SimpleSchema; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.elements.AuxiliaryElement; +import org.simantics.sysdyn.ui.elements.CloudElement; +import org.simantics.sysdyn.ui.elements.DependencyElement; +import org.simantics.sysdyn.ui.elements.FlowElement; +import org.simantics.sysdyn.ui.elements.StockElement; +import org.simantics.sysdyn.ui.elements.ValveElement; + +public class SysdynDiagramSchema extends SimpleSchema { + + public SysdynDiagramSchema(ReadGraph g) throws DatabaseException { + Builtins b = g.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(g); + try { + { + SimpleLinkType linkType = + new SimpleLinkType(sr.Configuration, Diagram.class); + linkType.addRule(new MappedElementsRule( + new RelatedObjectsAccessor(b.ConsistsOf, true), + new FieldAccessor>(Diagram.class.getField("elements")) + )); + addLinkType(linkType); + } + + addLinkType(MappingSchemas.fromAnnotations(g, AuxiliaryElement.class)); + addLinkType(MappingSchemas.fromAnnotations(g, StockElement.class)); + addLinkType(MappingSchemas.fromAnnotations(g, CloudElement.class)); + addLinkType(MappingSchemas.fromAnnotations(g, ValveElement.class)); + addLinkType(MappingSchemas.fromAnnotations(g, DependencyElement.class)); + addLinkType(MappingSchemas.fromAnnotations(g, FlowElement.class)); + } catch(NoSuchFieldException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/ConnectTool.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/ConnectTool.java new file mode 100644 index 00000000..d36ba476 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/ConnectTool.java @@ -0,0 +1,533 @@ +package org.simantics.sysdyn.ui.editor.participant; + +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.geom.Point2D; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; +import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup; +import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; +import org.simantics.g2d.command.CommandEvent; +import org.simantics.g2d.command.Commands; +import org.simantics.g2d.connection.IConnectionAdvisor; +import org.simantics.g2d.connection.handler.ConnectionHandler; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.DiagramMutator; +import org.simantics.g2d.diagram.DiagramUtils; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.PickContext; +import org.simantics.g2d.diagram.handler.Topology; +import org.simantics.g2d.diagram.handler.Topology.Connection; +import org.simantics.g2d.diagram.handler.Topology.Terminal; +import org.simantics.g2d.diagram.handler.TransactionContext.TransactionType; +import org.simantics.g2d.diagram.impl.Diagram; +import org.simantics.g2d.diagram.impl.MutatedDiagram; +import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant; +import org.simantics.g2d.diagram.participant.ElementPainter; +import org.simantics.g2d.diagram.participant.TerminalPainter; +import org.simantics.g2d.diagram.participant.TerminalPainter.TerminalHoverStrategy; +import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor; +import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.ElementHints; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.Parent; +import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; +import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; +import org.simantics.g2d.elementclass.BranchPoint; +import org.simantics.g2d.elementclass.FlagClass; +import org.simantics.g2d.elementclass.FlagHandler; +import org.simantics.g2d.event.Event; +import org.simantics.g2d.event.KeyEvent; +import org.simantics.g2d.event.MouseEvent; +import org.simantics.g2d.event.EventHandlerReflection.EventHandler; +import org.simantics.g2d.event.KeyEvent.KeyPressedEvent; +import org.simantics.g2d.event.MouseEvent.MouseButtonEvent; +import org.simantics.g2d.event.MouseEvent.MouseButtonPressedEvent; +import org.simantics.g2d.event.MouseEvent.MouseMovedEvent; +import org.simantics.g2d.participant.KeyUtil; +import org.simantics.g2d.participant.MouseUtil; +import org.simantics.g2d.participant.TransformUtil; +import org.simantics.g2d.snap.ISnapAdvisor; +import org.simantics.scenegraph.Node; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +public class ConnectTool extends AbstractDiagramParticipant { + + + public static final Key KEY_SG_NODE = new SceneGraphNodeKey(Node.class, "CONNECT_SG_NODE"); + + @Dependency TransformUtil util; + @Dependency ElementPainter diagramPainter; + @Dependency PickContext pickContext; + @Dependency PointerInteractor pi; + @Dependency MouseUtil mouseUtil; + @Dependency KeyUtil keys; + + boolean createFlags; + Point2D startPos; + + IElement startElement; + Terminal startTerminal; + + IElement endElement; + Terminal endTerminal; + + IDiagram inputDiagram; + MutatedDiagram ghostDiagram; + Topology topology; + + ElementClass connectionClass; + + ConnectionHandler connectionHandler; + IElement connection; + Deque edges = new ArrayDeque(); + Deque controlPoints = new ArrayDeque(); + int mouseId; + + Collection terminals = new ArrayList(); + + TerminalHoverStrategy originalStrategy = null; + TerminalHoverStrategy terminalHoverStrategy = new TerminalHoverStrategy() { + @Override + public boolean highlightEnabled() { + return true; + } + + @Override + public boolean highlight(TerminalInfo ti) { + IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR); + return canConnect(advisor, ti.e, ti.t) != null; + } + }; + + public ConnectTool(IDiagram diagram, ElementClass connectionClass, IElement startElement, Terminal startTerminal, int mouseId, Point2D mouseDiagramPos) + { + this.inputDiagram = diagram; + this.connectionClass = connectionClass; + this.mouseId = mouseId; + this.startPos = mouseDiagramPos; + this.startElement = startElement; + this.startTerminal = startTerminal; + } + + @Override + public void addedToContext(ICanvasContext ctx) { + + super.addedToContext(ctx); + + // Force terminals to always be highlighted. + originalStrategy = getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY); + setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, terminalHoverStrategy); + + // See if flags should be created or not + this.createFlags = Boolean.TRUE.equals(inputDiagram.getHint(DiagramHints.KEY_USE_CONNECTION_FLAGS)); + + // Mutate current diagram and add the connection to the mutated copy. + ghostDiagram = Diagram.mutate(inputDiagram); + topology = ghostDiagram.getDiagramClass().getSingleItem(Topology.class); + + IElement firstElement = null; + Terminal firstTerminal = null; + + // Where is start terminal? + if (startElement != null && startTerminal != null) { + // Whoomp, there it is. Is it already a part of an existing connection? + assert ElementUtils.peekDiagram(startElement) == inputDiagram; + IElement possibleConnection = getConnectionFromPart(startElement); + if (possibleConnection != null) { + // TODO: broken. + connection = ghostDiagram.getMutatedCorrespondence(possibleConnection); + } else { + connection = createConnection(connectionClass); + ghostDiagram.addElement(connection); + } + + connectionHandler = connection.getElementClass().getSingleItem(ConnectionHandler.class); + assert connectionHandler != null; + + firstElement = ghostDiagram.getMutatedCorrespondence(startElement); + firstTerminal = startTerminal; + } else { + connection = createConnection(connectionClass); + connectionHandler = connection.getElementClass().getSingleItem(ConnectionHandler.class); + assert connectionHandler != null; + ghostDiagram.addElement(connection); + + firstElement = createBranchPointOrFlag(startPos, EdgeEnd.Begin); + firstTerminal = ElementUtils.getSingleTerminal(firstElement); + startElement = firstElement; + startTerminal = firstTerminal; + } + + IElement secondElement = connectionHandler.newBranchPoint(connection); + controlPoints.add(secondElement); +// ghostDiagram.addElement(secondElement); + ElementUtils.setPos(secondElement, startPos); + Terminal secondTerminal = ElementUtils.getSingleTerminal(secondElement); + + IElement edge = connectionHandler.newEdge(connection); + edges.add(edge); +// ghostDiagram.addElement(edge); + + topology.connect(edge, EdgeEnd.Begin, firstElement, firstTerminal); + topology.connect(edge, EdgeEnd.End, secondElement, secondTerminal); + + } + + @Override + public void removedFromContext(ICanvasContext ctx) { + + if (getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY) == terminalHoverStrategy) { + if (originalStrategy != null) + setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, originalStrategy); + else + removeHint(TerminalPainter.TERMINAL_HOVER_STRATEGY); + } + + ghostDiagram.destroy(); + + super.removedFromContext(ctx); + } + + final static Composite ALPHA_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.75f); + public static final int PAINT_PRIORITY = ElementPainter.ELEMENT_PAINT_PRIORITY + 5; + + protected G2DParentNode node = null; + + @SGInit + public void initSG(G2DParentNode parent) { + node = parent.addNode(G2DParentNode.class); + node.setZIndex(PAINT_PRIORITY); + update(); + } + + public void update() { + if (ghostDiagram != null) { + diagramPainter.paintDiagram(node, ghostDiagram, ghostDiagram.getDifferences(), KEY_SG_NODE); + } + } + + @SGCleanup + public void cleanupSG() { + node.remove(); + node = null; + } + + boolean cancelPreviousBend() { + if (!routePointsAllowed()) + return false; + + // If not at the first branch point, remove the last branch + // point and edge. Otherwise, cancel action + if (controlPoints.size() < 2) { + DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR); + mutator.clear(); + update(); + remove(); + return true; + } + // Cancel prev bend + IElement lastControlPoint = controlPoints.removeLast(); + IElement prevControlPoint = controlPoints.peekLast(); + IElement lastEdge = edges.removeLast(); + for (Terminal t : ElementUtils.getTerminals(lastControlPoint, terminals, true)) + topology.disconnect(lastEdge, EdgeEnd.End, lastControlPoint, t); + for (Terminal t : ElementUtils.getTerminals(prevControlPoint, terminals, true)) + topology.disconnect(lastEdge, EdgeEnd.Begin, prevControlPoint, t); + connectionHandler.removeBranchPoint(connection, lastControlPoint); + connectionHandler.removeEdge(connection, lastEdge); + Point2D mousePos = mouseUtil.getMouseInfo(mouseId).canvasPosition; + ElementUtils.setPos(controlPoints.peekLast(), mousePos); + DiagramUtils.validateAndFix(ghostDiagram, getContext()); + update(); + setDirty(); + return true; + } + + @EventHandler(priority = 20) + public boolean handleEvent(Event e) { + // Back-space, cancel prev bend + if (e instanceof KeyPressedEvent) { + KeyEvent ke = (KeyEvent) e; + if (ke.keyCode == java.awt.event.KeyEvent.VK_BACK_SPACE) { + return cancelPreviousBend(); + } + } + if (e instanceof CommandEvent) { + CommandEvent ce = (CommandEvent) e; + if (ce.command.equals(Commands.CANCEL)) + { + DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR); + mutator.clear(); + update(); + remove(); + return true; + } + } + if (e instanceof MouseMovedEvent) { + MouseMovedEvent me = (MouseMovedEvent) e; + Point2D mouseControlPos = me.controlPosition; + Point2D mouseCanvasPos = util.controlToCanvas(mouseControlPos, new Point2D.Double()); + + ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR); + if (snapAdvisor != null) + snapAdvisor.snap(mouseCanvasPos); + + List tiList = ((org.simantics.sysdyn.ui.editor.participant.PointerInteractor)pi).pickTerminals(me.controlPosition); + TerminalInfo ti = null; + + IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR); + for(TerminalInfo info : tiList) { + if(advisor == null || info.e == null || info.t == null) + continue; + Object canConnect = canConnect(advisor, info.e, info.t); + if (canConnect != null) { + connection.setHint(ElementHints.KEY_CONNECTION_TYPE, canConnect); + ti = info; + } + } + + if (ti != null && !(ti.e == startElement && ti.t == startTerminal)) { + if (endElement == null) { + endElement = ti.e; + endTerminal = ti.t; + + IElement lastControlPoint = controlPoints.pollLast(); + topology.disconnect(edges.peekLast(), EdgeEnd.End, lastControlPoint, ElementUtils.getSingleTerminal(lastControlPoint)); + connectionHandler.removeBranchPoint(connection, lastControlPoint); + + topology.connect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal); + DiagramUtils.validateAndFix(ghostDiagram, getContext()); + } else if (!ti.e.equals(endElement) || !ti.t.equals(endTerminal)) { + topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal); + + endElement = ti.e; + endTerminal = ti.t; + + topology.connect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal); + DiagramUtils.validateAndFix(ghostDiagram, getContext()); + } + + update(); + setDirty(); + return false; + } + + { + connection.removeHint(ElementHints.KEY_CONNECTION_TYPE); + if (endElement != null) { + topology.disconnect(edges.peekLast(), EdgeEnd.End, ghostDiagram.getMutatedCorrespondence(endElement), endTerminal); + + endElement = null; + endTerminal = null; + + IElement bp = connectionHandler.newBranchPoint(connection); + controlPoints.add(bp); +// ghostDiagram.addElement(bp); + ElementUtils.setPos(controlPoints.peekLast(), mouseCanvasPos); + + topology.connect(edges.peekLast(), EdgeEnd.End, bp, ElementUtils.getSingleTerminal(bp)); + } else { + ElementUtils.setPos(controlPoints.peekLast(), mouseCanvasPos); + } + DiagramUtils.validateAndFix(ghostDiagram, getContext()); + + update(); + setDirty(); + } + + } + + if (e instanceof MouseButtonPressedEvent) { + MouseButtonEvent me = (MouseButtonEvent) e; + if (me.button==MouseEvent.LEFT_BUTTON && me.mouseId==mouseId) { + Point2D mouseControlPos = me.controlPosition; + Point2D mouseCanvasPos = util.getInverseTransform().transform(mouseControlPos, new Point2D.Double()); + + ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR); + if (snapAdvisor != null) + snapAdvisor.snap(mouseCanvasPos); + + // Clicked on a terminal .. End connection, End mode + if (endElement != null) { + attachToBranchPoint(); + commitDiagram(); + update(); + remove(); // Remove ConnectTool participant + return true; + } + } + } + + // Don't let any events slip to creator participant + if (e instanceof MouseEvent) { + MouseEvent me = (MouseEvent) e; + return me.mouseId == mouseId; + } + + return false; + } + + private void attachToBranchPoint() { + DiagramUtils.inDiagramTransaction(diagram, TransactionType.WRITE, new Runnable() { + + @Override + public void run() { + + // We are attaching to a branch point - some reordering is needed! + if (endElement.getElementClass().containsClass(BranchPoint.class)) { + + // Scrap everything we have and reconstruct + DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR); + mutator.clear(); + + HashMap bps = new HashMap(); + for(IElement bp : controlPoints) { + IElement nbp = mutator.newBranchPoint(endElement); + Point2D pos = ElementUtils.getPos(bp); + ElementUtils.setPos(nbp, pos); + bps.put(bp, nbp); + } + + for(IElement edge : edges) { + IElement newEdge = mutator.newEdge(endElement); + + // Disconnect and remove old edge + Connection b = mutator.getConnection(edge, EdgeEnd.Begin); + Connection e = mutator.getConnection(edge, EdgeEnd.End); + + IElement mappedB = bps.get(b.node) != null ? bps.get(b.node) : b.node; + IElement mappedE = bps.get(e.node) != null ? bps.get(e.node) : e.node; + + mutator.connect(newEdge, b.end, mappedB, b.terminal); + mutator.connect(newEdge, e.end, mappedE, e.terminal); + } + } + } + }); + } + + private void commitDiagram() { + DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR); + mutator.commit(); + } + + FlagClass.Type endToFlagType(EdgeEnd end) { + switch (end) { + case Begin: return FlagClass.Type.In; + case End: return FlagClass.Type.Out; + default: throw new IllegalArgumentException("unrecognized edge end: " + end); + } + } + + IElement createConnection(ElementClass element) { + DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR); + return mutator.newConnection(element); + } + + IElement createFlag(Point2D pos, EdgeEnd connectionEnd) { + + DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR); + IElement e = mutator.newFlag(); + + FlagHandler fh = e.getElementClass().getSingleItem(FlagHandler.class); + fh.setType(e, endToFlagType(connectionEnd)); + //fh.setMode(e, FlagClass.Mode.Internal); + ElementUtils.setPos(e, pos); + + ghostDiagram.addElement(e); + + return e; + + } + + /** + * Try to get a connection element from a connection part element. + * + * @param e a potential connection part + * @return null if e is not part a part of a connection. + */ + IElement getConnectionFromPart(IElement e) { + Parent parent = e.getElementClass().getAtMostOneItemOfClass(Parent.class); + if (parent == null) + return null; + IElement p = parent.getParent(e); + if (!p.getElementClass().containsClass(ConnectionHandler.class)) + return null; + return p; + } + + IElement createBranchPointOrFlag(Point2D pos, EdgeEnd connectionEnd) { + IElement e = null; + if (createFlags) { + e = createFlag(pos, connectionEnd); + } else { + e = connectionHandler.newBranchPoint(connection); + ElementUtils.setPos(e, pos); + } + return e; + } + + boolean routePointsAllowed() { + return Boolean.TRUE.equals(diagram.getHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS)); + } + + Object canConnect(final IConnectionAdvisor advisor, final IElement endElement, final Terminal endTerminal) { + if(startElement.equals(endElement)) return null; + + try { + return SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Object perform(ReadGraph g) throws DatabaseException { + + // Checking if connection type can be connected to the intended endElement + SysdynResource sr = SysdynResource.getInstance(g); + if(connection != null) { + StaticObjectAdapter soa = connectionClass.getSingleItem(StaticObjectAdapter.class); + Resource conntype = soa.adapt(Resource.class); + soa = endElement.getElementClass().getSingleItem(StaticObjectAdapter.class); + Resource end = soa.adapt(Resource.class); + if(conntype.equals(sr.DependencyConnection)) { + if(end.equals(sr.CloudSymbol)) return null; + //if(!(end.equals(sr.AuxiliarySymbol) || end.equals(sr.ValveSymbol))) return null; + } else if (conntype.equals(sr.FlowConnection)) { + if(!(end.equals(sr.StockSymbol) || end.equals(sr.ValveSymbol) || end.equals(sr.CloudSymbol))) return null; + } else { + return null; + } + } + + + if (advisor == null) + return Boolean.TRUE; + return advisor.canBeConnected(g, startElement, startTerminal, endElement, endTerminal); + } + + }); + } catch(DatabaseException e) { + e.printStackTrace(); + return null; + } + + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/PointerInteractor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/PointerInteractor.java new file mode 100644 index 00000000..f7994265 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/PointerInteractor.java @@ -0,0 +1,193 @@ +package org.simantics.sysdyn.ui.editor.participant; +/******************************************************************************* + * 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 + *******************************************************************************/ + +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.List; + +import org.simantics.g2d.canvas.Hints; +import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; +import org.simantics.g2d.canvas.impl.DependencyReflection.Reference; +import org.simantics.g2d.connection.IConnectionAdvisor; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.handler.PickContext; +import org.simantics.g2d.diagram.participant.Selection; +import org.simantics.g2d.diagram.participant.TerminalPainter; +import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil; +import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.IElementClassProvider; +import org.simantics.g2d.event.MouseEvent; +import org.simantics.g2d.event.EventHandlerReflection.EventHandler; +import org.simantics.g2d.event.MouseEvent.MouseButtonPressedEvent; +import org.simantics.g2d.participant.KeyUtil; +import org.simantics.g2d.participant.MouseUtil; +import org.simantics.g2d.participant.TransformUtil; +import org.simantics.g2d.routing.RouterFactory; +import org.simantics.g2d.utils.GeometryUtils; +import org.simantics.sysdyn.ui.elements2.AuxiliaryFactory; +import org.simantics.sysdyn.ui.elements2.CloudFactory; +import org.simantics.sysdyn.ui.elements2.connections.ConnectionClasses; + +/** + * Pointer tool does the following operations with mouse: + * - Selections + * - Scale + * - Rotate + * - Translate + * - Draws connections + * + * + * Pointer tool is active only when KEY_TOOLMODE is PointerToolMode + * + * TODO Pick rectangle not a point + * + * @author Toni Kalajainen + */ +public class PointerInteractor extends org.simantics.g2d.diagram.participant.pointertool.PointerInteractor { + + @Dependency Selection selection; + @Dependency KeyUtil keys; + @Dependency TransformUtil util; + @Dependency PickContext pickContext; + @Dependency MouseUtil mice; + @Reference TerminalPainter terminalPainter; + + public PointerInteractor(boolean clickSelect, boolean boxSelect, boolean dragElement, boolean dndDragElement, boolean connect, boolean doubleClickEdit, IElementClassProvider newConnectionClassProvider) { + super(clickSelect, boxSelect, dragElement, dndDragElement, connect, doubleClickEdit, newConnectionClassProvider); + } + + @EventHandler(priority = TOOL_PRIORITY) + public boolean handlePress(MouseButtonPressedEvent me) { + if (!connects()) return false; +// if (me.button != MouseEvent.LEFT_BUTTON) return false; + if (getHint(Hints.KEY_TOOL) != Hints.POINTERTOOL) return false; + assertDependencies(); + Point2D curCanvasPos = util.controlToCanvas(me.controlPosition, null); + + // Pick Terminal + TerminalInfo ti = pickTerminal(me.controlPosition); + + if(ti != null && elementClassProvider != null) { + + IElement terminalElement = ti.e; + + ElementClass connectionClass = null; + if( me.button == MouseEvent.LEFT_BUTTON && (me.stateMask & MouseEvent.ALT_MASK) != 0) { + if(terminalElement.getElementClass().getId().equals(CloudFactory.class.getSimpleName())) return false; + diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false)); + connectionClass = elementClassProvider.get(ConnectionClasses.DEPENDENCY); + + } else if (me.button == MouseEvent.RIGHT_BUTTON && (me.stateMask & MouseEvent.ALT_MASK) != 0) { + if(terminalElement.getElementClass().getId().equals(AuxiliaryFactory.class.getSimpleName())) return false; + diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true)); + connectionClass = elementClassProvider.get(ConnectionClasses.FLOW); + } else { + return false; + } + + ConnectTool bsi = null; + if (ti != null) { + IConnectionAdvisor advisor = diagram.getHint(DiagramHints.CONNECTION_ADVISOR); + if (advisor == null || (advisor != null && advisor.canBeginConnection(null, ti.e, ti.t))) { + bsi = new ConnectTool(diagram, connectionClass, ti.e, ti.t, me.mouseId, curCanvasPos); + } + } + /* Cannot be null + else { + ISnapAdvisor snapAdvisor = getHint(DiagramHints.SNAP_ADVISOR); + if(snapAdvisor != null) + snapAdvisor.snap(curCanvasPos); + + // Start connection out of thin air, without a terminal. + bsi = new ConnectTool(diagram, elementClassProvider.get(ConnectionClasses.DEPENDENCY), null, null, me.mouseId, curCanvasPos); + } + */ + if (bsi != null) { + getContext().add(bsi); + return true; + } + + } + return false; + } + + public List pickTerminals(Point2D controlPos) + { + Rectangle2D controlPickRect = new Rectangle2D.Double(controlPos.getX()-PointerInteractor.PICK_DIST, controlPos.getY()-PointerInteractor.PICK_DIST, PointerInteractor.PICK_DIST*2+1, PointerInteractor.PICK_DIST*2+1); + Shape canvasPickRect = GeometryUtils.transformShape(controlPickRect, util.getInverseTransform()); + List ti = TerminalUtil.pickTerminals(diagram, canvasPickRect, false, true); + return ti; + } + + /** + * Paint bend handles. Handle is a selectable and draggable object. + * + * @param gc + */ +// @Painter(priority = TerminalPainter.PAINT_PRIORITY + 10) +// public void paintBendHandles(GraphicsContext gc) { +// if (!connects()) return; +// double controlScale = GeometryUtils.getScale(gc.getGraphics2D().getTransform()); +// // TODO: use another key for setting the bend point stroke color +// //Color bgColor = getHint(Hints.KEY_BACKGROUND_COLOR); +// Color bgColor = null; +// if (bgColor==null) bgColor = Color.GRAY; +// Graphics2D g = gc.createClone(); +// util.controlToCanvas(g); +// if (!connects()) return; +// ArrayList bends = new ArrayList(); +// AffineTransform _at = g.getTransform(); +// Point2D bendPos = new Point2D.Double(); +// for (IElement e : selection.getAllSelections()) +// { +// BendsHandler bh = e.getElementClass().getAtMostOneItemOfClass(BendsHandler.class); +// if (bh==null) continue; +// bends.clear(); bh.getBends(e, bends); +// if (bends.isEmpty()) continue; +// g.setTransform(_at); +// g.transform( ElementUtils.getTransform(e) ); +// double scale = GeometryUtils.getScale( g.getTransform() ); +// for (Bend b : bends) { +// bh.getBendPosition(e, b, bendPos); +// g.translate(bendPos.getX(), bendPos.getY()); +// g.setColor(Color.WHITE); +// g.scale(controlScale / scale, controlScale / scale); +// g.fill(BENDS); +// g.setColor(bgColor); +// g.draw(BENDS); +// g.scale(scale / controlScale, scale / controlScale); +// g.translate(-bendPos.getX(), -bendPos.getY()); +// } +// } +// } +// static final Shape BENDS = new Rectangle2D.Double(-5, -5, 11, 11); + + + + // + /* + @EventHandler(priority = -1) + public boolean scaleKey(KeyEvent ke) { + boolean alt = (ke.stateMask & java.awt.event.MouseEvent.ALT_DOWN_MASK) != 0; + if (alt && ke.keyCode == java.awt.event.KeyEvent.VK_S) { + //ScaleMode sm = new ScaleMode(me.startCanvasPos, curCanvasPos, me.mouseId, elementsToScale); + //getContext().add(sm); + } + return false; + } + // + */ +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/Arcs.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/Arcs.java new file mode 100644 index 00000000..7651fcd0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/Arcs.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements; + +import java.awt.geom.Rectangle2D; + +public class Arcs { + + public static final double PI2 = Math.PI*2.0; + + /** + * Returns angle + 2PI * n such that the + * result is between -PI and PI. + */ + public static double normalizeAngle(double angle) { + return Math.IEEEremainder(angle, PI2); + } + + /** + * Returns true, if three normalized angles are clockwise oriented. + */ + public static boolean areClockwiseOrdered(double angle1, double angle2, double angle3) { + //System.out.println(angle1 + " " + angle2 + " " + angle3); + return angle1 < angle2 + ? (angle2 < angle3 || angle3 < angle1) + : (angle2 < angle3 && angle3 < angle1) + ; + } + + /** + * Returns an angle in radians between straight line from (x0,y0) to (x2,y2) + * and an arc from (x0,y0) to (x2,y2) thru (x1,y1). The angle + * is measured at (x0,y0) and is between -PI and PI. + */ + public static double angleOfArc( + double x0, double y0, + double x1, double y1, + double x2, double y2) { + double dx0 = x1-x0; + double dy0 = y1-y0; + double dx1 = x1-x2; + double dy1 = y1-y2; + double dx = x2-x0; + double dy = y2-y0; + // Length of cross product (p1-p0)x(p2-p0) + double dd = dx0*dy - dy0*dx; + + if(Math.abs(dd) < 1e-6) // Points are (almost) collinear + return 0.0; + else { + // (p1-p0)*(p1-p2) / dd + double offset = (dx0*dx1 + dy0*dy1) / dd; + double angle = Math.PI*0.5 - Math.atan(offset); + if(dd > 0.0) + angle = angle-Math.PI; + return angle; + + } + } + + private static double updateBestNextAngle(double curAngle, double bestAngle, double newAngle) { + if(newAngle < curAngle) + newAngle += PI2; + if(newAngle < bestAngle) + return newAngle; + return bestAngle; + } + + private static double updateBestPrevAngle(double curAngle, double bestAngle, double newAngle) { + if(newAngle > curAngle) + newAngle -= PI2; + if(newAngle > bestAngle) + return newAngle; + return bestAngle; + } + + public static double nextIntersectingAngle(double cx, double cy, double r, + double curAngle, Rectangle2D rect, boolean dir) { + if(!dir) { + double bestAngle = curAngle + PI2; + { + double dx = rect.getMinX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, -angle); + } + } + { + double dx = rect.getMaxX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, -angle); + } + } + { + double dy = cy - rect.getMinY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + { + double dy = cy - rect.getMaxY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + return normalizeAngle(bestAngle); + } + else { + double bestAngle = curAngle - PI2; + { + double dx = rect.getMinX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, -angle); + } + } + { + double dx = rect.getMaxX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, -angle); + } + } + { + double dy = cy - rect.getMinY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + { + double dy = cy - rect.getMaxY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + return normalizeAngle(bestAngle); + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/AuxiliaryElement.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/AuxiliaryElement.java new file mode 100644 index 00000000..068f65f8 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/AuxiliaryElement.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements; + +import org.simantics.objmap.annotations.GraphType; + +@GraphType("http://www.simantics.org/Sysdyn-1.0/Auxiliary") +public class AuxiliaryElement extends TextElement { + + public AuxiliaryElement() { + } + + public AuxiliaryElement(String label, double x, double y) { + super(label, x, y); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/CloudElement.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/CloudElement.java new file mode 100644 index 00000000..f7cd27fd --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/CloudElement.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.geom.Path2D; + +import org.simantics.h2d.element.handler.Connectable; +import org.simantics.h2d.node.ShapeNode; +import org.simantics.objmap.annotations.GraphType; +import org.simantics.scenegraph.g2d.G2DParentNode; + +@GraphType("http://www.simantics.org/Sysdyn-1.0/Cloud") +public class CloudElement extends RectangularElement implements Connectable { + + public static final double CLOUD_SIZE_X = 5.0; + public static final double CLOUD_SIZE_Y = 3.0; + + public static final double CLOUD_CURVES = 7; + + ShapeNode cloudNode; + boolean rotated = false; + + public CloudElement() { + } + + public CloudElement(double x, double y) { + this.posX = x; + this.posY = y; + } + + @Override + public void init(G2DParentNode parent) { + cloudNode = parent.addNode(ShapeNode.class); + cloudNode.setColor(Color.BLACK); + cloudNode.setScaleStroke(true); + cloudNode.setStroke(new BasicStroke(1)); + update(); + } + + @Override + public void remove() { + cloudNode.remove(); + } + + protected void update() { + //bounds.setFrame(posX-CLOUD_SIZE_X, posY-CLOUD_SIZE_Y, 2.0*CLOUD_SIZE_X, 2.0*CLOUD_SIZE_Y); + Path2D path = new Path2D.Double(); + double ox = CLOUD_SIZE_X; + double oy = 0.0; + path.moveTo(posX+ox, posY+oy); + for(int i=1;i 0.0); + double extent = angle1-angle0; + //double arcAngle = angle0; + if(angle < 0.0) { + double temp = angle0; + angle0 = angle1; + angle1 = temp; + extent = -extent; + } + if(extent < 0) + extent += Math.PI*2.0; + else if(extent >= 360.0) + extent -= Math.PI*2.0; + Shape shape = new Arc2D.Double(cx-r, cy-r, 2*r, 2*r, + Math.toDegrees(angle0), + Math.toDegrees(extent), + Arc2D.OPEN); + arcNode.setShape(shape); + + double xx = Math.cos(angle > 0.0 ? angle1 : angle0); + double yy = -Math.sin(angle > 0.0 ? angle1 : angle0); + Shape arrowShape = createArrow(cx + r*xx, cy + r*yy, + angle < 0.0 ? -yy : yy, + angle > 0.0 ? -xx : xx); + arrowNode.setShape(arrowShape); + } + + public void update() { + if(arcNode != null) + updateSceneGraph(); + fireElementUpdated(); + } + + @Override + public void getBounds(Rectangle2D bounds) { + bounds.setFrame(arcNode.getBounds()); + } + + @Override + public boolean hitTest(double x, double y, double tolerance) { + double dx = x-cx; + double dy = y-cy; + double dist = dx*dx + dy*dy; + if(dist < (r+tolerance)*(r+tolerance) && + dist > (r-tolerance)*(r-tolerance)) { + double angle = Arcs.normalizeAngle(Math.atan2(-dy, dx)); + if(Arcs.areClockwiseOrdered(angle0, angle, angle1)) + return true; + } + return false; + } + + class EventHandler extends DragEventHandler { + @Override + protected boolean begin(IDiagramEditor editor, DragEvent event) { + return event.startModifiers.equals("left"); + } + + @Override + protected void update(IDiagramEditor editor, DragEvent event) { + if(event == null) + return; + angle = Arcs.angleOfArc( + tail.getOrigo().getX(), tail.getOrigo().getY(), + event.current.getX(), event.current.getY(), + head.getOrigo().getX(), head.getOrigo().getY() + ); + DependencyElement.this.update(); + editor.requestRepaint(); + } + } + + @SuppressWarnings("unchecked") + @Override + public T getInterface(Class clazz) { + if(clazz == IEventHandler.class) + return (T)new EventHandler(); + return super.getInterface(clazz); + } + + @Override + public void elementRemoved(IElement element) { + remove(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/FlowElement.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/FlowElement.java new file mode 100644 index 00000000..9371a6d4 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/FlowElement.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements; + +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.h2d.element.Element; +import org.simantics.h2d.element.IElement; +import org.simantics.h2d.element.IElementListener; +import org.simantics.h2d.element.handler.Connectable; +import org.simantics.h2d.node.FilledShapeNode; +import org.simantics.h2d.node.ShapeNode; +import org.simantics.objmap.annotations.GraphType; +import org.simantics.objmap.annotations.RelatedElement; +import org.simantics.scenegraph.g2d.G2DParentNode; + +@GraphType("http://www.simantics.org/Sysdyn-1.0/Flow") +public class FlowElement extends Element implements IElementListener { + + public static double ARROW_LENGTH = 3.2; + public static double ARROW_WIDTH = 3; + + static final double OFFSET = 1.5; + static final double ARROW_OFFSET = 3.2; + + /* + * Total length of the arrow is ARROW_LENGTH1 + ARROW_LENGTH2 + */ + @RelatedElement("http://www.simantics.org/Sysdyn-1.0/HasTail") + Connectable tail; + @RelatedElement("http://www.simantics.org/Sysdyn-1.0/HasHead") + Connectable head; + + // Auxiliary + double angle0; + double angle1; + double cx; + double cy; + double r; + + // Scene graph + ShapeNode lineNode1; + ShapeNode lineNode2; + FilledShapeNode arrowNode; + + public FlowElement() { + } + + public FlowElement(Connectable tail, Connectable head) { + super(); + this.tail = tail; + this.head = head; + tail.addListener(this); + head.addListener(this); + } + + @Override + public void elementUpdated(IElement element) { + update(); + } + + @Override + public void remove() { + lineNode1.remove(); + lineNode2.remove(); + arrowNode.remove(); + tail.removeListener(this); + head.removeListener(this); + super.remove(); + } + + @Override + public void init(G2DParentNode parent) { + tail.addListener(this); + head.addListener(this); + + lineNode1 = parent.addNode(ShapeNode.class); + lineNode1.setScaleStroke(true); + lineNode2 = parent.addNode(ShapeNode.class); + lineNode2.setScaleStroke(true); + + arrowNode = parent.addNode(FilledShapeNode.class); + update(); + } + + protected void createArrow(Connectable head, Connectable tail) { + double x = tail.getOrigo().getX(); + double y = tail.getOrigo().getY(); + + Rectangle2D rect = new Rectangle2D.Double(); + head.getBounds(rect); + double cx = rect.getCenterX(); + double minx = rect.getMinX(); + double maxx = rect.getMaxX(); + double miny = rect.getMinY(); + double maxy = rect.getMaxY(); + + Path2D path = new Path2D.Double(); + + // approach from top + if (y < miny) { + path.moveTo(cx, miny); + path.lineTo(cx + ARROW_WIDTH, miny - ARROW_LENGTH); + path.lineTo(cx - ARROW_WIDTH, miny - ARROW_LENGTH); + } + + // approach from beneath + else if (y > maxy) { + path.moveTo(cx, maxy); + path.lineTo(cx + ARROW_WIDTH, maxy + ARROW_LENGTH); + path.lineTo(cx - ARROW_WIDTH, maxy + ARROW_LENGTH); + } + + // approach from left + else if (x < minx) { + path.moveTo(minx, y); + path.lineTo(minx - ARROW_LENGTH, y - ARROW_WIDTH); + path.lineTo(minx - ARROW_LENGTH, y + ARROW_WIDTH); + } + + // approach from right + else if (x > maxx) { + path.moveTo(maxx, y); + path.lineTo(maxx + ARROW_LENGTH, y - ARROW_WIDTH); + path.lineTo(maxx + ARROW_LENGTH, y + ARROW_WIDTH); + } + else + return; // FIXME (HN) This is just a quick bugfix, didn't understand the logic completely + + path.closePath(); + arrowNode.setShape(path); + } + + // TODO + + private void draw(boolean vertical, double ... coordinates) { + lineNode1.setShape(Flows.createOffsetLine(vertical, OFFSET, coordinates)); + lineNode2.setShape(Flows.createOffsetLine(vertical, -OFFSET, coordinates)); + } + + private void draw(boolean hasArrow, Connectable valve, Connectable node) { + double x0 = valve.getOrigo().getX(); + double y0 = valve.getOrigo().getY(); + double x1 = node.getOrigo().getX(); + double y1 = node.getOrigo().getY(); + + Rectangle2D rect = new Rectangle2D.Double(); + node.getBounds(rect); + + double minY = hasArrow ? rect.getMinY() - ARROW_OFFSET : rect.getMinY(); + double maxY = hasArrow ? rect.getMaxY() + ARROW_OFFSET : rect.getMaxY(); + double minX = hasArrow ? rect.getMinX() - ARROW_OFFSET : rect.getMinX(); + double maxX = hasArrow ? rect.getMaxX() + ARROW_OFFSET : rect.getMaxX(); + + + if( ((ValveElement)valve).rotated ) { + if(y1 > y0) + y0 += OFFSET; + else + y0 -= OFFSET; + if(rect.getMinX() <= x0 && rect.getMaxX() >= x0) { + if(y1 > y0) + draw(true, y0, x0, minY); + else + draw(true, y0, x0, maxY); + } + else { + if(x1 > x0) + draw(true, y0, x0, y1, minX); + else + draw(true, y0, x0, y1, maxX); + } + } + else { + if(x1 > x0) + x0 += OFFSET; + else + x0 -= OFFSET; + if(rect.getMinY() <= y0 && rect.getMaxY() >= y0) { + if(x1 > x0) + draw(false, x0, y0, minX); + else + draw(false, x0, y0, maxX); + } + else { + if(y1 > y0) + draw(false, x0, y0, x1, minY); + else + draw(false, x0, y0, x1, maxY); + } + } + + + } + + protected void updateSceneGraph() { + boolean hasArrow = tail instanceof ValveElement && !(head instanceof ValveElement); + if(tail instanceof ValveElement) + draw(hasArrow, tail, head); + else if(head instanceof ValveElement) + draw(hasArrow, head, tail); + if(hasArrow) + createArrow(head, tail); + } + + // TODO + + public void update() { + if(lineNode1 != null) + updateSceneGraph(); + fireElementUpdated(); + } + + @Override + public void getBounds(Rectangle2D bounds) { + bounds.setFrame(lineNode1.getBoundsInLocal()); + bounds.add(lineNode2.getBoundsInLocal()); + } + + @Override + public boolean hitTest(double x, double y, double tolerance) { + // FIXME totally incorrect + /*Rectangle2D rect = new Rectangle2D.Double(); + getBounds(rect); + return rect.contains(x, y);*/ + return false; + } + + @Override + public T getInterface(Class clazz) { + return super.getInterface(clazz); + } + + @Override + public void elementRemoved(IElement element) { + remove(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/Flows.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/Flows.java new file mode 100644 index 00000000..59e7def1 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/Flows.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements; + +import java.awt.geom.Path2D; + +public class Flows { + public static Path2D createLine(boolean vertical, double ... coordinates) { + Path2D path = new Path2D.Double(); + if(vertical) + path.moveTo(coordinates[1], coordinates[0]); + else + path.moveTo(coordinates[0], coordinates[1]); + for(int i=2;i elements = editor.getDiagram().getElements(); + for(IElement e : elements) { + if(e instanceof TextElement) { + TextElement t = (TextElement) e; + if(t != TextElement.this && t.label.equals(textNode.getText())) { + label = oldText; + //update(); + //editor.requestRepaint(); + } + } + } + } + } + + } + + public void beginRenameAction(IDiagramEditor editor) { + editor.addAction(new TextEditingAction(editor)); + } + + @Override + public boolean handle(IDiagramEditor editor, IEvent _event) { + if(_event instanceof KeyboardEvent) { + KeyboardEvent event = (KeyboardEvent)_event; + if(event.key.equals("F3") || event.key.equals("F2")) { + beginRenameAction(editor); + return true; + } + } + return false; + } + + boolean oldHasEquation = false; + + boolean hasEquation = true; + String oldLabel = label; + + @UpdateMethod + boolean updateCheck(ReadGraph g, Resource resource) { +// SysdynResource sr = SysdynResource.getInstance(g); + boolean update = false; +// try { +// hasEquation = +// !g.getObjects(resource, sr.HasExpression).isEmpty(); +// if(oldHasEquation != hasEquation) +// update = true; + if(!label.equals(oldLabel)) { + oldLabel = label; + update = true; + } + if(update) + update(); +// } catch (DatabaseException e) { +// e.printStackTrace(); +// } + return false; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveElement.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveElement.java new file mode 100644 index 00000000..81f14937 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveElement.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.geom.Path2D; + +import org.simantics.h2d.element.handler.Rotatable; +import org.simantics.h2d.node.ShapeNode; +import org.simantics.objmap.annotations.GraphType; +import org.simantics.scenegraph.g2d.G2DParentNode; + +@GraphType("http://www.simantics.org/Sysdyn-1.0/Valve") +public class ValveElement extends TextElement implements Rotatable { + + public static final double VALVE_SIZE = 5.0; + + ShapeNode valveNode; + boolean rotated = false; + + public ValveElement() { + } + + public ValveElement(double x, double y) { + this.posX = x; + this.posY = y; + } + + @Override + public double getTextDeltaY() { + return 8.0; + } + + @Override + public void init(G2DParentNode parent) { + valveNode = parent.addNode(ShapeNode.class); + valveNode.setColor(Color.BLACK); + valveNode.setScaleStroke(true); + valveNode.setStroke(new BasicStroke(1)); + super.init(parent); + } + + @Override + public void remove() { + valveNode.remove(); + super.remove(); + } + + @Override + protected void update() { + Path2D path = new Path2D.Double(); + path.moveTo(posX-VALVE_SIZE, posY-VALVE_SIZE); + if(rotated) { + path.lineTo(posX-VALVE_SIZE, posY+VALVE_SIZE); + path.lineTo(posX+VALVE_SIZE, posY-VALVE_SIZE); + } + else { + path.lineTo(posX+VALVE_SIZE, posY-VALVE_SIZE); + path.lineTo(posX-VALVE_SIZE, posY+VALVE_SIZE); + } + path.lineTo(posX+VALVE_SIZE, posY+VALVE_SIZE); + path.closePath(); + valveNode.setShape(path); + updateText(); + bounds.setFrame(posX-VALVE_SIZE, posY-VALVE_SIZE, 2.0*VALVE_SIZE, 2.0*VALVE_SIZE); + fireElementUpdated(); + } + + @Override + public void rotate(int amount) { + if((amount & 1) == 1) { + rotated = !rotated; + update(); + } + } + + public boolean isRotated() { + return rotated; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveElementOld.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveElementOld.java new file mode 100644 index 00000000..d63c7d4c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveElementOld.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.geom.Path2D; + +import org.simantics.h2d.element.handler.Connectable; +import org.simantics.h2d.element.handler.Rotatable; +import org.simantics.h2d.node.ShapeNode; +import org.simantics.objmap.annotations.GraphType; +import org.simantics.scenegraph.g2d.G2DParentNode; + +@GraphType("http://www.simantics.org/Sysdyn-1.0/Valve") +public class ValveElementOld extends RectangularElement implements Connectable, Rotatable { + + public static final double VALVE_SIZE = 5.0; + + ShapeNode valveNode; + boolean rotated = false; + + public ValveElementOld() { + } + + public ValveElementOld(double x, double y) { + this.posX = x; + this.posY = y; + } + + @Override + public void init(G2DParentNode parent) { + valveNode = parent.addNode(ShapeNode.class); + valveNode.setColor(Color.BLACK); + valveNode.setScaleStroke(true); + valveNode.setStroke(new BasicStroke(1)); + update(); + } + + @Override + public void remove() { + valveNode.remove(); + } + + protected void update() { + bounds.setFrame(posX-VALVE_SIZE, posY-VALVE_SIZE, 2.0*VALVE_SIZE, 2.0*VALVE_SIZE); + Path2D path = new Path2D.Double(); + path.moveTo(posX-VALVE_SIZE, posY-VALVE_SIZE); + if(rotated) { + path.lineTo(posX-VALVE_SIZE, posY+VALVE_SIZE); + path.lineTo(posX+VALVE_SIZE, posY-VALVE_SIZE); + } + else { + path.lineTo(posX+VALVE_SIZE, posY-VALVE_SIZE); + path.lineTo(posX-VALVE_SIZE, posY+VALVE_SIZE); + } + path.lineTo(posX+VALVE_SIZE, posY+VALVE_SIZE); + path.closePath(); + valveNode.setShape(path); + fireElementUpdated(); + } + + @Override + public void rotate(int amount) { + if((amount & 1) == 1) { + rotated = !rotated; + update(); + } + } + + public boolean isRotated() { + return rotated; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/AuxiliaryFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/AuxiliaryFactory.java new file mode 100644 index 00000000..1620323b --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/AuxiliaryFactory.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.geom.Ellipse2D; +import java.util.Collection; + +import org.simantics.db.Resource; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.handler.impl.BoundsOutline; +import org.simantics.g2d.element.handler.impl.DefaultTransform; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.g2d.element.handler.impl.OutlinePick; +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.TextColorImpl; +import org.simantics.g2d.element.handler.impl.TextFontImpl; +import org.simantics.g2d.element.handler.impl.TextImpl; +import org.simantics.g2d.image.Image; +import org.simantics.g2d.image.impl.ShapeImage; + +/** + * @author Tuukka Lehtonen + */ +public class AuxiliaryFactory extends SysdynElementFactory { + + // TODO: make the static symbol image a text "AUX" + private static final Image AUX_STATIC_IMAGE = new ShapeImage(new Ellipse2D.Double(-5, -2, 10, 4), null, new BasicStroke(1), true); + + @Override + protected ElementClass compileElementClass(Resource elementType, Collection terminals) { + return ElementClass.compile( + SimpleElementLayers.INSTANCE, + OutlinePick.INSTANCE, + TextImpl.INSTANCE, + TextColorImpl.BLACK, + TextFontImpl.DEFAULT, + DefaultTransform.INSTANCE, + new StaticObjectAdapter(elementType), + new StaticSymbolImpl(AUX_STATIC_IMAGE), + StaticSymbolImageInitializer.INSTANCE, + HoverTextElementHandler.INSTANCE, + BoundsOutline.INSTANCE, +// HoverImpl.INSTANCE, + new WholeElementTerminals(terminals) + ).setId(AuxiliaryFactory.class.getSimpleName()); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/BorderSceneGraph.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/BorderSceneGraph.java new file mode 100644 index 00000000..96a3cd5e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/BorderSceneGraph.java @@ -0,0 +1,43 @@ +package org.simantics.sysdyn.ui.elements2; + +import java.awt.geom.AffineTransform; + +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.SceneGraph; +import org.simantics.h2d.node.RectangleNode; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +public class BorderSceneGraph implements SceneGraph, Callback { + + public static final BorderSceneGraph INSTANCE = new BorderSceneGraph(); + + private static final long serialVersionUID = 5544256245734478634L; + + private static final Key BORDER_NODE = new SceneGraphNodeKey(RectangleNode.class, "BORDER_NODE"); + + @Override + public void init(IElement e, G2DParentNode parent) { + RectangleNode node = ElementUtils.getOrCreateNode(e, parent, BORDER_NODE, "border", RectangleNode.class, this); + + // Calculate borders from text node bounds. + node.init(ElementUtils.getElementBounds(e)); + AffineTransform transform = ElementUtils.getTransform(e); + if(transform != null) + node.setTransform(transform); + } + + @Override + public void run(RectangleNode node) { + node.setZIndex(-10); + } + + @Override + public void cleanup(IElement e) { + ElementUtils.removePossibleNode(e, BORDER_NODE); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/CloudFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/CloudFactory.java new file mode 100644 index 00000000..20da2813 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/CloudFactory.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; + +import org.simantics.db.Resource; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.HandleMouseEvent; +import org.simantics.g2d.element.handler.InternalSize; +import org.simantics.g2d.element.handler.SceneGraph; +import org.simantics.g2d.element.handler.impl.BoundsOutline; +import org.simantics.g2d.element.handler.impl.DefaultTransform; +import org.simantics.g2d.element.handler.impl.HoverImpl; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.g2d.element.handler.impl.OutlinePick; +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.TextColorImpl; +import org.simantics.g2d.element.handler.impl.TextFontImpl; +import org.simantics.g2d.element.handler.impl.TextImpl; +import org.simantics.g2d.event.MouseEvent; +import org.simantics.g2d.event.MouseEvent.MouseEnterEvent; +import org.simantics.g2d.event.MouseEvent.MouseExitEvent; +import org.simantics.g2d.image.Image; +import org.simantics.g2d.image.impl.ShapeImage; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.nodes.ShapeNode; +import org.simantics.utils.datastructures.hints.IHintListener; +import org.simantics.utils.datastructures.hints.IHintObservable; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +public class CloudFactory extends SysdynElementFactory { + + public static final double CLOUD_SIZE_X = 5.0; + public static final double CLOUD_SIZE_Y = 3.0; + public static final double CLOUD_CURVES = 7; + + private static final BasicStroke STROKE = new BasicStroke(1f); + private static final Image DEFAULT_IMAGE = new ShapeImage(getCloudShape(), null, STROKE, true); + + static Shape getCloudShape() { + Path2D path = new Path2D.Double(); + double ox = CLOUD_SIZE_X; + double oy = 0.0; + double posX = 0; + double posY = 0; + path.moveTo(posX + ox, posY + oy); + for (int i = 1; i < CLOUD_CURVES + 1; ++i) { + double angle = (Math.PI * 2.0 / CLOUD_CURVES) * i; + double x = Math.cos(angle) * CLOUD_SIZE_X; + double y = Math.sin(angle) * CLOUD_SIZE_Y; + path.curveTo( + posX + (2*ox + x)*0.5, posY + (2*oy + y)*0.5, + posX + (ox + 2*x)*0.5, posY + (oy + 2*y)*0.5, + posX + x, posY + y); + ox = x; + oy = y; + } + return path; + } + + @Override + protected ElementClass compileElementClass(Resource elementType, Collection terminals) { + return ElementClass.compile( + SimpleElementLayers.INSTANCE, + OutlinePick.INSTANCE, + TextImpl.INSTANCE, + TextColorImpl.BLACK, + TextFontImpl.DEFAULT, + DefaultTransform.INSTANCE, + new StaticObjectAdapter(elementType), + new StaticSymbolImpl(DEFAULT_IMAGE), + StaticSymbolImageInitializer.INSTANCE, + CloudSceneGraph.INSTANCE, + HoverImpl.INSTANCE, + BoundsOutline.INSTANCE, + new WholeElementTerminals(terminals) + ).setId(CloudFactory.class.getSimpleName()); + } + + public static class CloudSceneGraph implements SceneGraph, InternalSize, HandleMouseEvent { + + private static final long serialVersionUID = 5544256245734478634L; + + public static final CloudSceneGraph INSTANCE = new CloudSceneGraph(); + + private static final Key NODE = new SceneGraphNodeKey(ShapeNode.class, "VALVE_NODE"); + + private IHintListener hoverHintListener; + + @Override + public void init(IElement e, G2DParentNode parent) { + AffineTransform at = ElementUtils.getTransform(e); + HoverShapeNode node = ElementUtils.getOrCreateNode(e, parent, NODE, "valve", HoverShapeNode.class); + + node.setStroke(STROKE); + node.setScaleStroke(true); + node.setColor(Color.BLACK); + node.setShape(getCloudShape()); + AffineTransform transform = ElementUtils.getTransform(e); + if(transform != null) + node.setTransform(transform); + + if(at != null) + node.setTransform(at); + + hoverHintListener = new IHintListener() { + + @Override + public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { + + } + + @Override + public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { + IElement e = (IElement)sender; + HoverShapeNode shape = (HoverShapeNode) e.getHint(NODE); + shape.setHover(ElementUtils.isHovering(e)); + } + }; + e.addHintListener(hoverHintListener); + } + + @Override + public void cleanup(IElement e) { + e.removeHintListener(hoverHintListener); + ElementUtils.removePossibleNode(e, NODE); + } + + @Override + public Rectangle2D getBounds(IElement e, Rectangle2D size) { + if (size == null) + size = new Rectangle2D.Double(); + size.setFrame(getCloudShape().getBounds2D()); + return size; + } + + @Override + public boolean handleMouseEvent(IElement e, ICanvasContext ctx, MouseEvent me) { + if (me instanceof MouseEnterEvent) { + ElementUtils.setHover(e, true); + return false; + } else if (me instanceof MouseExitEvent) { + ElementUtils.setHover(e, false); + return false; + } + return false; + } + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ComponentNameSynchronizer.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ComponentNameSynchronizer.java new file mode 100644 index 00000000..a1f14b32 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ComponentNameSynchronizer.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.diagram.synchronization.IModificationQueue; +import org.simantics.diagram.synchronization.ISynchronizationContext; +import org.simantics.diagram.synchronization.graph.GraphSynchronizationHints; +import org.simantics.diagram.synchronization.graph.RelatedPropertyModification; +import org.simantics.diagram.synchronization.graph.ResourceSynchronizer; +import org.simantics.g2d.element.ElementHints; +import org.simantics.modeling.ModelingResources; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintObservable; + +/** + * @author Tuukka Lehtonen + */ +public class ComponentNameSynchronizer extends ResourceSynchronizer { + + public static final ComponentNameSynchronizer INSTANCE = new ComponentNameSynchronizer(); + + private static final Key[] SYNCHRONIZED_HINTS = { + ElementHints.KEY_TEXT + }; + + @Override + public Key[] getSynchronizedHints() { + return SYNCHRONIZED_HINTS; + } + + @Override + public boolean hintChanged(ISynchronizationContext context, IModificationQueue queue, Resource object, IHintObservable sender, Key key, Object oldValue, Object newValue) { + if (ElementHints.KEY_TEXT.equals(key)) { + Session session = context.get(GraphSynchronizationHints.SESSION); + Builtins b = session.getBuiltins(); + ModelingResources mr = session.getService(ModelingResources.class); + return queue.offer(new RelatedPropertyModification(object, mr.ElementToComponent, b.HasName, b.String, newValue, StringBindingDefault.INSTANCE), null); + } + return false; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConfigurationDiagramClassAdapter.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConfigurationDiagramClassAdapter.java new file mode 100644 index 00000000..6e4a945a --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ConfigurationDiagramClassAdapter.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import org.simantics.db.AsyncReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.adaption.Adapter; +import org.simantics.db.procedure.AsyncProcedure; +import org.simantics.diagram.adapter.DiagramClassAdapter; +import org.simantics.g2d.diagram.DiagramClass; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.LifeCycle; +import org.simantics.g2d.routing.RouterFactory; + +/** + * @author Tuukka Lehtonen + */ +public class ConfigurationDiagramClassAdapter implements Adapter { + + @Override + public void adapt(AsyncReadGraph g, Resource r, AsyncProcedure procedure) { + procedure.execute(g, DiagramClassAdapter.INSTANCE.newClassWith( + Initializer.INSTANCE + )); + } + + static class Initializer extends LifeCycle.Stub { + public static final Initializer INSTANCE = new Initializer(); + + @Override + public void onDiagramCreated(IDiagram diagram) { + diagram.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false)); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/GraphPropertyNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/GraphPropertyNode.java new file mode 100644 index 00000000..04d0674d --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/GraphPropertyNode.java @@ -0,0 +1,101 @@ +package org.simantics.sysdyn.ui.elements2; + +import java.awt.AWTEvent; +import java.awt.event.MouseEvent; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Field; +import java.util.HashMap; + +import org.simantics.scenegraph.g2d.G2DNode; +import org.simantics.scenegraph.g2d.events.SGMouseEvent; + +abstract public class GraphPropertyNode extends G2DNode { + + private static final long serialVersionUID = 245761992671850588L; + + HashMap fields = new HashMap(); + + private PropertyChangeListener fieldListener = null; + + protected GraphPropertyNode() { + for(Field f : getClass().getFields()) { +// System.out.println("register field '" + f.getName() + "'"); + fields.put(f.getName(), f); + } + } + + public void setFieldListener(PropertyChangeListener listener) { + this.fieldListener = listener; + } + + public void propertyChange(String field, Object value) { + } + + public void setProperty(String field, Object value) { + Field f = fields.get(field); + if(f == null) { + System.err.println("GraphPropertyNode tried to set undefined property '" + field + "'"); + return; + } + try { + //System.out.println("setting field '" + field + "'"); + f.set(this, value); + propertyChange(field, value); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + public void commitProperty(String field, Object value) { + if(fieldListener != null) { + fieldListener.propertyChange(new PropertyChangeEvent(this, field, null, value)); + } + } + + boolean pressHit = false; + + public boolean hitTest(double x, double y, double tolerance) { + return false; + } + + @Override + public void handleEvent(AWTEvent event) { + if(event instanceof SGMouseEvent) { + SGMouseEvent e = (SGMouseEvent)event; + boolean hit = hitTest(e.getDoubleX(), e.getDoubleY(), 3.0); + if(e.getID() == MouseEvent.MOUSE_DRAGGED) { + mouseDragged((SGMouseEvent)event, pressHit, hit); + } + if(e.getID() == MouseEvent.MOUSE_PRESSED) { + pressHit = hit; + mouseReleased((SGMouseEvent)event, hit); + } + if(e.getID() == MouseEvent.MOUSE_RELEASED) + mouseReleased((SGMouseEvent)event, hit); + if(e.getID() == MouseEvent.MOUSE_MOVED) + mouseMoved((SGMouseEvent)event, hit); + } + } + + public void mouseDragged(SGMouseEvent event, boolean pressHit, boolean currentHit) { + + } + + public void mouseReleased(SGMouseEvent event, boolean hit) { + + } + + public void mouseMoved(SGMouseEvent event, boolean hit) { + + } + + @Override + public Rectangle2D getBoundsInLocal() { + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverShapeNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverShapeNode.java new file mode 100644 index 00000000..1db4490c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverShapeNode.java @@ -0,0 +1,46 @@ +package org.simantics.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.Stroke; +import org.simantics.scenegraph.g2d.nodes.ShapeNode; + +public class HoverShapeNode extends ShapeNode { + + private static final long serialVersionUID = -4580969977763722602L; + + transient public boolean hover = false; + + @Override + protected void renderShape(Graphics2D g2d, Shape s) { + boolean fill = Boolean.TRUE.equals(dynamicFill) ? true : this.fill; + if (fill) + g2d.fill(s); + + if(hover) { + BasicStroke oldStroke = (BasicStroke)g2d.getStroke(); + Color oldColor = g2d.getColor(); + g2d.setColor(Color.LIGHT_GRAY); + float lineWidth = oldStroke.getLineWidth() * 6; + g2d.setStroke(new BasicStroke(lineWidth < 1.0f ? lineWidth : 1.0f)); + g2d.draw(s); + g2d.setColor(oldColor); + g2d.setStroke(oldStroke); + } + + Stroke stroke = dynamicStroke != null ? dynamicStroke : this.stroke; + if (stroke != null) + g2d.draw(s); + + } + + public void setHover(boolean hover) { + this.hover = hover; + repaint(); + } + + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextElementHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextElementHandler.java new file mode 100644 index 00000000..479a6884 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextElementHandler.java @@ -0,0 +1,43 @@ +package org.simantics.sysdyn.ui.elements2; + +import java.awt.geom.Rectangle2D; + +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.handler.InternalSize; +import org.simantics.g2d.utils.Alignment; + +public class HoverTextElementHandler extends HoverTextElementNoBounds implements InternalSize { + + private static final long serialVersionUID = 8800738238681432901L; + + public static final HoverTextElementHandler INSTANCE = new HoverTextElementHandler(); + + public HoverTextElementHandler() { + super(); + } + + public HoverTextElementHandler(double originX, double originY, Alignment horizontalAlignment) { + super(originX, originY, horizontalAlignment); + } + + public HoverTextElementHandler(double originX, double originY, Alignment horizontalAlignment, double borderWidth) { + super(originX, originY, horizontalAlignment, borderWidth); + } + + public HoverTextElementHandler(double originX, double originY, Alignment horizontalAlignment, double borderWidth, + double paddingX, double paddingY, boolean editable) { + super(originX, originY, horizontalAlignment, borderWidth, paddingX, paddingY, editable); + } + + @Override + public Rectangle2D getBounds(IElement e, Rectangle2D size) { + HoverTextNode node = (HoverTextNode) e.getHint(SG_NODE); + if (size == null) + size = new Rectangle2D.Double(); + if (node != null) + size.setRect(node.getBoundsInLocal()); + else + size.setFrame(0, 0, 0, 0); + return size; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextElementNoBounds.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextElementNoBounds.java new file mode 100644 index 00000000..e5b502d7 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextElementNoBounds.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import java.awt.Color; +import java.awt.Font; +import java.awt.geom.AffineTransform; + +import org.simantics.diagram.elements.ITextListener; +import org.simantics.diagram.elements.TextElementNoBounds; +import org.simantics.diagram.elements.TextNode; +import org.simantics.g2d.diagram.DiagramUtils; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.element.ElementHints; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.utils.Alignment; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.datastructures.hints.IHintListener; +import org.simantics.utils.datastructures.hints.IHintObservable; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +/** + * ElementHandler for text elements + * In-line editing supported. + * + * @author Marko Luukkainen + */ +public class HoverTextElementNoBounds extends TextElementNoBounds { + + private static final long serialVersionUID = -148784588840819612L; + + public static final HoverTextElementNoBounds INSTANCE = new HoverTextElementNoBounds(); + + private IHintListener hoverHintListener; + + public HoverTextElementNoBounds() { + super(0, 0, Alignment.LEADING, 0); + } + + public HoverTextElementNoBounds(double originX, double originY, Alignment horizontalAlignment) { + super(originX, originY, horizontalAlignment, 0); + } + + public HoverTextElementNoBounds(double originX, double originY, Alignment horizontalAlignment, double borderWidth) { + super(originX, originY, horizontalAlignment, borderWidth); + } + + public HoverTextElementNoBounds(double originX, double originY, Alignment horizontalAlignment, double borderWidth, double paddingX, double paddingY, boolean editable) { + super(originX, originY, horizontalAlignment, borderWidth, paddingX, paddingY, editable); + } + + @Override + public void init(final IElement e, G2DParentNode parent) { + HoverTextNode node = ElementUtils.getOrCreateNode(e, parent, SG_NODE, "text", HoverTextNode.class, new Callback() { + @Override + public void run(HoverTextNode node) { + node.setTextListener(new ITextListener() { + @Override + public void textChanged() {} + + @Override + public void textEditingStarted() {} + + @Override + public void textEditingCancelled() { + TextNode node = (TextNode) e.getHint(SG_NODE); + if (node != null) + endEdit(node); + } + + @Override + public void textEditingEnded() { + TextNode node = (TextNode) e.getHint(SG_NODE); + if (node == null) + return; + //System.out.println("Node text changed: " + node.getText()); + ElementUtils.setText(e, node.getText()); + IDiagram diagram = ElementUtils.getDiagram(e); + DiagramUtils.synchronizeHintsToBackend(diagram, e); + endEdit(node); + } + }); + } + }); + + //Font font = new Font("Tahoma", 0, 12); + Font font = ElementUtils.getTextFont(e); + Color color = ElementUtils.getTextColor(e); + Color fillColor = ElementUtils.getFillColor(e); + Color borderColor = ElementUtils.getBorderColor(e, Color.BLACK); + String text = ElementUtils.getText(e); + AffineTransform at = ElementUtils.getTransform(e); + node.init(text, font, color, originX, originY, 0.235); + node.setBackgroundColor(fillColor); + node.setBorderColor(borderColor); + node.setHorizontalAlignment((byte) horizontalAlignment.ordinal()); + node.setPadding(paddingX, paddingY); + node.setBorderWidth((float) borderWidth); + node.setEditable(editable); + if(at != null) + node.setTransform(at); + + this.hoverHintListener = new IHintListener() { + @Override + public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { + + } + + @Override + public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { + if(key == ElementHints.KEY_HOVER) { + IElement e = (IElement)sender; + TextNode name = (TextNode) e.getHint(SG_NODE); + if(name != null) + name.setHover((Boolean)e.getHint(ElementHints.KEY_HOVER)); + } + } + }; + e.addHintListener(hoverHintListener); + } + + @Override + public void cleanup(IElement e) { + if(hoverHintListener != null) + e.removeHintListener(hoverHintListener); + ElementUtils.removePossibleNode(e, SG_NODE); + } +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextNode.java new file mode 100644 index 00000000..a55f7544 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/HoverTextNode.java @@ -0,0 +1,52 @@ +package org.simantics.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.font.FontRenderContext; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.Rectangle2D; + +import org.simantics.diagram.elements.TextNode; +import org.simantics.g2d.utils.Alignment; +import org.simantics.scenegraph.utils.NodeUtil; + +public class HoverTextNode extends TextNode { + + private static final long serialVersionUID = 3539499125943249895L; + + + @Override + public void render(Graphics2D g) { + + g.transform(transform); + if(horizontalAlignment == Alignment.CENTER.ordinal()) { + FontRenderContext frc = g.getFontRenderContext(); + Rectangle2D stringBounds = font.getStringBounds(getText(), frc); + g.translate(- stringBounds.getWidth() / 2 * scale, 0); + } + Rectangle2D r = getBoundsInLocal(); + + boolean selected = NodeUtil.isSelected(this, 1); + if (!selected && hover){ + + BasicStroke oldStroke = (BasicStroke)g.getStroke(); + Color oldColor = g.getColor(); + g.setColor(Color.LIGHT_GRAY); + g.setStroke(new BasicStroke((float)(2.0f * scale))); + g.translate(x, y); + g.draw(r); + g.translate(-x, -y); + g.setColor(oldColor); + g.setStroke(oldStroke); + } + try { + g.transform(transform.createInverse()); + } catch (NoninvertibleTransformException e) { + e.printStackTrace(); + } + super.render(g); + + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/Input.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/Input.java new file mode 100644 index 00000000..60f9a4c5 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/Input.java @@ -0,0 +1,25 @@ +package org.simantics.sysdyn.ui.elements2; + +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.handler.ElementHandler; + +public class Input implements ElementHandler { + + private static final long serialVersionUID = -1526125969376635502L; + + public static final Input INSTANCE = new Input(); + + public String getInputReference(IElement e) { + return e.getHint(SysdynElementHints.KEY_INPUT_REFERENCE); + } + + + public void setInputReference(IElement e, String inputReference) { + if (inputReference != null) + e.setHint(SysdynElementHints.KEY_INPUT_REFERENCE, inputReference); + else + e.removeHint(SysdynElementHints.KEY_INPUT_REFERENCE); + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/InputFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/InputFactory.java new file mode 100644 index 00000000..43936fd3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/InputFactory.java @@ -0,0 +1,210 @@ +package org.simantics.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; + +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.elements.TextNode; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.diagram.ui.DiagramModelHints; +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.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.InternalSize; +import org.simantics.g2d.element.handler.impl.BoundsOutline; +import org.simantics.g2d.element.handler.impl.DefaultTransform; +import org.simantics.g2d.element.handler.impl.HoverImpl; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.g2d.element.handler.impl.OutlinePick; +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.TextColorImpl; +import org.simantics.g2d.element.handler.impl.TextFontImpl; +import org.simantics.g2d.element.handler.impl.TextImpl; +import org.simantics.g2d.image.Image; +import org.simantics.g2d.image.impl.ShapeImage; +import org.simantics.g2d.utils.Alignment; +import org.simantics.modeling.ModelingResources; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +public class InputFactory extends SysdynElementFactory { + + private static final BasicStroke STROKE = new BasicStroke(1f); + private static final Image INPUT_IMAGE = new ShapeImage(getInputShape(), null, STROKE, true); + + static Shape getInputShape() { + Path2D path = new Path2D.Double(); + path.moveTo(0, -1); + path.lineTo(5, -1); + path.lineTo(5, -2.5); + path.lineTo(7.5, 0); + path.curveTo(7.5, -2.5, 12.5, -2.5, 12.5, 0); + path.curveTo(12.5, 2.5, 7.5, 2.5, 7.5, 0); + path.lineTo(5, 2.5); + path.lineTo(5, 1); + path.lineTo(0, 1); + path.closePath(); + return path; + } + + @Override + protected ElementClass compileElementClass(Resource elementType, Collection terminals) { + return ElementClass.compile( + SimpleElementLayers.INSTANCE, + OutlinePick.INSTANCE, + TextImpl.INSTANCE, + TextColorImpl.BLACK, + TextFontImpl.DEFAULT, + DefaultTransform.INSTANCE, + new StaticObjectAdapter(elementType), + new StaticSymbolImpl(INPUT_IMAGE), + StaticSymbolImageInitializer.INSTANCE, + Input.INSTANCE, + new InputSceneGraph(0, 0, Alignment.LEADING), + BoundsOutline.INSTANCE, + HoverImpl.INSTANCE, + new WholeElementTerminals(terminals) + ).setId(InputFactory.class.getSimpleName()); + } + + @Override + public void load(ReadGraph graph, final ICanvasContext canvas, final IDiagram diagram, final Resource element, final IElement e) throws DatabaseException { + super.load(graph, canvas, diagram, element, e); + Builtins b = graph.getBuiltins(); + ModelingResources mr = ModelingResources.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + Resource component = null; + Resource dependency = null; + Resource refersTo = null; + Resource module = null; + String moduleName = ""; + String referenceName = ""; + component = graph.getPossibleObject(element, mr.ElementToComponent); + if(component != null) + dependency = graph.getPossibleObject(component, sr.IsHeadOf); + if(dependency != null) { + refersTo = graph.getPossibleObject(dependency, sr.RefersTo); + if(refersTo != null) { + referenceName = (String) graph.getPossibleRelatedValue(refersTo, b.HasName); + module = graph.getPossibleObject(dependency, sr.HasTail); + moduleName = (String) graph.getPossibleRelatedValue(module, b.HasName); + } + } else { + Resource runtime = diagram.getHint((DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE)); + DiagramResource dr = DiagramResource.getInstance(graph); + String variable = (String)graph.getRelatedValue(runtime, dr.HasVariable); + Resource moduleRepresentation = graph.getPossibleResource(variable); + if(moduleRepresentation != null) + module = graph.getPossibleObject(moduleRepresentation, b.Represents); + if(module != null) + for(Resource dep : graph.getObjects(module, sr.IsHeadOf)) { + Resource reference = graph.getPossibleObject(dep, sr.RefersTo); + if(reference!= null && reference.equals(component)) { + refersTo = graph.getSingleObject(dep, sr.HasTail); + referenceName = (String) graph.getPossibleRelatedValue(refersTo, b.HasName); + moduleRepresentation = graph.getPossibleResource(variable.substring(0, variable.lastIndexOf("/"))); + Resource parent = graph.getPossibleObject(moduleRepresentation, b.PartOf); + String parentURI = graph.getURI(parent); + String modelURI = diagram.getHint((DiagramModelHints.KEY_DIAGRAM_MODEL_URI)); + module = graph.getPossibleObject(moduleRepresentation, b.Represents); + if(parentURI.equals(modelURI) || module == null) + moduleName = ""; + else { + moduleName = (String) graph.getPossibleRelatedValue(module, b.HasName); + } + break; + } + } + } + + String inputReference = null; + if (moduleName != null && refersTo != null) { + inputReference = moduleName + "." + referenceName; + } + if (inputReference == null) { + inputReference = ""; + } + + SysdynElementUtils.setInputReference(e, inputReference); + + Font font = ElementUtils.getTextFont(e); + font = font.deriveFont(font.getStyle() + Font.ITALIC); + ElementUtils.setTextFont(e, font); + ElementUtils.setHover(e, false); + } + + + public static class InputSceneGraph extends HoverTextElementNoBounds implements InternalSize { + + private static final long serialVersionUID = -3713275157729126409L; + public static final Key INPUT_SG_NODE = new SceneGraphNodeKey(TextNode.class, "INPUT_SG_NODE"); + + private final double originX; + private final Alignment horizontalAlignment; + + public InputSceneGraph(double originX, double originY, Alignment horizontalAlignment) { + super(originX, originY, horizontalAlignment, 0.0, 2.0, 2.0, true); + this.originX = originX; + this.horizontalAlignment = horizontalAlignment; + } + + @Override + public void init(final IElement e, G2DParentNode parent) { + super.init(e, parent); + TextNode node = ElementUtils.getOrCreateNode(e, parent, INPUT_SG_NODE, "input", TextNode.class); + Font font = ElementUtils.getTextFont(e); + font = font.deriveFont((float) 10.0); + font = font.deriveFont(Font.ITALIC); + Color color = new Color(150, 150, 150); + Color fillColor = ElementUtils.getFillColor(e); + Color borderColor = ElementUtils.getBorderColor(e, Color.BLACK); + String text = SysdynElementUtils.getInputReference(e); + double scale = 0.235; + AffineTransform at = ElementUtils.getTransform(e); + node.init(text, font, color, originX, font.getSize2D() * scale, scale); + node.setBackgroundColor(fillColor); + node.setBorderColor(borderColor); + node.setHorizontalAlignment((byte) horizontalAlignment.ordinal()); + node.setBorderWidth((float) 0); + node.setEditable(false); + node.setShowSelection(false); + + if(at != null) + node.setTransform(at); + } + + @Override + public Rectangle2D getBounds(IElement e, Rectangle2D size) { + TextNode name = (TextNode) e.getHint(SG_NODE); + TextNode reference = (TextNode) e.getHint(INPUT_SG_NODE); + if (size == null) + size = new Rectangle2D.Double(); + if (name != null) + size.setRect(name.getBoundsInLocal()); + if(reference != null) { + if (reference.getBoundsInLocal().getWidth() > size.getWidth()) + size.setRect(size.getX(), size.getY(), reference.getBoundsInLocal().getWidth(), size.getHeight()); + } + else + size.setFrame(0, 0, 0, 0); + return size; + } + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ModuleFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ModuleFactory.java new file mode 100644 index 00000000..c542c1a2 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ModuleFactory.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.Font; +import java.awt.geom.Rectangle2D; +import java.util.Collection; + +import org.simantics.db.Resource; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.handler.impl.BoundsOutline; +import org.simantics.g2d.element.handler.impl.DefaultTransform; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.g2d.element.handler.impl.OutlinePick; +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.TextColorImpl; +import org.simantics.g2d.element.handler.impl.TextFontImpl; +import org.simantics.g2d.element.handler.impl.TextImpl; +import org.simantics.g2d.image.Image; +import org.simantics.g2d.image.impl.ShapeImage; +import org.simantics.g2d.utils.Alignment; + +public class ModuleFactory extends SysdynElementFactory { + + private static final BasicStroke STROKE = new BasicStroke(1f); + private static final Image DEFAULT_IMAGE = new ShapeImage(new Rectangle2D.Double(-5, -2.5, 10, 5), null, STROKE, true); + + @Override + protected ElementClass compileElementClass(Resource elementType, Collection terminals) { + return ElementClass.compile( + SimpleElementLayers.INSTANCE, + OutlinePick.INSTANCE, + TextImpl.INSTANCE, + TextColorImpl.BLACK, + new TextFontImpl(new Font("arial", Font.PLAIN, 25)), + DefaultTransform.INSTANCE, + new StaticObjectAdapter(elementType), + new StaticSymbolImpl(DEFAULT_IMAGE), + StaticSymbolImageInitializer.INSTANCE, + new HoverTextElementHandler(0, 0, Alignment.LEADING, 1f , 7, 7, false), + BoundsOutline.INSTANCE, + new WholeElementTerminals(terminals) + ).setId(ModuleFactory.class.getSimpleName()); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/StockFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/StockFactory.java new file mode 100644 index 00000000..44476a87 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/StockFactory.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.geom.Rectangle2D; +import java.util.Collection; + +import org.simantics.db.Resource; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.handler.impl.BoundsOutline; +import org.simantics.g2d.element.handler.impl.DefaultTransform; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.g2d.element.handler.impl.OutlinePick; +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.TextColorImpl; +import org.simantics.g2d.element.handler.impl.TextFontImpl; +import org.simantics.g2d.element.handler.impl.TextImpl; +import org.simantics.g2d.image.Image; +import org.simantics.g2d.image.impl.ShapeImage; +import org.simantics.g2d.utils.Alignment; + +public class StockFactory extends SysdynElementFactory { + + private static final BasicStroke STROKE = new BasicStroke(1f); + private static final Image DEFAULT_IMAGE = new ShapeImage(new Rectangle2D.Double(-5, -2.5, 10, 5), null, STROKE, true); + + @Override + protected ElementClass compileElementClass(Resource elementType, Collection terminals) { + return ElementClass.compile( + SimpleElementLayers.INSTANCE, + OutlinePick.INSTANCE, + TextImpl.INSTANCE, + TextColorImpl.BLACK, + TextFontImpl.DEFAULT, + DefaultTransform.INSTANCE, + new StaticObjectAdapter(elementType), + new StaticSymbolImpl(DEFAULT_IMAGE), + StaticSymbolImageInitializer.INSTANCE, + new HoverTextElementHandler(0, 0, Alignment.LEADING, 1f), + BoundsOutline.INSTANCE, + new WholeElementTerminals(terminals) + ).setId(StockFactory.class.getSimpleName()); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementFactory.java new file mode 100644 index 00000000..989380f0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementFactory.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import java.awt.Font; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.G2DUtils; +import org.simantics.diagram.adapter.SyncElementFactory; +import org.simantics.diagram.content.ResourceTerminal; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.diagram.stubs.G2DResource; +import org.simantics.diagram.synchronization.CompositeHintSynchronizer; +import org.simantics.diagram.synchronization.IHintSynchronizer; +import org.simantics.diagram.synchronization.SynchronizationHints; +import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; +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.ElementHints; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.modeling.ModelingResources; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.sysdyn.SysdynResource; + +/** + * An ElementFactory that gathers common functionality for system dynamics symbols. + * Just implement {@link #compileElementClass(Resource, Collection)} to add a symbol. + * + * @author Tuukka Lehtonen + */ +public abstract class SysdynElementFactory extends SyncElementFactory { + + public static final IHintSynchronizer SYNCHRONIZER = new CompositeHintSynchronizer( + ComponentNameSynchronizer.INSTANCE, + TransformSynchronizer.INSTANCE); + + @Override + public void load(ReadGraph graph, final ICanvasContext canvas, final IDiagram diagram, final Resource element, final IElement e) throws DatabaseException { + Builtins b = graph.getBuiltins(); + G2DResource g2d = G2DResource.getInstance(graph); + DiagramResource dr = DiagramResource.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + + Resource component = graph.getPossibleObject(element, mr.ElementToComponent); + String text = null; + if (component != null) { + text = (String) graph.getPossibleRelatedValue(component, b.HasName); + } + if (text == null) + text = "[empty]"; + + ElementUtils.setText(e, text); + + if (graph.isInstanceOf(element, dr.FontProvider)) { + Resource fontResource = graph.getPossibleObject(element, g2d.HasFont); + if (fontResource != null) + ElementUtils.setTextFont(e, G2DUtils.getFont(graph, fontResource)); + } + if (graph.isInstanceOf(element, dr.ColorProvider)) { + Resource colorResource = graph.getPossibleObject(element, g2d.HasColor); + if (colorResource != null) + ElementUtils.setTextColor(e, G2DUtils.getColor(graph, colorResource)); + } + + if (component != null && graph.hasStatement(component, SysdynResource.getInstance(graph).IsOutput)) { + Font font = ElementUtils.getTextFont(e); + font = font.deriveFont(Font.BOLD); + ElementUtils.setTextFont(e, font); + } + + AffineTransform at = DiagramGraphUtil.getAffineTransform(graph, element); + ElementUtils.setTransform(e, at); + + // This synchronizes only text and transformation (not font and color) + e.setHint(SynchronizationHints.HINT_SYNCHRONIZER, SYNCHRONIZER); + + e.setHint(ElementHints.KEY_HOVER, false); + } + + @Override + public ElementClass create(ReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType) + throws DatabaseException { + StructuralResource2 sr = StructuralResource2.getInstance(graph); + DiagramResource dr = DiagramResource.getInstance(graph); + + Resource definedByList = graph.getPossibleObject(elementType, sr.IsDefinedBy); + Collection definedBy = Collections.emptyList(); + if (definedByList != null) + definedBy = OrderedSetUtils.toList(graph, definedByList); + Collection terminals = new ArrayList(definedBy.size()); + for (Resource r : definedBy) { + if (graph.isInstanceOf(r, dr.Terminal)) { + terminals.add(new ResourceTerminal(r)); + } + } + + return compileElementClass(elementType, terminals); + } + + /** + * @param elementType the type of the loaded element + * @param terminals the terminals of the element type being loaded + * @return an {@link ElementClass} representing the loaded element type + */ + protected abstract ElementClass compileElementClass(Resource elementType, Collection terminals); + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementHints.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementHints.java new file mode 100644 index 00000000..ef69bf4d --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementHints.java @@ -0,0 +1,10 @@ +package org.simantics.sysdyn.ui.elements2; + +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; + +public class SysdynElementHints { + + public static final Key KEY_INPUT_REFERENCE = new KeyOf(String.class, "INPUT_REFERENCE"); + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementUtils.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementUtils.java new file mode 100644 index 00000000..dd82a3c9 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/SysdynElementUtils.java @@ -0,0 +1,20 @@ +package org.simantics.sysdyn.ui.elements2; + +import org.simantics.g2d.element.IElement; + +public class SysdynElementUtils { + + + public static void setInputReference(IElement e, String inputReference) + { + Input i = e.getElementClass().getSingleItem(Input.class); + i.setInputReference(e, inputReference); + } + + public static String getInputReference(IElement e) + { + Input i = e.getElementClass().getSingleItem(Input.class); + return i.getInputReference(e); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ValveFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ValveFactory.java new file mode 100644 index 00000000..6c9123a8 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/ValveFactory.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; + +import org.simantics.db.Resource; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.HandleMouseEvent; +import org.simantics.g2d.element.handler.InternalSize; +import org.simantics.g2d.element.handler.impl.BoundsOutline; +import org.simantics.g2d.element.handler.impl.DefaultTransform; +import org.simantics.g2d.element.handler.impl.HoverImpl; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.g2d.element.handler.impl.OutlinePick; +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.TextColorImpl; +import org.simantics.g2d.element.handler.impl.TextFontImpl; +import org.simantics.g2d.element.handler.impl.TextImpl; +import org.simantics.g2d.image.Image; +import org.simantics.g2d.image.impl.ShapeImage; +import org.simantics.g2d.utils.Alignment; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.nodes.ShapeNode; +import org.simantics.utils.datastructures.hints.IHintListener; +import org.simantics.utils.datastructures.hints.IHintObservable; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; + + +public class ValveFactory extends SysdynElementFactory { + + public static final Key KEY_ROTATED = new KeyOf(Boolean.class, "ROTATED"); + + public static final double VALVE_SIZE = 2.5; + + private static final BasicStroke STROKE = new BasicStroke(1f); + private static final Image VALVE_STATIC_IMAGE = new ShapeImage(createShape(VALVE_SIZE, false), null, STROKE, true); + + /* (non-Javadoc) + * @see org.simantics.sysdyn.ui.elements2.SysdynElementFactory#compileElementClass(org.simantics.db.Resource, java.util.Collection) + */ + @Override + protected ElementClass compileElementClass(Resource elementType, Collection terminals) { + return ElementClass.compile( + SimpleElementLayers.INSTANCE, + OutlinePick.INSTANCE, + TextImpl.INSTANCE, + TextColorImpl.BLACK, + TextFontImpl.DEFAULT, + DefaultTransform.INSTANCE, + new StaticObjectAdapter(elementType), + new StaticSymbolImpl(VALVE_STATIC_IMAGE), + StaticSymbolImageInitializer.INSTANCE, + HoverImpl.INSTANCE, + ValveSceneGraph.INSTANCE, + BoundsOutline.INSTANCE, + new WholeElementTerminals(terminals) + ).setId(ValveFactory.class.getSimpleName()); + } + + /** + * @param valveSize + * @param rotated true for vertical valve, false + * for horizontal + * @return + */ + private static Path2D createShape(double valveSize, boolean rotated) { + Path2D path = new Path2D.Double(); + path.moveTo(-valveSize, -valveSize); + if(rotated) { + path.lineTo(-valveSize, +valveSize); + path.lineTo(+valveSize, -valveSize); + } else { + path.lineTo(+valveSize, -valveSize); + path.lineTo(-valveSize, +valveSize); + } + path.lineTo(+valveSize, +valveSize); + path.closePath(); + return path; + } + + public static class ValveSceneGraph extends HoverTextElementNoBounds implements InternalSize, HandleMouseEvent { + + private static final long serialVersionUID = 5544256245734478634L; + + public static final ValveSceneGraph INSTANCE = new ValveSceneGraph(); + + private static final Key NODE = new SceneGraphNodeKey(ShapeNode.class, "VALVE_NODE"); + + private IHintListener hoverHintListener; + + public ValveSceneGraph() { + super(0, VALVE_SIZE + 3.0, Alignment.CENTER); + } + @Override + public void init(IElement e, G2DParentNode parent) { + super.init(e, parent); + AffineTransform at = ElementUtils.getTransform(e); + final HoverShapeNode node = ElementUtils.getOrCreateNode(e, parent, NODE, "valve", HoverShapeNode.class); + + // Calculate borders from text node bounds. + node.setStroke(STROKE); + node.setScaleStroke(true); + node.setColor(Color.BLACK); + node.setShape(createShape(VALVE_SIZE, Boolean.TRUE.equals(e.getHint(KEY_ROTATED)))); + node.setHover(ElementUtils.isHovering(e)); + + if(at != null) + node.setTransform(at); + + hoverHintListener = new IHintListener() { + + @Override + public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { + + } + + @Override + public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { + IElement e = (IElement)sender; + HoverShapeNode shape = (HoverShapeNode) e.getHint(NODE); + if(shape == null) { + return; + } + boolean hover = ElementUtils.isHovering(e); + shape.setHover(hover); + } + }; + e.addHintListener(hoverHintListener); + } + + @Override + public void cleanup(IElement e) { + e.removeHintListener(hoverHintListener); + ElementUtils.removePossibleNode(e, NODE); + } + + @Override + public Rectangle2D getBounds(IElement e, Rectangle2D size) { + if (size == null) + size = new Rectangle2D.Double(); + size.setFrame(createShape(VALVE_SIZE, Boolean.TRUE.equals(e.getHint(KEY_ROTATED))).getBounds2D()); + double paddingX = 2.0; + double paddingY = 2.0; + size.setRect(size.getX() - paddingX, size.getY() -paddingY, size.getWidth() + paddingX + paddingX, size.getHeight() + paddingY + paddingY); + return size; + } + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/WholeElementTerminals.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/WholeElementTerminals.java new file mode 100644 index 00000000..46296ae9 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/WholeElementTerminals.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.ui.elements2; + +import java.awt.Shape; +import java.util.Collection; + +import org.simantics.g2d.diagram.handler.Topology.Terminal; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.handler.impl.ObjectTerminal; +import org.simantics.g2d.element.handler.impl.Terminals; + +/** + * @author Tuukka Lehtonen + */ +public class WholeElementTerminals extends Terminals { + + private static final long serialVersionUID = -8209833430671135001L; + + public WholeElementTerminals(Collection ts) { + super(ts); + } + + @Override + public Shape getTerminalShape(IElement node, Terminal t) { + // For each terminal, return the shape of the element. + return ElementUtils.getElementShapeOrBounds(node); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Arcs.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Arcs.java new file mode 100644 index 00000000..70092ac6 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Arcs.java @@ -0,0 +1,211 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import java.awt.geom.Rectangle2D; + +public class Arcs { + + public static final double PI2 = Math.PI*2.0; + + /** + * Returns angle + 2PI * n such that the + * result is between -PI and PI. + */ + public static double normalizeAngle(double angle) { + return Math.IEEEremainder(angle, PI2); + } + + /** + * Returns true, if three normalized angles are clockwise oriented. + */ + public static boolean areClockwiseOrdered(double angle1, double angle2, double angle3) { + //System.out.println(angle1 + " " + angle2 + " " + angle3); + return angle1 < angle2 + ? (angle2 < angle3 || angle3 < angle1) + : (angle2 < angle3 && angle3 < angle1) + ; + } + + /** + * Returns an angle in radians between straight line from (x0,y0) to (x2,y2) + * and an arc from (x0,y0) to (x2,y2) thru (x1,y1). The angle + * is measured at (x0,y0) and is between -PI and PI. + */ + public static double angleOfArc( + double x0, double y0, + double x1, double y1, + double x2, double y2) { + double dx0 = x1-x0; + double dy0 = y1-y0; + double dx1 = x1-x2; + double dy1 = y1-y2; + double dx = x2-x0; + double dy = y2-y0; + // Length of cross product (p1-p0)x(p2-p0) + double dd = dx0*dy - dy0*dx; + + if(Math.abs(dd) < 1e-6) // Points are (almost) collinear + return 0.0; + else { + // (p1-p0)*(p1-p2) / dd + double offset = (dx0*dx1 + dy0*dy1) / dd; + double angle = Math.PI*0.5 - Math.atan(offset); + if(dd > 0.0) + angle = angle-Math.PI; + return angle; + + } + } + + private static double updateBestNextAngle(double curAngle, double bestAngle, double newAngle) { + if(newAngle < curAngle) + newAngle += PI2; + if(newAngle < bestAngle) + return newAngle; + return bestAngle; + } + + private static double updateBestPrevAngle(double curAngle, double bestAngle, double newAngle) { + if(newAngle > curAngle) + newAngle -= PI2; + if(newAngle > bestAngle) + return newAngle; + return bestAngle; + } + + public static double nextIntersectingAngle(double cx, double cy, double r, + double curAngle, Rectangle2D rect, boolean dir) { + if(!dir) { + double bestAngle = curAngle + PI2; + { + double dx = rect.getMinX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, -angle); + } + } + { + double dx = rect.getMaxX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, -angle); + } + } + { + double dy = cy - rect.getMinY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + { + double dy = cy - rect.getMaxY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestNextAngle(curAngle, bestAngle, angle); + bestAngle = updateBestNextAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + return normalizeAngle(bestAngle); + } + else { + double bestAngle = curAngle - PI2; + { + double dx = rect.getMinX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, -angle); + } + } + { + double dx = rect.getMaxX() - cx; + if(Math.abs(dx) < r) { + double angle = normalizeAngle(Math.acos(dx / r)); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, -angle); + } + } + { + double dy = cy - rect.getMinY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + { + double dy = cy - rect.getMaxY(); + if(Math.abs(dy) < r) { + double angle = Math.asin(dy / r); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle); + bestAngle = updateBestPrevAngle(curAngle, bestAngle, + normalizeAngle(Math.PI-angle)); + } + } + return normalizeAngle(bestAngle); + } + } + + public static boolean hitTest(Rectangle2D beginBounds, Rectangle2D endBounds, double angle, double x, double y, double tolerance) { + + boolean clockWise = angle > 0; + + double x0 = beginBounds.getCenterX(); + double y0 = beginBounds.getCenterY(); + double x1 = endBounds.getCenterX(); + double y1 = endBounds.getCenterY(); + + double offset = + Math.abs(angle) < 1.0e-6 + ? 1e3 * Math.signum(angle) + : Math.tan(Math.PI*0.5-angle)*0.5; + double cx = 0.5*(x0+x1) + offset * (y1-y0); + double cy = 0.5*(y0+y1) + offset * (x0-x1); + double dx0 = x0 - cx; + double dy0 = y0 - cy; + double dx1 = x1 - cx; + double dy1 = y1 - cy; + double r = Math.sqrt(dx0*dx0 + dy0*dy0); + double angle0 = Arcs.nextIntersectingAngle(cx, cy, r, + Math.atan2(-dy0, dx0), beginBounds, angle < 0.0); + double angle1 = Arcs.nextIntersectingAngle(cx, cy, r, + Math.atan2(-dy1, dx1), endBounds, angle > 0.0); + + double dx = x-cx; + double dy = y-cy; + double dist = dx*dx + dy*dy; + +// System.out.println("HitTest: x0=" + x0 + " y0=" + y0 + " y=" + y + " x=" + x + " dist=" + dist + " r2=" + r*r); + + if(dist < (r+tolerance)*(r+tolerance) && + dist > (r-tolerance)*(r-tolerance)) { + double ang = Arcs.normalizeAngle(Math.atan2(-dy, dx)); +// System.out.println("test " + angle0 + " " + ang + " " + angle1); + if(Arcs.areClockwiseOrdered(angle0, ang, angle1) == clockWise) { +// System.out.println("hit"); + return true; + } + } + + return false; + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/ConnectionClasses.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/ConnectionClasses.java new file mode 100644 index 00000000..4d090671 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/ConnectionClasses.java @@ -0,0 +1,20 @@ +package org.simantics.sysdyn.ui.elements2.connections; + +public class ConnectionClasses { + + public static final Object CONNECTION = new Object() { + public String toString() { return "CONNECTION"; } + }; + + public static final Object FLAG = new Object() { + public String toString() { return "FLAG"; } + }; + + public static final Object FLOW = new Object() { + public String toString() { return "FLOW"; } + }; + + public static final Object DEPENDENCY = new Object() { + public String toString() { return "DEPENDENCY"; } + }; +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Dependencies.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Dependencies.java new file mode 100644 index 00000000..2fba1306 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Dependencies.java @@ -0,0 +1,227 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import java.awt.Shape; +import java.awt.geom.Arc2D; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.utils.datastructures.Pair; + +public class Dependencies { + + /* + * Total length of the arrow is ARROW_LENGTH1 + ARROW_LENGTH2 + */ + public static double ARROW_LENGTH1 = 0.2; + public static double ARROW_LENGTH2 = 1.0; + public static double ARROW_WIDTH = 0.5; + +// +// // Auxiliary +// double angle0; +// double angle1; +// double cx; +// double cy; +// double r; +// +// // Scene graph +// ShapeNode arcNode; +// FilledShapeNode arrowNode; +// +// public Dependencies() { +// } +// +// public Dependencies(Connectable tail, Connectable head) { +// super(); +// this.tail = tail; +// this.head = head; +// } +// +// @Override +// public void elementUpdated(IElement element) { +// update(); +// } +// +// @Override +// public void remove() { +// arcNode.remove(); +// arrowNode.remove(); +// tail.removeListener(this); +// head.removeListener(this); +// super.remove(); +// } +// +// @Override +// public void init(G2DParentNode parent) { +// tail.addListener(this); +// head.addListener(this); +// +// arcNode = parent.addNode(ShapeNode.class); +// arcNode.setScaleStroke(true); +// arcNode.setStroke(new BasicStroke(1)); +// arrowNode = parent.addNode(FilledShapeNode.class); +// update(); +// } +// + + private static Shape createArrow(double x, double y, double dx, double dy) { + Path2D path = new Path2D.Double(); + path.moveTo(x+ARROW_LENGTH1*dx, y+ARROW_LENGTH1*dy); + x -= ARROW_LENGTH2*dx; + y -= ARROW_LENGTH2*dy; + path.lineTo(x-ARROW_WIDTH*dy, y+ARROW_WIDTH*dx); + path.lineTo(x+ARROW_WIDTH*dy, y-ARROW_WIDTH*dx); + path.closePath(); + return path; + } + + public static Point2D computeCenter(Rectangle2D tail, Rectangle2D head, double angle) { + + double x0 = tail.getCenterX(); + double y0 = tail.getCenterY(); + double x1 = head.getCenterX(); + double y1 = head.getCenterY(); + +// System.out.println("createArrowShape " + x0 + " " + y0 + " " + x1 + " " + y1); + + double offset = + Math.abs(angle) < 1.0e-6 + ? 1e3 * Math.signum(angle) + : Math.tan(Math.PI*0.5-angle)*0.5; + + double cx = 0.5*(x0+x1) + offset * (y1-y0); + double cy = 0.5*(y0+y1) + offset * (x0-x1); + + return new Point2D.Double(cx, cy); + + } + + public static Pair createArrowShape(Rectangle2D tail, Rectangle2D head, double angle) { + + double x0 = tail.getCenterX(); + double y0 = tail.getCenterY(); + double x1 = head.getCenterX(); + double y1 = head.getCenterY(); + +// System.out.println("createArrowShape " + x0 + " " + y0 + " " + x1 + " " + y1); + + double offset = + Math.abs(angle) < 1.0e-6 + ? 1e3 * Math.signum(angle) + : Math.tan(Math.PI*0.5-angle)*0.5; + + double cx = 0.5*(x0+x1) + offset * (y1-y0); + double cy = 0.5*(y0+y1) + offset * (x0-x1); + double dx0 = x0 - cx; + double dy0 = y0 - cy; + double dx1 = x1 - cx; + double dy1 = y1 - cy; + + double r = Math.sqrt(dx0*dx0 + dy0*dy0); + +// Rectangle2D bounds = new Rectangle2D.Double(); +// tail.getBounds(bounds); + double angle0 = Arcs.nextIntersectingAngle(cx, cy, r, + Math.atan2(-dy0, dx0), tail, angle < 0.0); +// head.getBounds(bounds); + double angle1 = Arcs.nextIntersectingAngle(cx, cy, r, + Math.atan2(-dy1, dx1), head, angle > 0.0); + double extent = angle1-angle0; + //double arcAngle = angle0; + if(angle < 0.0) { + double temp = angle0; + angle0 = angle1; + angle1 = temp; + extent = -extent; + } + if(extent < 0) + extent += Math.PI*2.0; + else if(extent >= 360.0) + extent -= Math.PI*2.0; + Shape shape1 = new Arc2D.Double(cx-r, cy-r, 2*r, 2*r, + Math.toDegrees(angle0), + Math.toDegrees(extent), + Arc2D.OPEN); +// + double xx = Math.cos(angle > 0.0 ? angle1 : angle0); + double yy = -Math.sin(angle > 0.0 ? angle1 : angle0); + + Shape arrowShape = createArrow(cx + r*xx, cy + r*yy, + angle < 0.0 ? -yy : yy, + angle > 0.0 ? -xx : xx); + + return Pair.make(shape1, arrowShape); + + } +// +// public void update() { +// if(arcNode != null) +// updateSceneGraph(); +// fireElementUpdated(); +// } +// +// @Override +// public void getBounds(Rectangle2D bounds) { +// bounds.setFrame(arcNode.getBounds()); +// } +// +// @Override +// public boolean hitTest(double x, double y, double tolerance) { +// double dx = x-cx; +// double dy = y-cy; +// double dist = dx*dx + dy*dy; +// if(dist < (r+tolerance)*(r+tolerance) && +// dist > (r-tolerance)*(r-tolerance)) { +// double angle = Arcs.normalizeAngle(Math.atan2(-dy, dx)); +// if(Arcs.areClockwiseOrdered(angle0, angle, angle1)) +// return true; +// } +// return false; +// } +// +// class EventHandler extends DragEventHandler { +// @Override +// protected boolean begin(IDiagramEditor editor, DragEvent event) { +// return event.startModifiers.equals("left"); +// } +// +// @Override +// protected void update(IDiagramEditor editor, DragEvent event) { +// if(event == null) +// return; +// angle = Arcs.angleOfArc( +// tail.getOrigo().getX(), tail.getOrigo().getY(), +// event.current.getX(), event.current.getY(), +// head.getOrigo().getX(), head.getOrigo().getY() +// ); +// Dependencies.this.update(); +// editor.requestRepaint(); +// } +// } +// +// @SuppressWarnings("unchecked") +// @Override +// public T getInterface(Class clazz) { +// if(clazz == IEventHandler.class) +// return (T)new EventHandler(); +// return super.getInterface(clazz); +// } +// +// @Override +// public void elementRemoved(IElement element) { +// remove(); +// } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyConnectionFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyConnectionFactory.java new file mode 100644 index 00000000..403aa412 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyConnectionFactory.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import java.util.HashMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.atomic.AtomicInteger; + +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.AsyncReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.procedure.AsyncMultiProcedure; +import org.simantics.db.procedure.AsyncProcedure; +import org.simantics.diagram.adapter.ElementFactoryAdapter; +import org.simantics.diagram.stubs.DiagramResource; +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.IElement; +import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; +import org.simantics.g2d.routing.RouterFactory; +import org.simantics.utils.datastructures.Pair; + +/** + * An element class for single connection entity elements. A connection entity + * consists of connection edge segments and branch points as its children. + * + * @author Tuukka Lehtonen + */ +public class DependencyConnectionFactory extends ElementFactoryAdapter { + + public static final ElementClass CLASS = SysdynConnectionClass.CLASS; + + @Override + public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, final AsyncProcedure procedure) { + DiagramResource dr = graph.getService(DiagramResource.class); + graph.forSingleType(elementType, dr.Connection, new AsyncProcedure() { + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + procedure.exception(graph, throwable); + } + @Override + public void execute(AsyncReadGraph graph, Resource connectionType) { + procedure.execute(graph, SysdynConnectionClass.CLASS.newClassWith(false, new StaticObjectAdapter(connectionType))); + } + }); + } + + @Override + public void load(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, final Resource elementResource, + final IElement element, final AsyncProcedure procedure) { + + final AtomicInteger ready = new AtomicInteger(1); + final ConcurrentSkipListMap> properties = new ConcurrentSkipListMap>(); + + element.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(false, false)); + + graph.forEachPredicate(elementResource, new AsyncMultiProcedure() { + + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + throwable.printStackTrace(); + } + + @Override + public void execute(AsyncReadGraph graph, final Resource property) { + + ready.incrementAndGet(); + + graph.forIsSubrelationOf(property, graph.getBuiltins().HasProperty, new AsyncProcedure() { + + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + throwable.printStackTrace(); + } + + @Override + public void execute(AsyncReadGraph graph, final Boolean isProperty) { + + if(isProperty) { + + graph.forPossibleRelatedValue(elementResource, property, new AsyncProcedure() { + + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + throwable.printStackTrace(); + } + + @Override + public void execute(AsyncReadGraph graph, final Object value) { + + graph.forPossibleRelatedValue(property, graph.getBuiltins().HasName, StringBindingDefault.INSTANCE, new AsyncProcedure() { + + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + throwable.printStackTrace(); + } + + @Override + public void execute(AsyncReadGraph graph, String name) { + + properties.put(name, Pair.make(property, value)); +// System.out.println("load properties " + name + " => " + value); + if(ready.decrementAndGet() == 0) { + element.setHint(DiagramHints.PROPERTIES, new HashMap>(properties)); + procedure.execute(graph, element); + } + + } + + }); + + } + + }); + + + } else { + + if(ready.decrementAndGet() == 0) { + element.setHint(DiagramHints.PROPERTIES, new HashMap>(properties)); + procedure.execute(graph, element); + } + + } + + } + + }); + + } + + @Override + public void finished(AsyncReadGraph graph) { + + if(ready.decrementAndGet() == 0) { + element.setHint(DiagramHints.PROPERTIES, new HashMap(properties)); + procedure.execute(graph, element); + } + + } + + }); + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyEdgeClass.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyEdgeClass.java new file mode 100644 index 00000000..140bd0df --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyEdgeClass.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Map; + +import org.simantics.db.Resource; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.DiagramMutator; +import org.simantics.g2d.diagram.DiagramUtils; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.Topology; +import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy; +import org.simantics.g2d.diagram.handler.Topology.Connection; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.EdgeVisuals; +import org.simantics.g2d.element.handler.Pick; +import org.simantics.g2d.element.handler.SceneGraph; +import org.simantics.g2d.element.handler.TerminalLayout; +import org.simantics.g2d.element.handler.Transform; +import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; +import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals; +import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline; +import org.simantics.g2d.element.handler.impl.FillColorImpl; +import org.simantics.g2d.element.handler.impl.ParentImpl; +import org.simantics.g2d.element.handler.impl.SimpleElementLayers; +import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler; +import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +public class DependencyEdgeClass { + + public static class NodePick implements Pick { + + private static final long serialVersionUID = 1L; + + @Override + public boolean pickTest(IElement e, Shape s, PickPolicy policy) { + Rectangle2D pickRect = null; + if (s instanceof Rectangle2D) + pickRect = (Rectangle2D) s; + else + // FIXME: suboptimal, but works. + pickRect = s.getBounds2D(); + + DependencyNode node = e.getHint(SysdynEdgeSceneGraph.KEY_SG_NODE); + if(node == null) { + System.out.println("pickTest no node!"); + return false; + } + + return Arcs.hitTest(node.beginBounds, node.endBounds, node.angle, pickRect.getCenterX(), pickRect.getCenterY(), 3.0); + + } + + } + + // TODO scale, rotate, move, transform + public static final ElementClass CLASS = + ElementClass.compile( + SysdynEdgeSceneGraph.INSTANCE, + EdgeHandler.INSTANCE, + ConfigurableEdgeVisuals.DEFAULT, + FillColorImpl.BLACK, + FixedTransform.INSTANCE, + new NodePick(), + ConnectionSelectionOutline.INSTANCE, + SimpleElementLayers.INSTANCE, + ParentImpl.INSTANCE + ).setId("EdgeClass.STRAIGHT"); + + public static class SysdynEdgeSceneGraph implements SceneGraph { + + private static final long serialVersionUID = 2914383071126238996L; + + public static final SysdynEdgeSceneGraph INSTANCE = new SysdynEdgeSceneGraph(); + + public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); + + public static final Key KEY_SG_NODE = new SceneGraphNodeKey(DependencyNode.class, "EDGE_NODE"); + + @Override + public void init(IElement e, G2DParentNode parent) { + ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), DependencyNode.class); + update(e); + } + + @Override + public void cleanup(IElement e) { + ElementUtils.removePossibleNode(e, KEY_SG_NODE); + } + + public void update(final IElement e) { + + DependencyNode node = e.getHint(KEY_SG_NODE); + if(node == null) return; + + final IDiagram diagram = ElementUtils.peekDiagram(e); + + node.setFieldListener(new PropertyChangeListener() { + + @Override + public void propertyChange(final PropertyChangeEvent event) { + + String field = event.getPropertyName(); + Map> properties = e.getHint(DiagramHints.PROPERTIES); + if(properties == null) return; + final Pair property = properties.get(field); + if(property == null) return; + + DiagramUtils.mutateDiagram(diagram, new Callback() { + + @Override + public void run(DiagramMutator mutator) { + mutator.modifyProperty(e, property.first, event.getNewValue()); + } + + }); + + } + + }); + + EdgeVisuals vh = e.getElementClass().getSingleItem(EdgeVisuals.class); + Stroke stroke = vh.getStroke(e); + Color c = ElementUtils.getFillColor(e, Color.BLACK); + + Shape beginTerminalShape = null; + Shape endTerminalShape = null; + if (diagram != null) { + Topology topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class); + if (topology != null) { + Connection beginConnection = topology.getConnection(e, EdgeEnd.Begin); + Connection endConnection = topology.getConnection(e, EdgeEnd.End); + beginTerminalShape = getCanvasTerminalShape(beginConnection); + endTerminalShape = getCanvasTerminalShape(endConnection); + } + } + + if(beginTerminalShape == null || endTerminalShape == null) return; + + node.setProperty("beginBounds", beginTerminalShape.getBounds2D()); + node.setProperty("endBounds", endTerminalShape.getBounds2D()); + node.setProperty("stroke", stroke); + node.setProperty("color", c); + node.setProperty("angle", 0.1); + + Map> properties = e.getHint(DiagramHints.PROPERTIES); + if(properties != null) { + for(Map.Entry> entry : properties.entrySet()) { + node.setProperty(entry.getKey(), entry.getValue().second); +// System.out.println("setProperty " + entry.getKey() + " => " + entry.getValue().second); + } + } + + Pair shapes = Dependencies.createArrowShape(beginTerminalShape.getBounds2D(), endTerminalShape.getBounds2D(), node.angle); + EdgeHandler eh = e.getElementClass().getAtMostOneItemOfClass(EdgeHandler.class); + Path2D path = new Path2D.Double(shapes.first); + eh.setPath(e, path); + + } + + private static Shape getCanvasTerminalShape(Connection connection) { + if (connection != null && connection.node != null && connection.terminal != null) { + TerminalLayout layout = connection.node.getElementClass().getAtMostOneItemOfClass(TerminalLayout.class); + if (layout != null) { + //return layout.getTerminalShape(connection.node, connection.terminal); + Shape shp = layout.getTerminalShape(connection.node, connection.terminal); + Transform tr = connection.node.getElementClass().getAtMostOneItemOfClass(Transform.class); + if (tr == null) + return shp; + + return tr.getTransform(connection.node).createTransformedShape(shp); + + } + } + return null; + } + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyEdgeFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyEdgeFactory.java new file mode 100644 index 00000000..7713bdff --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyEdgeFactory.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import org.simantics.db.AsyncReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.procedure.AsyncProcedure; +import org.simantics.diagram.adapter.ElementFactoryAdapter; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.element.ElementClass; + +/** + * An element class factory for sysdyn dependency connection edge segments. + * + * @author Tuukka Lehtonen + */ +public class DependencyEdgeFactory extends ElementFactoryAdapter { + + private static final ElementClass CLASS = DependencyEdgeClass.CLASS; + + @Override + public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, + AsyncProcedure procedure) { + procedure.execute(graph, CLASS); + } + + @Override + public void getClass(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource, + AsyncProcedure procedure) { + throw new UnsupportedOperationException(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyNode.java new file mode 100644 index 00000000..a2a24a90 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/DependencyNode.java @@ -0,0 +1,97 @@ +package org.simantics.sysdyn.ui.elements2.connections; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.Rectangle2D; + +import org.simantics.scenegraph.ISelectionPainterNode; +import org.simantics.scenegraph.g2d.events.SGMouseEvent; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.sysdyn.ui.elements2.GraphPropertyNode; +import org.simantics.utils.datastructures.Pair; + +public class DependencyNode extends GraphPropertyNode implements ISelectionPainterNode { + + private static final long serialVersionUID = 1294351381209071074L; + + public Color color; + public Stroke stroke; + public Rectangle2D beginBounds; + public Rectangle2D endBounds; + public double angle = 0.1; + + transient public boolean hover = false; + + @Override + public void render(Graphics2D g) { + + // NICENESS + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + +// System.out.println("dep " + angle + " " + beginBounds + " " + endBounds); + + Pair shapes = Dependencies.createArrowShape(beginBounds, endBounds, angle); + + boolean selected = NodeUtil.isSelected(this, 2); + if(selected) { + g.setColor(Color.PINK); + g.setStroke(new BasicStroke(1.0f)); + g.draw(shapes.first); + g.fill(shapes.second); + if(color != null) g.setColor(color); + g.setStroke(stroke); + g.draw(shapes.first); + g.fill(shapes.second); + } else if (hover){ + g.setColor(Color.LIGHT_GRAY); + g.setStroke(new BasicStroke(1.0f)); + g.draw(shapes.first); + g.fill(shapes.second); + if(color != null) g.setColor(color); + g.setStroke(stroke); + g.draw(shapes.first); + g.fill(shapes.second); + } else { + if(color != null) g.setColor(color); + if(stroke != null) g.setStroke(stroke); + g.draw(shapes.first); + g.fill(shapes.second); + } + + } + + @Override + public boolean hitTest(double x, double y, double tolerance) { + return Arcs.hitTest(beginBounds, endBounds, angle, x, y, tolerance); + } + + @Override + public void mouseDragged(SGMouseEvent event, boolean pressHit, boolean currentHit) { + + if(!pressHit) return; + + angle = Arcs.angleOfArc( + beginBounds.getCenterX(), beginBounds.getCenterY(), + event.getDoubleX(), event.getDoubleY(), + endBounds.getCenterX(), endBounds.getCenterY()); + + } + + @Override + public void mouseReleased(SGMouseEvent event, boolean hit) { + if(hit) commitProperty("angle", angle); + } + + @Override + public void mouseMoved(SGMouseEvent event, boolean hit) { + if(hit != hover) { + hover = hit; + repaint(); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowConnectionFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowConnectionFactory.java new file mode 100644 index 00000000..57cc1fca --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowConnectionFactory.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import org.simantics.db.AsyncReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.procedure.AsyncProcedure; +import org.simantics.diagram.adapter.ElementFactoryAdapter; +import org.simantics.diagram.stubs.DiagramResource; +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.IElement; +import org.simantics.g2d.element.handler.impl.StaticObjectAdapter; +import org.simantics.g2d.elementclass.connection.ConnectionClass; +import org.simantics.g2d.routing.RouterFactory; + +/** + * An element class for single connection entity elements. A connection entity + * consists of connection edge segments and branch points as its children. + * + * @author Tuukka Lehtonen + */ +public class FlowConnectionFactory extends ElementFactoryAdapter { + + public static final ElementClass CLASS = SysdynConnectionClass.CLASS; + + @Override + public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, final AsyncProcedure procedure) { + DiagramResource dr = graph.getService(DiagramResource.class); + graph.forSingleType(elementType, dr.Connection, new AsyncProcedure() { + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + procedure.exception(graph, throwable); + } + @Override + public void execute(AsyncReadGraph graph, Resource connectionType) { + procedure.execute(graph, ConnectionClass.CLASS.newClassWith(false, new StaticObjectAdapter(connectionType))); + } + }); + } + + @Override + public void load(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource, + final IElement element, final AsyncProcedure procedure) { + element.setHint(DiagramHints.ROUTE_ALGORITHM, RouterFactory.create(true, true)); + procedure.execute(graph, element); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowEdgeClass.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowEdgeClass.java new file mode 100644 index 00000000..66874597 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowEdgeClass.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Shape; +import java.awt.Stroke; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Map; + +import org.simantics.db.Resource; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.DiagramMutator; +import org.simantics.g2d.diagram.DiagramUtils; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.Topology; +import org.simantics.g2d.diagram.handler.Topology.Connection; +import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.SceneGraphNodeKey; +import org.simantics.g2d.element.handler.SceneGraph; +import org.simantics.g2d.element.handler.TerminalLayout; +import org.simantics.g2d.element.handler.Transform; +import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; +import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals; +import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline; +import org.simantics.g2d.element.handler.impl.FillColorImpl; +import org.simantics.g2d.element.handler.impl.ParentImpl; +import org.simantics.g2d.element.handler.impl.ShapePick; +import org.simantics.g2d.element.handler.impl.SimpleElementLayers; +import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler; +import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.sysdyn.ui.elements2.ValveFactory.ValveSceneGraph; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.datastructures.hints.IHintContext.Key; + +/** + * @author Toni Kalajainen + */ +public class FlowEdgeClass { + + // TODO scale, rotate, move, transform + public static final ElementClass CLASS = + ElementClass.compile( + SysdynEdgeSceneGraph.INSTANCE, + EdgeHandler.INSTANCE, + ConfigurableEdgeVisuals.DEFAULT, + FillColorImpl.BLACK, + FixedTransform.INSTANCE, + ShapePick.INSTANCE, + ConnectionSelectionOutline.INSTANCE, + SimpleElementLayers.INSTANCE, + ParentImpl.INSTANCE + ).setId("EdgeClass.STRAIGHT"); + + public static class SysdynEdgeSceneGraph implements SceneGraph { + + private static final long serialVersionUID = 2914383071126238996L; + + public static final SysdynEdgeSceneGraph INSTANCE = new SysdynEdgeSceneGraph(); + + public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); + + public static final Key KEY_SG_NODE = new SceneGraphNodeKey(FlowNode.class, "EDGE_NODE"); + + @Override + public void init(IElement e, G2DParentNode parent) { + ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), FlowNode.class); + update(e); + } + + @Override + public void cleanup(IElement e) { + ElementUtils.removePossibleNode(e, KEY_SG_NODE); + } + + public void update(final IElement e) { + + FlowNode node = e.getHint(KEY_SG_NODE); + if(node == null) return; + + final IDiagram diagram = ElementUtils.peekDiagram(e); + + node.setFieldListener(new PropertyChangeListener() { + + @Override + public void propertyChange(final PropertyChangeEvent event) { + + DiagramUtils.mutateDiagram(diagram, new Callback() { + + @Override + public void run(DiagramMutator mutator) { + + String field = event.getPropertyName(); + Map> properties = e.getHint(DiagramHints.PROPERTIES); + Pair property = properties.get(field); + + mutator.modifyProperty(e, property.first, event.getNewValue()); + + } + + }); + + } + + }); + + Stroke stroke = new BasicStroke(0.1f); + Color c = ElementUtils.getFillColor(e, Color.BLACK); + + Shape beginTerminalShape = null; + Shape endTerminalShape = null; + boolean toValve = false; + if (diagram != null) { + Topology topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class); + if (topology != null) { + Connection beginConnection = topology.getConnection(e, EdgeEnd.Begin); + Connection endConnection = topology.getConnection(e, EdgeEnd.End); + beginTerminalShape = getCanvasTerminalShape(beginConnection); + endTerminalShape = getCanvasTerminalShape(endConnection); + toValve = endConnection.node.getElementClass().containsClass(ValveSceneGraph.class); +// System.out.println("end connection class = " + endConnection.node.getElementClass()); + } + } + + if(beginTerminalShape == null || endTerminalShape == null) return; + + node.setProperty("beginBounds", beginTerminalShape.getBounds2D()); + node.setProperty("endBounds", endTerminalShape.getBounds2D()); + node.setProperty("stroke", stroke); + node.setProperty("color", c); + node.setProperty("toValve", toValve); +// System.out.println("set toValve = " + toValve); + node.toValve = toValve; + + Map> properties = e.getHint(DiagramHints.PROPERTIES); + if(properties != null) { + for(Map.Entry> entry : properties.entrySet()) { + node.setProperty(entry.getKey(), entry.getValue().second); + } + } + + } + + private static Shape getCanvasTerminalShape(Connection connection) { + if (connection != null && connection.node != null && connection.terminal != null) { + TerminalLayout layout = connection.node.getElementClass().getAtMostOneItemOfClass(TerminalLayout.class); + if (layout != null) { + //return layout.getTerminalShape(connection.node, connection.terminal); + Shape shp = layout.getTerminalShape(connection.node, connection.terminal); + Transform tr = connection.node.getElementClass().getAtMostOneItemOfClass(Transform.class); + if (tr == null) + return shp; + + return tr.getTransform(connection.node).createTransformedShape(shp); + + } + } + return null; + } + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowEdgeFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowEdgeFactory.java new file mode 100644 index 00000000..e2926c70 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowEdgeFactory.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import org.simantics.db.AsyncReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.procedure.AsyncProcedure; +import org.simantics.diagram.adapter.ElementFactoryAdapter; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.element.ElementClass; + +/** + * An element class factory for sysdyn flow connection edge segments. + * + * @author Tuukka Lehtonen + */ +public class FlowEdgeFactory extends ElementFactoryAdapter { + + private static final ElementClass CLASS = FlowEdgeClass.CLASS; + + @Override + public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, + AsyncProcedure procedure) { + procedure.execute(graph, CLASS); + } + + @Override + public void getClass(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementResource, + AsyncProcedure procedure) { + throw new UnsupportedOperationException(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowNode.java new file mode 100644 index 00000000..4b307b43 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowNode.java @@ -0,0 +1,76 @@ +package org.simantics.sysdyn.ui.elements2.connections; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.Rectangle2D; + +import org.simantics.scenegraph.ISelectionPainterNode; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.sysdyn.ui.elements2.GraphPropertyNode; +import org.simantics.utils.datastructures.Pair; + +public class FlowNode extends GraphPropertyNode implements ISelectionPainterNode { + + private static final long serialVersionUID = 328942356917631237L; + + public Color color; + public Stroke stroke; + public Rectangle2D beginBounds; + public Rectangle2D endBounds; + public Boolean toValve; + + @Override + public void render(Graphics2D g) { + + // NICENESS + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + /* + * There are two cases, first is from Stock|Cloud to Valve and second is from Valve to Stock|Cloud + * -In the first case there is no arrow and valve is endBounds + * -In the second case there is an arrow and valve is beginBounds + */ + + Pair lines = null; + Shape arrow = null; + +// System.out.println("FlowNode.render toValve = " + toValve); + + if(toValve) { + + lines = Flows.createLines(false, endBounds, beginBounds); + + } else { + + lines = Flows.createLines(true, beginBounds, endBounds); + arrow = Flows.createArrow(beginBounds, endBounds); + + } + + boolean selected = NodeUtil.isSelected(this, 2); + if(selected) { + g.setColor(Color.PINK); + g.setStroke(new BasicStroke(1.0f)); + g.draw(lines.first); + g.draw(lines.second); + if(color != null) g.setColor(color); + g.setStroke(stroke); + g.draw(lines.first); + g.draw(lines.second); + if(arrow != null) g.fill(arrow); + } else { + if(color != null) g.setColor(color); + if(stroke != null) g.setStroke(stroke); + g.draw(lines.first); + g.draw(lines.second); + if(arrow != null) g.fill(arrow); + } + + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowStroke.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowStroke.java new file mode 100644 index 00000000..137d9c54 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/FlowStroke.java @@ -0,0 +1,18 @@ +package org.simantics.sysdyn.ui.elements2.connections; + +import java.awt.Shape; +import java.awt.Stroke; + +public class FlowStroke implements Stroke { + private Stroke stroke1, stroke2; + + public FlowStroke( Stroke stroke1, Stroke stroke2 ) { + this.stroke1 = stroke1; + this.stroke2 = stroke2; + } + + public Shape createStrokedShape( Shape shape ) { + return stroke2.createStrokedShape( stroke1.createStrokedShape( shape ) ); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Flows.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Flows.java new file mode 100644 index 00000000..fc00fa7f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/connections/Flows.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * 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.sysdyn.ui.elements2.connections; + +import java.awt.Shape; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.utils.datastructures.Pair; + +public class Flows { + + public static double ARROW_LENGTH = 3.2; + public static double ARROW_WIDTH = 2; + + static final double OFFSET = 1.0; + static final double ARROW_OFFSET = 3.2; + + public static Path2D createArrow(Rectangle2D tail, Rectangle2D head) { + + double x = tail.getCenterX(); + double y = tail.getCenterY(); + +// Rectangle2D rect = new Rectangle2D.Double(); +// head.getBounds(rect); + double cx = head.getCenterX(); + double minx = head.getMinX(); + double maxx = head.getMaxX(); + double miny = head.getMinY(); + double maxy = head.getMaxY(); + + Path2D path = new Path2D.Double(); + + // approach from top + if (y < miny) { + path.moveTo(cx, miny); + path.lineTo(cx + ARROW_WIDTH, miny - ARROW_LENGTH); + path.lineTo(cx - ARROW_WIDTH, miny - ARROW_LENGTH); + } + + // approach from beneath + else if (y > maxy) { + path.moveTo(cx, maxy); + path.lineTo(cx + ARROW_WIDTH, maxy + ARROW_LENGTH); + path.lineTo(cx - ARROW_WIDTH, maxy + ARROW_LENGTH); + } + + // approach from left + else if (x < minx) { + path.moveTo(minx, y); + path.lineTo(minx - ARROW_LENGTH, y - ARROW_WIDTH); + path.lineTo(minx - ARROW_LENGTH, y + ARROW_WIDTH); + } + + // approach from right + else if (x > maxx) { + path.moveTo(maxx, y); + path.lineTo(maxx + ARROW_LENGTH, y - ARROW_WIDTH); + path.lineTo(maxx + ARROW_LENGTH, y + ARROW_WIDTH); + } + else + return null; // FIXME (HN) This is just a quick bugfix, didn't understand the logic completely + + path.closePath(); + + return path; + + } + + private static Pair createLines(boolean vertical, double ... coordinates) { + +// lineNode1.setShape(createOffsetLine(vertical, OFFSET, coordinates)); +// lineNode2.setShape(createOffsetLine(vertical, -OFFSET, coordinates)); + return new Pair(createOffsetLine(vertical, OFFSET, coordinates), Flows.createOffsetLine(vertical, -OFFSET, coordinates)); + + } + + public static Pair createLines(boolean hasArrow, Rectangle2D valve, Rectangle2D node) { + + double x0 = valve.getCenterX(); + double y0 = valve.getCenterY(); + double x1 = node.getCenterX(); + double y1 = node.getCenterY(); + +// System.out.println("FlowNode " + x0 + " " + y0 + " x1 " + x1 + " y1 " + y1); + +// Rectangle2D rect = new Rectangle2D.Double(); +// node.getBounds(rect); + + double minY = hasArrow ? node.getMinY() - ARROW_OFFSET : node.getMinY(); + double maxY = hasArrow ? node.getMaxY() + ARROW_OFFSET : node.getMaxY(); + double minX = hasArrow ? node.getMinX() - ARROW_OFFSET : node.getMinX(); + double maxX = hasArrow ? node.getMaxX() + ARROW_OFFSET : node.getMaxX(); + +// boolean rotated = ((ValveElement)valve).rotated; + boolean rotated = false; + + if( rotated ) { + if(y1 > y0) + y0 += OFFSET; + else + y0 -= OFFSET; + if(node.getMinX() <= x0 && node.getMaxX() >= x0) { + if(y1 > y0) + return createLines(true, y0, x0, minY); + else + return createLines(true, y0, x0, maxY); + } + else { + if(x1 > x0) + return createLines(true, y0, x0, y1, minX); + else + return createLines(true, y0, x0, y1, maxX); + } + } + else { + if(x1 > x0) + x0 += OFFSET; + else + x0 -= OFFSET; + if(node.getMinY() <= y0 && node.getMaxY() >= y0) { + if(x1 > x0) + return createLines(false, x0, y0, minX); + else + return createLines(false, x0, y0, maxX); + } + else { + if(y1 > y0) + return createLines(false, x0, y0, x1, minY); + else + return createLines(false, x0, y0, x1, maxY); + } + } + + + } + + public static Path2D createLine(boolean vertical, double ... coordinates) { + Path2D path = new Path2D.Double(); + if(vertical) + path.moveTo(coordinates[1], coordinates[0]); + else + path.moveTo(coordinates[0], coordinates[1]); + for(int i=2;i> perThreadElementList = new ThreadLocal>() { + @Override + protected java.util.List initialValue() { + return new ArrayList(); + } + }; + + static class ConnectionHandlerImpl implements ConnectionHandler { + + public static final ConnectionHandlerImpl INSTANCE = new ConnectionHandlerImpl(); + + private static final long serialVersionUID = 3267139233182458330L; + + @Override + public Collection getBranchPoints(IElement connection, Collection result) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + return Collections.emptySet(); + return entity.getBranchPoints(result); + } + + @Override + public Collection getChildren(IElement connection, Collection result) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + return Collections.emptySet(); + result = entity.getSegments(result); + return entity.getBranchPoints(result); + } + + @Override + public Collection getSegments(IElement connection, Collection result) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + return Collections.emptySet(); + return entity.getSegments(result); + } + + @Override + public Collection getTerminalConnections(IElement connection, Collection result) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + return Collections.emptySet(); + return entity.getTerminalConnections(result); + } + + @Override + public IElement newBranchPoint(IElement connection) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + throw new IllegalArgumentException("element '" + connection + "' is not a connection element"); + return entity.newBranchPoint(); + } + + @Override + public IElement newEdge(IElement connection) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + throw new IllegalArgumentException("element '" + connection + "' is not a connection element"); + return entity.newEdge(); + } + + @Override + public void removeBranchPoint(IElement connection, IElement branchPoint) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + throw new IllegalArgumentException("element '" + connection + "' is not a connection element"); + entity.removeBranchPoint(branchPoint); + } + + @Override + public void removeEdge(IElement connection, IElement edge) { + ConnectionEntity entity = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (entity == null) + throw new IllegalArgumentException("element '" + connection + "' is not a connection element"); + entity.removeEdge(edge); + } + } + + static final class ConnectionSceneGraph implements SceneGraph { + + public static final ConnectionSceneGraph INSTANCE = new ConnectionSceneGraph(); + + private static final long serialVersionUID = 4232871859964883266L; + + @Override + public void init(IElement connection, G2DParentNode parent) { + ConnectionEntity ce = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (ce == null) + return; + + // Painting is single-threaded, it is OK to use a single thread-local collection here. + List children = perThreadElementList.get(); + children.clear(); + ce.getSegments(children); + ce.getBranchPoints(children); + //new Exception("painting connection entity " + ce.hashCode() + " with " + children.size() + " segments and branch points").printStackTrace(); + if (children.isEmpty()) + return; + + Set tmp = new HashSet(); + + Map> properties = connection.getHint(DiagramHints.PROPERTIES); + + int zIndex = 0; + for (IElement child : children) { + + ElementClass ec = child.getElementClass(); + + Transform transform = child.getElementClass().getSingleItem(Transform.class); + assert (transform != null); + AffineTransform at2 = transform.getTransform(child); + if (at2 == null) + continue; + + if(properties != null) + child.setHint(DiagramHints.PROPERTIES, properties); + + SingleElementNode holder = child.getHint(ElementHints.KEY_SG_NODE); + if (holder == null) { + holder = parent.addNode(ElementUtils.generateNodeId(child), SingleElementNode.class); + child.setHint(ElementHints.KEY_SG_NODE, holder); + } + holder.setZIndex(++zIndex); + + Composite composite = child.getHint(ElementHints.KEY_COMPOSITE); + + holder.setTransform(at2); + holder.setComposite(composite); + holder.setVisible(true); + + // New node handler + for (SceneGraph n : ec.getItemsByClass(SceneGraph.class)) { + n.init(child, holder); + } + tmp.add(holder); + } + + // Hide unaccessed nodes (but don't remove) + for (IG2DNode node : parent.getNodes()) { + if (node instanceof SingleElementNode) { + if (!tmp.contains(node)) { + ((SingleElementNode)node).setVisible(false); + } + } else { + //System.out.println("WHAT IS THIS: "); + //NodeDebug.printSceneGraph(((Node) node)); + } + } + + // Don't leave dangling references behind. + children.clear(); + } + + @Override + public void cleanup(IElement e) { + } + } + + static final class ConnectionBounds implements InternalSize, Outline { + + public static final ConnectionBounds INSTANCE = new ConnectionBounds(); + + private static final long serialVersionUID = 4232871859964883266L; + + @Override + public Rectangle2D getBounds(IElement e, Rectangle2D size) { + + if (size == null) + size = new Rectangle2D.Double(); + size.setFrame(0, 0, 0, 0); + + ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (ce == null) + return size; + + Collection parts = ce.getSegments(null); + if (parts.isEmpty()) + return size; + parts = ce.getBranchPoints(parts); + + Rectangle2D temp = null; + for (IElement part : parts) { + // Using on-diagram coordinates because neither connections nor + // edges have a non-identity transform which means that + // coordinates are always absolute. Therefore branch point + // bounds also need to be calculated in absolute coordinates. + ElementUtils.getElementBoundsOnDiagram(part, size); +// System.out.println("InternalSize BOUNDS: " + size + " for part " + part + " " + part.getElementClass()); + if (temp == null) { + temp = new Rectangle2D.Double(); + temp.setRect(size); + } else + Rectangle2D.union(temp, size, temp); + //System.out.println("InternalSize Combined BOUNDS: " + temp); + } + size.setRect(temp); + return size; + + } + + private Shape getSelectionShape(IElement forPart) { + for (SelectionOutline so : forPart.getElementClass().getItemsByClass(SelectionOutline.class)) { + Shape shape = so.getSelectionShape(forPart); + if (shape != null) + return shape; + } + // Using on-diagram coordinates because neither connections nor + // edges have a non-identity transform which means that + // coordinates are always absolute. Therefore branch point + // shape also needs to be calculated in absolute coordinates. + Shape shape = ElementUtils.getElementShapeOrBoundsOnDiagram(forPart); + return shape; + //return shape.getBounds2D(); + } + + @Override + public Shape getElementShape(IElement e) { + ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (ce == null) + return new Rectangle2D.Double(); + + Collection parts = ce.getSegments(null); + if (parts.isEmpty()) + return new Rectangle2D.Double(); + parts = ce.getBranchPoints(parts); + + if (parts.size() == 1) { + Shape shape = getSelectionShape(parts.iterator().next()); + //System.out.println("Outline SHAPE: " + shape); + //System.out.println("Outline BOUNDS: " + shape.getBounds2D()); + return shape; + } + + //System.out.println("Outline: " + e); + Area area = new Area(); + for (IElement part : parts) { + //System.out.println(part); + + Shape shape = getSelectionShape(part); + + Rectangle2D bounds = shape.getBounds2D(); +// System.out.println(" shape: " + shape); +// System.out.println(" bounds: " + bounds); + + if (bounds.isEmpty()) { + double w = bounds.getWidth(); + double h = bounds.getHeight(); + if (w <= 0.0 && h <= 0.0) + continue; + + // Need to expand shape in either width or height to make it visible. + final double exp = 0.1; + if (w <= 0.0) + shape = GeometryUtils.expandRectangle(bounds, 0, 0, exp, exp); + else if (h <= 0.0) + shape = GeometryUtils.expandRectangle(bounds, exp, exp, 0, 0); + } + + //System.out.println(" final shape: " + shape); + //shape = bounds; + + Area a = null; + if (shape instanceof Area) + a = (Area) shape; + else + a = new Area(shape); + area.add(a); + } + + //System.out.println(" connection area outline: " + area); + //System.out.println(" connection area outline bounds: " + area.getBounds2D()); + return area; + } + } + + public static class ConnectionPick implements Pick2 { + + public final static ConnectionPick INSTANCE = new ConnectionPick(); + + private static final long serialVersionUID = 1L; + + @Override + public boolean pickTest(IElement e, Shape s, PickPolicy policy) { + ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (ce == null) + return false; + + // Primarily pick branch points and then edges. + Collection parts = ce.getBranchPoints(null); + parts = ce.getSegments(parts); + if (parts.isEmpty()) + return false; + + for (IElement part : parts) { + for (Pick pick : part.getElementClass().getItemsByClass(Pick.class)) { +// System.out.println("TESTING: " + part + " : " + s + " : " + policy); + if (pick.pickTest(part, s, policy)) { + //System.out.println(" HIT!"); + return true; + } + } + } + + return false; + } + + @Override + public int pick(IElement e, Shape s, PickPolicy policy, Collection result) { + int oldResultSize = result.size(); + +// new Exception("SysdynConnectionClass.pick: " + e + " : " + s + " : " + policy).printStackTrace(); + + ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (ce == null) + return 0; + + // Primarily pick branch points and then edges. + List parts = perThreadElementList.get(); + parts.clear(); + + ce.getSegments(parts); + int edges = parts.size(); + ce.getBranchPoints(parts); + int branchPoints = parts.size() - edges; + + boolean singleEdge = branchPoints == 0 && edges == 1; + + if (parts.isEmpty()) + return 0; + + // See whether the whole connection is to be picked.. + boolean pickConnection = false; + wholeConnectionPick: + for (Outline outline : e.getElementClass().getItemsByClass(Outline.class)) { + Shape elementShape = outline.getElementShape(e); + if (elementShape == null) + continue; + + switch (policy) { + case PICK_CONTAINED_OBJECTS: + if (GeometryUtils.contains(s, elementShape)) { + pickConnection = true; + break wholeConnectionPick; + } + break; + case PICK_INTERSECTING_OBJECTS: + if (GeometryUtils.intersects(s, elementShape)) { + pickConnection = true; + break wholeConnectionPick; + } + break; + } + } + + ArrayList picks = null; + + // Pick connection segments + for (int i = 0; i < edges; ++i) { + IElement part = parts.get(i); + for (Pick pick : part.getElementClass().getItemsByClass(Pick.class)) { +// System.out.println("TESTING SEGMENT: " + part + " : " + s + " : " + policy); + if (pick.pickTest(part, s, policy)) { +// System.out.println(" HIT!"); + if (picks == null) + picks = new ArrayList(4); + picks.add(e); + break; + } + } + } + + // Pick the whole connection ? + if (pickConnection) { + if (picks == null) + picks = new ArrayList(4); + picks.add(e); + } + + // Pick branch/route points + for (int i = edges; i < parts.size(); ++i) { + IElement part = parts.get(i); + for (Pick pick : part.getElementClass().getItemsByClass(Pick.class)) { + //System.out.println("TESTING BRANCHPOINT: " + part + " : " + s + " : " + policy); + if (pick.pickTest(part, s, policy)) { + //System.out.println(" HIT!"); + if (picks == null) + picks = new ArrayList(4); + picks.add(part); + break; + } + } + } + + if (picks != null) { + // Add the discovered pickable children to the result after the + // parent to make the parent the primary pickable. + // Skip the children if there is only one child. + if (!singleEdge) { + result.addAll(picks); + } else { + result.add(e); + } + } + +// System.out.println("pick result size = " + result.size()); + + return result.size() - oldResultSize; + } + } + + private static final Key CHILD_LISTENERS = new KeyOf(ListenerList.class, "CHILD_LISTENERS"); + + public static class ConnectionChildren implements Children, ConnectionListener { + + public final static ConnectionChildren INSTANCE = new ConnectionChildren(); + + private static final long serialVersionUID = 1L; + + @Override + public Collection getChildren(IElement element, Collection result) { + ConnectionEntity ce = element.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (ce == null) { + if (result == null) + result = new ArrayList(0); + return result; + } + result = ce.getSegments(result); + result = ce.getBranchPoints(result); + return result; + } + + @Override + public void addChildListener(IElement element, ChildListener listener) { + ListenerList ll = null; + synchronized (element) { + ll = element.getHint(CHILD_LISTENERS); + if (ll == null) { + ll = new ListenerList(ChildListener.class); + element.setHint(CHILD_LISTENERS, ll); + ConnectionEntity entity = element.getHint(ElementHints.KEY_CONNECTION_ENTITY); + entity.setListener(this); + } + } + ll.add(listener); + } + + @Override + public void removeChildListener(IElement element, ChildListener listener) { + synchronized (element) { + ListenerList ll = element.getHint(CHILD_LISTENERS); + if (ll == null) + return; + ll.remove(listener); + if (ll.isEmpty()) { + ConnectionEntity entity = element.getHint(ElementHints.KEY_CONNECTION_ENTITY); + entity.setListener(null); + } + } + } + + @Override + public void connectionChanged(ConnectionEvent event) { + fireChildrenChanged(event); + } + + private void fireChildrenChanged(ConnectionEvent event) { + ListenerList ll = event.connection.getHint(CHILD_LISTENERS); + if (ll == null) + return; + ChildEvent ce = new ChildEvent(event.connection, event.removedParts, event.addedParts); + for (ChildListener cl : ll.getListeners()) { + cl.elementChildrenChanged(ce); + } + } + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/EquationView.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/EquationView.java new file mode 100644 index 00000000..ae407a96 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/EquationView.java @@ -0,0 +1,482 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation; + + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartReference; +import org.eclipse.ui.part.ViewPart; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.procedure.Listener; +import org.simantics.db.request.Read; +import org.simantics.modeling.ModelingResources; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.expressionParser.ExpressionParser; +import org.simantics.sysdyn.expressionParser.ParseException; +import org.simantics.sysdyn.expressionParser.Token; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.representation.Configuration; +import org.simantics.sysdyn.representation.IElement; +import org.simantics.sysdyn.representation.IndependentVariable; +import org.simantics.sysdyn.ui.equation.expressions.ExpressionField; +import org.simantics.sysdyn.ui.equation.expressions.StockExpressionViewFactor; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; +import org.eclipse.jface.text.Position; + +public class EquationView extends ViewPart implements ISelectionListener { + + static final Font FONT = new Font(null, "Courier New", 12, SWT.NORMAL); + + //Resources + Resource variable; + Resource configuration; + + boolean disposed = false; + org.eclipse.ui.IPartListener2 focusLostListener; + + NameComposite nameComposite; + ShortcutTabs shortcutTabs; + ExpressionTypeSelector expressionController; + Composite unitComposite; + UnitSelector unitSelector; + ExpressionComposite expressionComposite; + + @Override + public void createPartControl(Composite parent) { + // Listeners + getSite().getPage().addPostSelectionListener(this); + focusLostListener = new org.eclipse.ui.IPartListener2() + { + public void partInputChanged(IWorkbenchPartReference partRef) {} + public void partVisible(IWorkbenchPartReference partRef) {} + public void partHidden(IWorkbenchPartReference partRef) {} + public void partOpened(IWorkbenchPartReference partRef) {} + public void partDeactivated(IWorkbenchPartReference partRef) + { + if(partRef.getPart(false) instanceof EquationView) { + // Save expressions + if(expressionComposite != null) { + expressionComposite.save(); + } + + + // Save unit + if(unitSelector != null) { + unitSelector.save(); + } + + if(nameComposite != null) { + nameComposite.save(variable); + } + } + + } + public void partClosed(IWorkbenchPartReference partRef) {} + public void partBroughtToTop(IWorkbenchPartReference partRef) {} + public void partActivated(IWorkbenchPartReference partRef) {} + }; + getViewSite().getPage().addPartListener(focusLostListener); + + GridLayoutFactory.fillDefaults().numColumns(4).margins(3, 3).applyTo(parent); + + + + // Upper part of the view: Name (and renaming) + nameComposite = new NameComposite(parent, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(nameComposite); + + + // Upper part of the view: Expression type + expressionController = new ExpressionTypeSelector(parent, SWT.NONE); + GridDataFactory.fillDefaults().applyTo(expressionController); + addVariableTypeSelectionListener(); + + // Upper part of the view: Unit input/selection + unitComposite = new Composite(parent, SWT.NONE); + GridDataFactory.fillDefaults().applyTo(unitComposite); + GridLayoutFactory.fillDefaults().applyTo(unitComposite); + unitSelector = new UnitSelector(unitComposite, SWT.NONE); + + // Center of the view: variables and possible functions + shortcutTabs = new ShortcutTabs(parent, SWT.NONE); + GridDataFactory.fillDefaults().span(1, 4).applyTo(shortcutTabs); + addVariableTableListeners(); + + // Below variable name: Equation + expressionComposite = new ExpressionComposite(parent, SWT.NONE); + GridDataFactory.fillDefaults().span(3, 1).grab(true, true).applyTo(expressionComposite); + + } + + static class Auxiliary { + String name; + Resource configuration; + boolean isVariable; + } + + class UpdateViewRequest implements Read { + + Resource resource; + + public UpdateViewRequest(Resource resource) { + this.resource = resource; + } + + @Override + public Auxiliary perform(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + ModelingResources mr = ModelingResources.getInstance(graph); + + Resource map = graph.getPossibleObject(resource, mr.ElementToComponent); + if(map != null) resource = map; + + Auxiliary a = new Auxiliary(); + variable = resource; + a.configuration = graph.getPossibleObject(variable, b.PartOf); + a.name = graph.getPossibleRelatedValue(resource, b.HasName); + a.isVariable = graph.isInstanceOf(variable, sr.IndependentVariable); + if(a.name == null) + a.name = ""; + return a; + } + } + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if(selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = + (IStructuredSelection)selection; + if(structuredSelection.size() == 1) { +// Object element = structuredSelection.getFirstElement(); + Resource res = ISelectionUtils.filterSingleSelection(structuredSelection, Resource.class); + if(res != null) + SimanticsUI.getSession().asyncRequest( + new UpdateViewRequest(res), + new Listener() { + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + @Override + public void execute(final Auxiliary result) { + if(isDisposed()) + return; + expressionComposite.getDisplay().asyncExec(new Runnable() { + + @Override + public void run(){ + if(isDisposed()) + return; + if(result.isVariable) { + unitSelector.setEnabled(true); + expressionController.setEnabled(true); + expressionComposite.setEnabled(true); + nameComposite.setEnabled(true); + if(configuration == null || !configuration.equals(result.configuration)) { + configuration = result.configuration; + if(unitSelector!= null) { + unitSelector.dispose(); + unitSelector = new UnitSelector(unitComposite, SWT.NONE); + } + } else { + unitSelector.updateUnits(variable); + } + + if(shortcutTabs != null) shortcutTabs.updateTables(variable); + String expressionType = expressionComposite.resetExpressionView(variable); + addExpressionFieldListeners(); + validateExpressionFields(); + expressionController.setExpressionTypes(expressionComposite.getExpressionTypes()); + expressionController.select(expressionType); + nameComposite.setName(result.name); + } else { + unitSelector.setEnabled(false); + expressionController.setEnabled(false); + expressionComposite.setEnabled(false); + nameComposite.setEnabled(false); + + unitSelector.clear(); // empty units + shortcutTabs.updateTables(variable); + expressionController.setExpressionTypes(null); + nameComposite.setName(""); + expressionComposite.resetExpressionView(variable); + } + } + }); + + } + + @Override + public boolean isDisposed() { + return disposed; + } + + } + ); + } + } + } + + @Override + public void setFocus() { + if(expressionComposite.getExpressionViewFactor() != null) + expressionComposite.focus(); + else + nameComposite.setFocus(); + } + + @Override + public void dispose() { + disposed = true; + getViewSite().getPage().removePartListener(focusLostListener); + super.dispose(); + } + + + private void addVariableTypeSelectionListener() { + expressionController.getTypeCombo().addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + expressionComposite.displayExpressionView(expressionController.getSelecetedType()); + addExpressionFieldListeners(); + validateExpressionFields(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + } + + private void addVariableTableListeners() { + Table[] tables = this.shortcutTabs.getTables(); + for(final Table table : tables) { + table.addMouseListener(new MouseListener(){ + + @Override + public void mouseDoubleClick(MouseEvent e) { + TableItem item = table.getItem(new Point(e.x, e.y)); + if(item != null) { + final String var = (String)item.getData(); + table.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if(expressionComposite!= null && !expressionComposite.isDisposed()) { + expressionComposite.replaceSelection(var); + validateExpressionFields(); + } + } + }); + } + } + + @Override + public void mouseDown(MouseEvent e) { + expressionComposite.focus(); + } + + @Override + public void mouseUp(MouseEvent e) { + expressionComposite.focus(); + } + + }); + + table.addFocusListener(new FocusListener() { + + @Override + public void focusGained(FocusEvent e) { + } + + @Override + public void focusLost(FocusEvent e) { + table.deselectAll(); + } + + }); + } + } + + private void addExpressionFieldListeners() { + if(expressionComposite.getExpressionViewFactor() != null) + for(final ExpressionField ef : expressionComposite.getExpressionViewFactor().getExpressionFields()) { + StyledText st = ef.getSourceViewer().getTextWidget(); + st.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + validateExpressionFields(); + } + }); + st.addKeyListener(new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if(e.keyCode == SWT.ESC && ef.getExpression() != null) { + ((StyledText)e.widget).setText(ef.getExpression()); + ((StyledText)e.widget).setSelection(ef.getExpression().length()); + } + } + }); + } + } + + private void validateExpressionFields() { + ExpressionParser parser = new ExpressionParser(new StringReader("")); + Set variables = new HashSet(); + HashMap>> references = new HashMap>>(); + + + // Build references and variable array + if(expressionComposite.getExpressionViewFactor() != null) + for(ExpressionField ef : expressionComposite.getExpressionViewFactor().getExpressionFields()) { + ef.resetAnnotations(); + String textString = ef.getExpression(); + parser.ReInit(new StringReader(textString)); + try { + parser.expr(); + HashMap> cr = parser.getReferences(); + references.put(ef, cr); + for(String t : cr.keySet()) + variables.add(t); + } catch (ParseException e1) { + ef.setSyntaxError(e1.currentToken); + } + } + + // Remove variables from variable array that don't exist in the model. Create annotations + if(!variables.isEmpty()) { + ArrayList modelVariables = new ArrayList(); + Set noSuchVariables = new HashSet(); + SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession()); + SysdynModel model = sdm.getModel(configuration); + Configuration conf = model.getConfiguration(); + ArrayList elements = conf.getElements(); + for(IElement e : elements) { + if(e instanceof IndependentVariable) { + IndependentVariable v = (IndependentVariable) e; + modelVariables.add(v.getName()); + } + } + + + for(String v : variables) { + if(!modelVariables.contains(v)) { + noSuchVariables.add(v); + } + } + + if(!noSuchVariables.isEmpty()) { + // remove no such variables from variable list + for(String s : noSuchVariables) + variables.remove(s); + // create annotations + HashMap> positions = getPositionsForVariables(references, noSuchVariables); + for(ExpressionField ef : positions.keySet()) { + ef.setNoSuchVariableAnnotations(positions.get(ef)); + } + } + } + + // Check that the variables that exist have connections and the connected variables have references in the expressions + if(!(expressionComposite.getExpressionViewFactor() instanceof StockExpressionViewFactor)) { + for(TableItem ti : this.shortcutTabs.getVariableTable().getItems()) { + if(!variables.contains(ti.getText())) { + ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0)); + } else { + ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0)); + variables.remove(ti.getText()); + } + } + + if(!variables.isEmpty()) { + HashMap> positions = getPositionsForVariables(references, variables); + for(ExpressionField ef : positions.keySet()) { + ef.setMissingLinkAnnotations(positions.get(ef)); + } + + } + } + + } + + @SuppressWarnings("unchecked") + private HashMap> getPositionsForVariables(HashMap>> references, Set variables) { + HashMap> result = new HashMap>(); + for(String s : variables) { + List tlist = new ArrayList(); + for(ExpressionField ef : references.keySet()) { + ArrayList positions = new ArrayList(); + tlist = references.get(ef).get(s); + if(tlist != null) + for(Token t : tlist) { + StyledText st = ef.getSourceViewer().getTextWidget(); + int start = st.getOffsetAtLine(t.beginLine - 1) + t.beginColumn - 1; + int offset = st.getOffsetAtLine(t.endLine - 1) + t.endColumn - start; + positions.add(new Position( + start, + offset)); + } + if(result.keySet().contains(ef)) { + result.get(ef).addAll((ArrayList)positions.clone()); + } else { + result.put(ef, (ArrayList)positions.clone()); + } + } + } + return result; + } +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ExpressionComposite.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ExpressionComposite.java new file mode 100644 index 00000000..33ccb1e8 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ExpressionComposite.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.equation.expressions.AuxiliaryExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.ConstantExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.DelayExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.EmptyExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.IExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.LookupExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.ParameterExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.StockExpressionViewFactor; +import org.simantics.sysdyn.ui.equation.expressions.WithLookupExpressionViewFactor; +import org.simantics.ui.SimanticsUI; + +public class ExpressionComposite extends Composite { + + static enum ExpressionType {Auxiliary, Parameter, Constant, Lookup, WithLookup, Stock, Delay, Empty}; + + ExpressionType[] auxiliaryExpressions = new ExpressionType[] { + ExpressionType.Parameter, + ExpressionType.Auxiliary, + ExpressionType.Constant, + ExpressionType.Lookup, + ExpressionType.WithLookup}; + + ExpressionType[] valveExpressions = new ExpressionType[] { + ExpressionType.Auxiliary, + ExpressionType.Parameter, + ExpressionType.Constant, + ExpressionType.WithLookup}; + + ExpressionType[] stockExpressions = new ExpressionType[] { + ExpressionType.Stock}; + + + IExpressionViewFactor expressionViewFactor; + Map data; + Map origData; + Resource variable; + ArrayList dependencies; + + public ExpressionComposite(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + + this.data = new HashMap(); + this.origData = new HashMap(); + } + + public void save() { + if(variable != null && data != null) + this.expressionViewFactor.writeData(variable, data); + } + + public void displayExpressionView(String expressionType) { + displayExpressionView(expressionType, false); + } + + public String resetExpressionView(Resource variable) { + this.data.clear(); + this.origData.clear(); + this.variable = variable; + this.expressionViewFactor = null; + String origExpressionType = getOriginalExpressionType().toString(); + displayExpressionView(origExpressionType, true); + return origExpressionType; + } + + + public void displayExpressionView(String expressionType, boolean original) { + if(expressionType == null) + return; + + if(this.expressionViewFactor != null) expressionViewFactor.updateData(data); + ExpressionType et = ExpressionType.valueOf(expressionType); + IExpressionViewFactor evf = null; + switch (et) { + case Auxiliary: + evf = new AuxiliaryExpressionViewFactor(); break; + case Parameter: + evf = new ParameterExpressionViewFactor(); break; + case Constant: + evf = new ConstantExpressionViewFactor(); break; + case Lookup: + evf = new LookupExpressionViewFactor(); break; + case WithLookup: + evf = new WithLookupExpressionViewFactor(variable); break; + case Stock: + evf = new StockExpressionViewFactor(); break; + case Delay: + evf = new DelayExpressionViewFactor(); break; + default: + evf = new EmptyExpressionViewFactor(); + } + + if (evf != null) { + for(Control c : this.getChildren()) { + c.dispose(); + } + + if(original) { + evf.readData(variable, data); + for(String key : data.keySet()) { + origData.put(key, data.get(key)); + } + } + + evf.createView(this, data); + this.expressionViewFactor = evf; + this.layout(); + } + } + + + public ExpressionType[] getExpressionTypes() { + ExpressionType[] expressionTypes = null; + + if(variable != null) { + try { + expressionTypes = SimanticsUI.getSession().syncRequest(new Read< ExpressionType[]>() { + + @Override + public ExpressionType[] perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + ExpressionType[] expressionTypes; + if(graph.isInstanceOf(variable, sr.Auxiliary)) { + expressionTypes = auxiliaryExpressions; + } + else if(graph.isInstanceOf(variable, sr.Valve)) { + expressionTypes = valveExpressions; + } + else if(graph.isInstanceOf(variable, sr.Stock)) { + expressionTypes = stockExpressions; + } + else + expressionTypes = null; + + return expressionTypes; + } + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + } + + return expressionTypes; + } + + public void focus() { + if(this.expressionViewFactor != null) + this.expressionViewFactor.focus(); + } + + public void replaceSelection(String var) { + this.expressionViewFactor.replaceSelection(var); + } + + public IExpressionViewFactor getExpressionViewFactor() { + return this.expressionViewFactor; + } + + private ExpressionType getOriginalExpressionType() { + + ExpressionType et = null; + + try { + et = SimanticsUI.getSession().syncRequest(new Read< ExpressionType>() { + + @Override + public ExpressionType perform(ReadGraph graph) throws DatabaseException { + + ExpressionType et = null; + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if(expression == null) { + if(graph.isInstanceOf(variable, sr.Auxiliary)) { + et = ExpressionType.Auxiliary; + } + else if(graph.isInstanceOf(variable, sr.Valve)) { + et = ExpressionType.Auxiliary; + } + else if(graph.isInstanceOf(variable, sr.Stock)) { + et = ExpressionType.Stock; + } else + et = ExpressionType.Empty; + } else { + + if(graph.isInstanceOf(expression, sr.NormalExpression)) { + et = ExpressionType.Auxiliary; + } else if (graph.isInstanceOf(expression, sr.StockExpression)) { + et = ExpressionType.Stock; + } else if (graph.isInstanceOf(expression, sr.ParameterExpression)) { + et = ExpressionType.Parameter; + } else if (graph.isInstanceOf(expression, sr.ConstantExpression)) { + et = ExpressionType.Constant; + } else if (graph.isInstanceOf(expression, sr.DelayExpression)) { + et = ExpressionType.Delay; + } else if (graph.isInstanceOf(expression, sr.LookupExpression)) { + et = ExpressionType.Lookup; + } else if (graph.isInstanceOf(expression, sr.WithLookupExpression)) { + et = ExpressionType.WithLookup; + } else { + et = ExpressionType.Empty; + } + } + return et; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return et; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ExpressionTypeSelector.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ExpressionTypeSelector.java new file mode 100644 index 00000000..383fff32 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ExpressionTypeSelector.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; + +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +public class ExpressionTypeSelector extends Composite { + + Combo typeCombo; + + public ExpressionTypeSelector(final Composite parent, int style) { + super(parent, style); + GridLayoutFactory.fillDefaults().numColumns(2).spacing(3, 3).applyTo(this); + + + Label label = new Label(this, SWT.SINGLE ); + label.setFont(EquationView.FONT); + label.setText("Type:"); + GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); + + typeCombo = new Combo(this, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); + typeCombo.setFont(EquationView.FONT); + + int columns = 6; + GC gc = new GC (typeCombo); + FontMetrics fm = gc.getFontMetrics (); + int width = columns * fm.getAverageCharWidth (); + int height = fm.getHeight (); + gc.dispose (); + GridDataFactory.fillDefaults().hint(typeCombo.computeSize(width, height)).applyTo(typeCombo); + + } + + public Combo getTypeCombo() { + return this.typeCombo; + } + + public String getSelecetedType() { + return this.typeCombo.getItem(this.typeCombo.getSelectionIndex()); + } + + public void setExpressionTypes(ExpressionComposite.ExpressionType[] expressionTypes) { + typeCombo.removeAll(); + if(expressionTypes != null) { + for(ExpressionComposite.ExpressionType et : expressionTypes) { + typeCombo.add(et.toString()); + } + } + } + + public void select(String expressionType) { + int index = typeCombo.indexOf(expressionType); + if (index > -1) { + typeCombo.select(index); + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/NameComposite.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/NameComposite.java new file mode 100644 index 00000000..bc959253 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/NameComposite.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation; + +import java.util.ArrayList; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.representation.Configuration; +import org.simantics.sysdyn.representation.IElement; +import org.simantics.sysdyn.representation.IndependentVariable; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.workbench.ResourceEditorInput; + +public class NameComposite extends Composite { + + Text nameText; + String originalName = ""; + + + public NameComposite(Composite parent, int style) { + super(parent, style); + GridLayoutFactory.fillDefaults().spacing(3, 3).applyTo(this); + + nameText = new Text(this, SWT.SINGLE | SWT.BORDER); + nameText.setFont(EquationView.FONT); + GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText); + + nameText.addVerifyListener(new VerifyListener() { + + @Override + public void verifyText(VerifyEvent e) { + e.doit = false; + char c = e.character; + if(c != ' ') { + e.doit = true; + } + } + }); + + nameText.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + Text t = (Text) e.widget; + String txt = t.getText(); + // Don't allow this to produce an eternal loop + if (!txt.equals(originalName) && txt.contains(" ")) { + t.setText(originalName); + } + } + }); + + nameText.addKeyListener(new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + + } + + @Override + public void keyPressed(KeyEvent e) { + if(e.keyCode == SWT.ESC && originalName != null) { + ((Text)e.widget).setText(originalName); + ((Text)e.widget).setSelection(originalName.length()); + } + } + }); + } + + public void setName(String name) { + if (name == null) + throw new NullPointerException("null name"); + this.originalName = name; + this.nameText.setText(name); + } + + public void save(final Resource variable) { + final String nameNew = this.nameText.getText(); + if(nameNew != null && !nameNew.equals(this.originalName) && variable != null) { + + final IEditorPart editor = + PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + IEditorInput input = editor.getEditorInput(); + ResourceEditorInput rei = (ResourceEditorInput) input; + SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession()); + SysdynModel model = sdm.getModel(rei.getResource()); + Configuration conf = model.getConfiguration(); + IElement thisElement = model.getElement(variable); + ArrayList elements = conf.getElements(); + for(IElement e : elements) { + if(e instanceof IndependentVariable) { + IndependentVariable v = (IndependentVariable)e; + if(v != thisElement && v.getName().equals(this.nameText.getText())) { + this.nameText.setText(this.originalName); + this.nameText.setSelection(this.originalName.length()); + return; + } + } + } + + + + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + Builtins b = g.getBuiltins(); + g.claimValue(variable, b.HasName, nameNew); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ShortcutTabs.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ShortcutTabs.java new file mode 100644 index 00000000..8cba344f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/ShortcutTabs.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation; + +import java.util.Collection; +import java.util.HashSet; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ExceptionUtils; + +public class ShortcutTabs extends Composite { + + TabFolder tabFolder; + TabItem variables; + TabItem functions; + Table variableTable; + Table functionTable; + + public ShortcutTabs(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + + tabFolder = new TabFolder (this, SWT.NONE); + GridDataFactory.fillDefaults().grab(false, true).applyTo(tabFolder); + GridLayoutFactory.fillDefaults().applyTo(tabFolder); + variables = new TabItem(tabFolder, SWT.NULL); + variables.setText("Variables"); + variableTable = new Table (tabFolder, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); + + variables.setControl(variableTable); + + functions = new TabItem(tabFolder, SWT.NULL); + functions.setText("Functions"); + functionTable = new Table (tabFolder, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); + TableItem item = new TableItem(functionTable, SWT.NONE); + item.setText("min()"); + item.setData("min({ })"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("max()"); + item.setData("max({ })"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("abs()"); + item.setData("abs({ })"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("if then else"); + item.setData("if then else"); + functions.setControl(functionTable); + + this.layout(); + } + + public HashSet updateTables(Resource variable) { + HashSet dependencies = getDependencies(variable); + variableTable.removeAll(); + TableItem item; + for(String d : dependencies) { + item = new TableItem(variableTable, SWT.NONE); + item.setText(d); + item.setData(d); + } + return dependencies; + } + + // Returns the names of the related variables (dependencies) + private HashSet getDependencies(final Resource r){ + HashSet variables = null; + if(r != null) + try { + variables = SimanticsUI.getSession().syncRequest(new Read>() { + + @Override + public HashSet perform(ReadGraph graph) + throws DatabaseException { + HashSet variables = new HashSet(); + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + + Collection dependencies = graph.getObjects(r, sr.IsHeadOf); + + for(Resource d : dependencies) { + if(graph.isInstanceOf(d, sr.Dependency)) { + Resource tail = graph.getPossibleObject(d, sr.HasTail); + if(tail != null) { + Object name = graph.getPossibleRelatedValue(tail, b.HasName); + if(name != null) + variables.add((String)name); + } + } + } + + return variables; + + } + + + }); + } catch (DatabaseException ee) { + ExceptionUtils.logAndShowError(ee); + } + + return variables; + } + + public Table getVariableTable() { + return this.variableTable; + } + + public Table[] getTables() { + Table[] ret = {this.variableTable, this.functionTable}; + return ret; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/UnitSelector.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/UnitSelector.java new file mode 100644 index 00000000..b78edbd3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/UnitSelector.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ExceptionUtils; + +public class UnitSelector extends Composite { + + Combo unitCombo; + Resource variable; + String unit = null; + ArrayList units; + + public UnitSelector(Composite parent, int style) { + super(parent, style); + GridLayoutFactory.fillDefaults().numColumns(2).spacing(3, 3).applyTo(this); + + this.units = getUnits(); + + Label label = new Label(this, SWT.SINGLE ); + label.setFont(EquationView.FONT); + label.setText("Unit:"); + //label.setAlignment(SWT.RIGHT); + GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); + + + unitCombo = new Combo(this, SWT.DROP_DOWN | SWT.BORDER); + unitCombo.setFont(EquationView.FONT); + + int columns = 6; + GC gc = new GC (unitCombo); + FontMetrics fm = gc.getFontMetrics (); + int width = columns * fm.getAverageCharWidth (); + int height = fm.getHeight (); + gc.dispose (); + GridDataFactory.fillDefaults().hint(unitCombo.computeSize(width, height)).applyTo(unitCombo); + + parent.layout(); + + } + + public String save(){ + final String unitNew = unitCombo.getText(); + + if(unitNew != null && !unitNew.equals("") && !units.contains(unitNew)) { + units.add(unitNew); + Collections.sort(units); + } + + if(unitNew != null && !unitNew.equals(unit) && variable != null) { + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + if (!unitNew.equals("")) { + g.claimValue(variable, sr.HasUnit, unitNew); + } + else if (g.getPossibleRelatedValue(variable, sr.HasUnit) != null) + g.deny(variable, sr.HasUnit); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return unitNew; + } + return null; + } + + public void updateUnits(Resource variable) { + if(unitCombo != null) { + this.variable = variable; + if(unitCombo.getItemCount() > 0) unitCombo.removeAll(); + for(String unit : this.units) { + unitCombo.add(unit); + } + + setUnit(); + } + } + + public void clear() { + this.unitCombo.removeAll(); + } + + private void setUnit() { + + if(variable != null) { + try { + SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + unit = graph.getPossibleRelatedValue(variable, sr.HasUnit); + return null; + } + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + } + + if (unit != null) + if(unitCombo.indexOf(unit) >= 0) + unitCombo.select(unitCombo.indexOf(unit)); + else + unitCombo.setText(unit); + } + + + // Returns all the used units in the model + private ArrayList getUnits() { + ArrayList units = new ArrayList(); + if(variable != null) { + try { + units = SimanticsUI.getSession().syncRequest(new Read>() { + + @Override + public ArrayList perform(ReadGraph graph) + throws DatabaseException { + ArrayList units = new ArrayList(); + + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + Resource model = graph.getPossibleObject(variable, b.PartOf); + if (model != null) { + Collection variables = graph.getObjects(model, b.ConsistsOf); + for(Resource v : variables) { + Object unit = graph.getPossibleRelatedValue(v, sr.HasUnit); + if (unit != null && !units.contains((String) unit)) { + units.add((String)unit); + } + } + } + + return units; + + } + + + }); + } catch (DatabaseException ee) { + ExceptionUtils.logAndShowError(ee); + } + } + return units; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/AuxiliaryExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/AuxiliaryExpressionViewFactor.java new file mode 100644 index 00000000..9a74a19c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/AuxiliaryExpressionViewFactor.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class AuxiliaryExpressionViewFactor implements IExpressionViewFactor { + + private Label equationLabel; + private ExpressionField expression; + + @Override + public void createView(Composite parent, Map data) { + + final String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + + GridLayoutFactory.fillDefaults().numColumns(2).spacing(3, 3).applyTo(parent); + equationLabel = new Label(parent, SWT.NONE); + equationLabel.setFont(FONT); + equationLabel.setText("="); + GridDataFactory.fillDefaults().applyTo(equationLabel); + + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setFont(FONT); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + } + + @Override + public void readData(final Resource variable, Map data) { + String equation = null; + if (variable != null && data.get("equation") == null) { + try { + equation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.NormalExpression)) { + return graph.getRelatedValue(expression, sr.HasEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", equation); + } + } + + @Override + public void writeData(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + if(currentText != null) { + data.put("equation", currentText); + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.NormalExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasEquation, currentText); + } + + }); + } + } + + @Override + public void focus() { + if(this.expression != null) this.expression.focus(); + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ColorManager.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ColorManager.java new file mode 100644 index 00000000..5bbb3391 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ColorManager.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.HashMap; + +import org.eclipse.jface.text.source.ISharedTextColors; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +public class ColorManager implements ISharedTextColors { + + protected HashMap colorTable = new HashMap(); + + @Override + public void dispose() { + for(Color c : colorTable.values()) + c.dispose(); + colorTable.clear(); + } + + @Override + public Color getColor(RGB rgb) { + Color color = colorTable.get(rgb); + if (color == null) { + color = new Color(Display.getCurrent(), rgb); + colorTable.put(rgb, color); + } + return color; + + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ConstantExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ConstantExpressionViewFactor.java new file mode 100644 index 00000000..1994fd0c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ConstantExpressionViewFactor.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ConstantExpressionViewFactor implements IExpressionViewFactor { + + private Label equationLabel; + private ExpressionField expression; + + @Override + public void createView(Composite parent, Map data) { + + final String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + + GridLayoutFactory.fillDefaults().numColumns(2).spacing(3, 3).applyTo(parent); + equationLabel = new Label(parent, SWT.NONE); + equationLabel.setFont(FONT); + equationLabel.setText("="); + GridDataFactory.fillDefaults().applyTo(equationLabel); + + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setFont(FONT); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + } + + @Override + public void focus() { + if(this.expression != null) this.expression.focus(); + } + + @Override + public void readData(final Resource variable, Map data) { + String equation = null; + if (variable != null && data.get("equation") == null) { + try { + equation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.ConstantExpression)) { + return graph.getRelatedValue(expression, sr.HasEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", equation); + } + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void writeData(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + if(currentText != null) { + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.ConstantExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasEquation, currentText); + } + + }); + } + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/DelayExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/DelayExpressionViewFactor.java new file mode 100644 index 00000000..debac678 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/DelayExpressionViewFactor.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class DelayExpressionViewFactor implements IExpressionViewFactor { + + @Override + public void createView(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public void readData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void writeData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/EmptyExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/EmptyExpressionViewFactor.java new file mode 100644 index 00000000..0b0c170c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/EmptyExpressionViewFactor.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class EmptyExpressionViewFactor implements IExpressionViewFactor { + + @Override + public void createView(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void readData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void writeData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ExpressionField.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ExpressionField.java new file mode 100644 index 00000000..f2101548 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ExpressionField.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.List; + +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.PaintManager; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.AnnotationPainter; +import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; +import org.eclipse.jface.text.source.IAnnotationAccess; +import org.eclipse.jface.text.source.MatchingCharacterPainter; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; +import org.eclipse.swt.graphics.Point; +import org.simantics.sysdyn.expressionParser.Token; + +public class ExpressionField extends Composite { + + protected SourceViewer _sourceViewer; + protected IDocument _document; + protected AnnotationModel _annotationModel; + + ColorManager cManager = new ColorManager(); + + IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess(); + + public ExpressionField(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + + int styles = SWT.V_SCROLL + | SWT.MULTI + | SWT.FULL_SELECTION + | SWT.WRAP; + + _document = new Document(); + _document.set(""); + + _annotationModel = new AnnotationModel(); + _annotationModel.connect(_document); + + _sourceViewer = new SourceViewer(this, + + null, + null, + true, + styles); + _sourceViewer.configure(new ExpressionFieldConfiguration(cManager)); + + AnnotationPainter painter = new AnnotationPainter(_sourceViewer, annotationAccess); + _sourceViewer.addPainter(painter); + + painter.addAnnotationType("MissingLink"); + painter.setAnnotationTypeColor("MissingLink", new Color(this.getDisplay(), 255,0,0)); + painter.addAnnotationType("NoSuchVariable"); + painter.setAnnotationTypeColor("NoSuchVariable", new Color(this.getDisplay(), 255,0,0)); + + _sourceViewer.setDocument(_document, _annotationModel); + + _sourceViewer.getControl().setLayoutData(new GridData(SWT.FILL, + SWT.FILL, + true, + true)); + + PaintManager paintManager = new PaintManager(_sourceViewer); + MatchingCharacterPainter matchingCharacterPainter = new MatchingCharacterPainter(_sourceViewer, + new DefaultCharacterPairMatcher( new char[] {'(', ')', '{', '}', '[', ']'} )); + matchingCharacterPainter.setColor(new Color(Display.getCurrent(), new RGB(160, 160, 160))); + paintManager.addPainter(matchingCharacterPainter); + + + } + + public SourceViewer getSourceViewer() { + return this._sourceViewer; + } + + public void setMissingLinkAnnotations(List positions){ + for(Position p : positions) { + Annotation annotation = new Annotation(false); + annotation.setType("MissingLink"); + annotation.setText("No link to this variable"); + _annotationModel.addAnnotation(annotation, p); + } + } + + public void setNoSuchVariableAnnotations(List positions){ + for(Position p : positions) { + Annotation annotation = new Annotation(false); + annotation.setType("NoSuchVariable"); + annotation.setText("No such variable in model"); + _annotationModel.addAnnotation(annotation, p); + } + } + + public void setSyntaxError(Token token){ + int start = 0; + int offset = this._document.getLength(); + if(token.image != null && this._document.getLength() > 0) { + try { + start = this._document.getLineOffset(token.beginLine - 1) + token.beginColumn - 1; + offset = this._document.getLineOffset(token.endLine - 1) + token.endColumn - start; + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + Annotation annotation = new Annotation(false); + annotation.setType("MissingLink"); + annotation.setText("Syntax error"); + Position p = new Position(start, offset); + _annotationModel.addAnnotation(annotation, p); + } + + public void resetAnnotations() { + _annotationModel.removeAllAnnotations(); + } + public void setExpression(String expression) { + _document.set(expression); + } + + public String getExpression() { + return this._document.get(); + } + + public Point getSelection() { + return _sourceViewer.getSelectedRange(); + } + + public void setSelection(int selection) { + this._sourceViewer.setSelectedRange(selection, 0); + } + + public IDocument getDocument() { + return _document; + } + + public void focus() { + this._sourceViewer.getTextWidget().forceFocus(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ExpressionFieldConfiguration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ExpressionFieldConfiguration.java new file mode 100644 index 00000000..018028ba --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ExpressionFieldConfiguration.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.text.DefaultTextHover; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.ITokenScanner; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; +import org.eclipse.jface.text.source.DefaultAnnotationHover; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.RGB; + +public class ExpressionFieldConfiguration extends SourceViewerConfiguration { + + + ColorManager colorManager; + + public ExpressionFieldConfiguration(ColorManager colorManager) { + super(); + this.colorManager = colorManager; + } + + public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { + return new String[] { + IDocument.DEFAULT_CONTENT_TYPE + }; + } + + /* + @Override + public IAutoEditStrategy[] getAutoEditStrategies( + ISourceViewer sourceViewer, String contentType) { + return new IAutoEditStrategy[] { + new ReplaceTabsBySpaces(), + new IndentLineEditStrategy(), + new MatchingBracketsEditStrategy() + }; + } + */ + + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + PresentationReconciler reconciler = new PresentationReconciler(); + + DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getSclTokenScanner()); + + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + + return reconciler; + } + + /* + * + */ + ITokenScanner getSclTokenScanner() { + RuleBasedScanner scanner = new RuleBasedScanner(); + + final Token reserved = new Token( + new TextAttribute( + colorManager.getColor(new RGB(127, 0, 85)), + null, + SWT.BOLD + )); + + + WordRule reservedWord = new WordRule(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + return Character.isLetter(c); + } + + @Override + public boolean isWordPart(char c) { + return Character.isLetter(c); + } + }); + + for(String s : keywords) { + reservedWord.addWord(s, reserved); + } + + IRule[] rules = new IRule[] { + reservedWord + }; + scanner.setRules(rules); + + return scanner; + } + + @Override + public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { + return new DefaultTextHover(sourceViewer); + } + + @Override + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new DefaultAnnotationHover(); + } + + static final Set keywords = new HashSet(); + + static { + keywords.add("within"); + keywords.add("final"); + keywords.add("public"); + keywords.add("protected"); + keywords.add("connect"); + keywords.add("when"); + keywords.add("then"); + keywords.add("elsewhen"); + keywords.add("if"); + keywords.add("end"); + keywords.add("elseif"); + keywords.add("else"); + keywords.add("for"); + keywords.add("while"); + keywords.add("loop"); + keywords.add("der"); + keywords.add("enumeration"); + keywords.add("extends"); + keywords.add("class"); + keywords.add("partial"); + keywords.add("encapsulated"); + keywords.add("model"); + keywords.add("record"); + keywords.add("block"); + keywords.add("expandable"); + keywords.add("connector"); + keywords.add("type"); + keywords.add("package"); + keywords.add("function"); + keywords.add("import"); + keywords.add("external"); + keywords.add("constrainedby"); + keywords.add("redeclare"); + keywords.add("replaceable"); + keywords.add("flow"); + keywords.add("discrete"); + keywords.add("parameter"); + keywords.add("constant"); + keywords.add("input"); + keywords.add("output"); + keywords.add("annotation"); + keywords.add("false"); + keywords.add("true"); + keywords.add("each"); + keywords.add("initial"); + keywords.add("algorithm"); + keywords.add("equation"); + keywords.add("or"); + keywords.add("and"); + keywords.add("not"); + keywords.add("break"); + keywords.add("return"); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/IExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/IExpressionViewFactor.java new file mode 100644 index 00000000..f7ac03b8 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/IExpressionViewFactor.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public interface IExpressionViewFactor { + + static final Font FONT = new Font(null, "Courier New", 12, SWT.NORMAL); + + /** + * Creates expression type specific user interface and initializes + * the components by the given data. The given map is linked + * to the ui components and updated. + * @param parent + * @param data + */ + void createView(Composite parent, Map data); + /** + * Reads expression type specific data from database. + * @param variable + * @return + */ + void readData(Resource variable, Map data); + + /** + * Writes expression type specific data to database. + * @param variable + * @return + */ + void writeData(Resource variable, Map data); + + /** + * Focuses to some part of the expression view. + */ + void focus(); + + /** + * Replaces the current selection with a variable name. + * @param var + */ + void replaceSelection(String var); + + /** + * Updates data from text inputs to the data map + * @param data + */ + void updateData(Map data); + + /** + * @return all individual expression fields for modelica validation + */ + List getExpressionFields(); + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupChartInfo.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupChartInfo.java new file mode 100644 index 00000000..237eff3c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupChartInfo.java @@ -0,0 +1,63 @@ +package org.simantics.sysdyn.ui.equation.expressions; + +import java.util.Map; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class LookupChartInfo { + + String lookupTable, expression; + Double minX, maxX, minY, maxY; + + private static Double MINX = 0.0; + private static Double MAXX = 10.0; + private static Double MINY = 0.0; + private static Double MAXY = 10.0; + + public LookupChartInfo(String expression, String lookupTable, final Resource variable, Map data) { + this.lookupTable = lookupTable != null ? lookupTable : ""; + this.expression = expression != null ? expression : ""; + this.minX = (Double)data.get("minX"); + this.maxX = (Double)data.get("maxX"); + this.minY = (Double)data.get("minY"); + this.maxY = (Double)data.get("maxY"); + if(variable != null && (minX == null || maxX == null || minY == null || maxY == null)) { + try { + SimanticsUI.getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if(expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) { + minX = graph.getPossibleRelatedValue(expression, sr.HasMinX); + if(minX == null) minX = MINX; + maxX = graph.getPossibleRelatedValue(expression, sr.HasMaxX); + if(maxX == null) maxX = MAXX; + minY = graph.getPossibleRelatedValue(expression, sr.HasMinY); + if(minY == null) minY = MINY; + maxY = graph.getPossibleRelatedValue(expression, sr.HasMaxY); + if(maxY == null) maxY = MAXY; + } else { + defaultValues(); + } + + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } + + private void defaultValues() { + minX = MINX; + maxX = MAXX; + minY = MINY; + maxY = MAXY; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupChartPanel.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupChartPanel.java new file mode 100644 index 00000000..c08fbf9f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupChartPanel.java @@ -0,0 +1,152 @@ +package org.simantics.sysdyn.ui.equation.expressions; + +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.jfree.chart.ChartPanel; +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.entity.ChartEntity; +import org.jfree.chart.entity.PlotEntity; +import org.jfree.chart.entity.XYItemEntity; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +@SuppressWarnings("serial") +public class LookupChartPanel extends ChartPanel { + + private XYItemEntity dragPrevEntity; + private boolean drawing; + private XYSeries series; + private JFreeChart chart; + private LookupInputOutputTable table; + + public LookupChartPanel(JFreeChart chart) { + super(chart); + this.chart = chart; + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + series = collection.getSeries(0); + } + + public void setTable(LookupInputOutputTable table) { + this.table = table; + } + + public void mouseDragged(MouseEvent e) + { + if(dragPrevEntity != null) { + + int item = dragPrevEntity.getItem(); + XYPlot plot = (XYPlot)chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + ValueAxis domainAxis = plot.getDomainAxis(); + Point2D location = getLocationOnChart(getMouseLocation(e)); + Number prevX = item == 0 ? null : series.getX(item - 1); + Number nextX = item == series.getItemCount() - 1 ? null : series.getX(item + 1); + + + if(series.indexOf(location.getX()) >= 0 && series.indexOf(location.getX()) != item) + return; + else if (prevX != null && location.getX() < prevX.doubleValue()) + location.setLocation(series.getX(item).doubleValue(), location.getY()); + else if (nextX != null && location.getX() > nextX.doubleValue()) + location.setLocation(series.getX(item).doubleValue(), location.getY()); + else if (location.getX() > domainAxis.getUpperBound()) + location.setLocation(domainAxis.getUpperBound(), location.getY()); + else if (location.getX() < domainAxis.getLowerBound()) + location.setLocation(domainAxis.getLowerBound(), location.getY()); + + if (location.getY() > rangeAxis.getUpperBound()) + location.setLocation(location.getX(), rangeAxis.getUpperBound()); + else if (location.getY() < rangeAxis.getLowerBound()) + location.setLocation(location.getX(), rangeAxis.getLowerBound()); + + removeItemFromSeries(dragPrevEntity.getItem()); + addLocationToSeries(location); + } else { + ChartEntity currEntity = this.getEntityForPoint(e.getX(),e.getY()); + if(!drawing && currEntity instanceof XYItemEntity) { + dragPrevEntity = ((XYItemEntity)currEntity); + } else if (currEntity instanceof PlotEntity){ + drawing = true; + Point2D locationOnChart = getLocationOnChart(getMouseLocation(e)); + int item = series.indexOf(locationOnChart.getX()); + if (item >= 0) { + Point2D location = new Point2D.Double(series.getX(item).doubleValue(), series.getY(item).doubleValue()); + Point2D javaLocation = getLocationOnJava2D(location); + removeItemFromSeries(item); + addLocationToSeries(getLocationOnChart(new Point2D.Double(javaLocation.getX(), e.getY()))); + } + } + } + + } + + public void mouseReleased(MouseEvent e) { + + dragPrevEntity = null; + drawing = false; + } + + public void mouseClicked(MouseEvent e) + { + if(e.getButton() == MouseEvent.BUTTON1) { + addLocationToSeries(getLocationOnChart(getMouseLocation(e))); + } else if (e.getButton() == MouseEvent.BUTTON3) { + ChartEntity entity = this.getEntityForPoint(e.getX(),e.getY()); + if(entity instanceof XYItemEntity) { + XYItemEntity xyentity = ((XYItemEntity)entity); + removeItemFromSeries(xyentity.getItem()); + } + } + } + + private Point2D getLocationOnChart(Point2D coordinates) { + XYPlot plot = (XYPlot)chart.getPlot(); + ChartRenderingInfo info = getChartRenderingInfo(); + Rectangle2D dataArea = info.getPlotInfo().getDataArea(); + double chartX = plot.getDomainAxis().java2DToValue(coordinates.getX(), dataArea, + plot.getDomainAxisEdge()); + double chartY = plot.getRangeAxis().java2DToValue(coordinates.getY(), dataArea, + plot.getRangeAxisEdge()); + return new Point2D.Double(chartX, chartY); + } + + private Point2D getLocationOnJava2D(Point2D location) { + XYPlot plot = (XYPlot)chart.getPlot(); + ChartRenderingInfo info = getChartRenderingInfo(); + Rectangle2D dataArea = info.getPlotInfo().getDataArea(); + double javaX = plot.getDomainAxis().valueToJava2D(location.getX(), dataArea, + plot.getDomainAxisEdge()); + double javaY = plot.getRangeAxis().valueToJava2D(location.getY(), dataArea, + plot.getRangeAxisEdge()); + return new Point2D.Double(javaX, javaY); + } + + public void addLocationToSeries(Point2D location) { + if(series.indexOf(location.getX()) < 0) { + series.add(location.getX(), location.getY()); + table.addLocation(location); + } + } + + public void removeItemFromSeries(int item){ + Point2D location = new Point2D.Double(series.getX(item).doubleValue(),series.getY(item).doubleValue()); + series.remove(item); + table.removeLocation(location); + } + + private Point2D getMouseLocation(MouseEvent e) { + int mouseX = e.getX(); + int mouseY = e.getY(); + Point2D p = translateScreenToJava2D( + new Point(mouseX, mouseY)); + return p; + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupExpressionViewFactor.java new file mode 100644 index 00000000..97841d94 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupExpressionViewFactor.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class LookupExpressionViewFactor implements IExpressionViewFactor { + + @Override + public void createView(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public void readData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void writeData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupInputOutputTable.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupInputOutputTable.java new file mode 100644 index 00000000..585ac91c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupInputOutputTable.java @@ -0,0 +1,202 @@ +package org.simantics.sysdyn.ui.equation.expressions; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +public class LookupInputOutputTable extends Composite { + + public static final String INPUT = "Input"; + public static final String OUTPUT = "Output"; + public static final String[] PROPS = { INPUT, OUTPUT }; + + Table table; + TableViewer tableViewer; + List tableRows; + + public LookupInputOutputTable(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + GridDataFactory.fillDefaults().grab(true, true).applyTo(this); + table = new Table(this, SWT.BORDER|SWT.SINGLE|SWT.FULL_SELECTION); + GridDataFactory.fillDefaults().grab(true, true).applyTo(table); + table.setHeaderVisible (true); + table.setLinesVisible(true); + table.getVerticalBar().setVisible(true); + TableColumn column1 = new TableColumn (table, SWT.LEFT); + column1.setText (INPUT); + column1.setWidth (85); + + TableColumn column2 = new TableColumn (table, SWT.LEFT); + column2.setText (OUTPUT); + column2.setWidth (85); + + // Create the viewer and connect it to the view + tableViewer = new TableViewer (table); + + tableViewer.setContentProvider (new ArrayContentProvider()); + tableViewer.setLabelProvider (new InputOutputLabelProvider()); + + tableRows = new ArrayList(); + tableViewer.setInput(tableRows); + + CellEditor[] editors = new CellEditor[2]; + editors[0] = new TextCellEditor(table); + editors[1] = new TextCellEditor(table); + tableViewer.setCellEditors(editors); + tableViewer.setColumnProperties(PROPS); + + } + + private class InputOutputLabelProvider extends LabelProvider implements ITableLabelProvider { + public Image getColumnImage (Object element, int columnIndex) { + return null; + } + public String getColumnText (Object element, int columnIndex) { + if(element instanceof InputOutput) { + InputOutput io = (InputOutput)element; + switch (columnIndex) { + case 0: return (String)io.getInput(String.class); + case 1: return (String)io.getOutput(String.class); + } + } + return ""; + } + } + + public void addLocation(Point2D location) { + tableRows.add(new InputOutput(location.getX(), location.getY())); + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + refresh(); + } + }); + + } + + public void removeLocation(Point2D location) { + for(InputOutput io : tableRows) { + if((Double)io.getInput(Double.class) == location.getX()) { + tableRows.remove(io); + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + refresh(); + } + }); + break; + } + } + + } + + + class InputOutput { + private double input, output; + + public InputOutput(double input, double output) { + this.input = input; + this.output = output; + } + + /** + * + * @param clazz String.class or Double.class + * @return input as string or double or null if asked for something else + */ + @SuppressWarnings("unchecked") + public Object getInput(Class clazz) { + if(clazz == String.class) { + return "" + input; + } else if (clazz == Double.class) { + return input; + } + return null; + } + + public Double setInput(String input) { + try { + this.input = Double.parseDouble(input); + return this.input; + } catch (NumberFormatException e) { + return null; + } + } + + public void setInput(double input) { + this.input = input; + } + + /** + * + * @param clazz String.class or Double.class + * @return output as string or double or null if asked for something else + */ + @SuppressWarnings("unchecked") + public Object getOutput(Class clazz) { + if(clazz == String.class) { + return "" + output; + } else if (clazz == Double.class) { + return output; + } + return null; + } + + public void setOutput(String output) { + try { + this.output = Double.parseDouble(output); + } catch (NumberFormatException e) { + + } + } + + public void setOutput(double output) { + this.output = output; + } + + } + + class InputOutputComparator extends ViewerComparator { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + if ((e1 instanceof InputOutput) && + (e2 instanceof InputOutput)) { + InputOutput io1 = (InputOutput)e1; + InputOutput io2 = (InputOutput)e2; + Double d1 = (Double)io1.getInput((Double.class)); + Double d2 = (Double)io2.getInput((Double.class)); + return d1.compareTo(d2); + } + return 0; + } + } + + public TableViewer getTableViewer() { + return this.tableViewer; + } + + public void refresh() { + tableViewer.setComparator(new InputOutputComparator()); + tableViewer.refresh(); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupPopup.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupPopup.java new file mode 100644 index 00000000..57b29045 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/LookupPopup.java @@ -0,0 +1,435 @@ +package org.simantics.sysdyn.ui.equation.expressions; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.GridLayout; +import java.awt.event.MouseEvent; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Iterator; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYDataItem; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.simantics.g2d.chassis.SWTAWTComponent; +import org.simantics.sysdyn.tableParser.ParseException; +import org.simantics.sysdyn.tableParser.Token; +import org.simantics.sysdyn.tableParser.TableParser; +import org.simantics.sysdyn.ui.equation.expressions.LookupInputOutputTable.InputOutput; + +public class LookupPopup extends Dialog { + + JFreeChart chart; + LookupInputOutputTable table; + ArrayList dataPoints; + Text input, output; + Text minX, maxX, minY, maxY; + Label unit; + LookupChartInfo chartInfo; + + protected LookupPopup(Shell parentShell, LookupChartInfo chartInfo) { + super(parentShell); + this.chartInfo = chartInfo; + this.dataPoints = new ArrayList(); + TableParser parser = new TableParser(new StringReader("")); + parser.ReInit(new StringReader(chartInfo.lookupTable)); + try { + parser.table(); + ArrayList xTokens = parser.getXTokens(); + for(Token token : xTokens) { + dataPoints.add(new Point2D.Double( + Double.parseDouble(token.image), + Double.parseDouble(token.next.next.image))); + } + } catch (ParseException e1) { + } + + } + + @Override + protected Control createDialogArea(Composite parent) { + KeyListener enterListener = new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) {} + + @Override + public void keyPressed(KeyEvent e) { + if(e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) + getButton(IDialogConstants.OK_ID).forceFocus(); + } + }; + + final LookupChartPanel chartPanel = new LookupChartPanel(createChart()); + chartPanel.setPreferredSize(new java.awt.Dimension(500, 270)); + chartPanel.setMouseZoomable(true, false); + chartPanel.setDomainZoomable(false); + chartPanel.setRangeZoomable(false); + + XYPlot plot = (XYPlot) chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + ValueAxis domainAxis = plot.getDomainAxis(); + + Composite container = new Composite(parent, SWT.None); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(container); + + Composite yAxis = new Composite(container, SWT.NONE); + GridLayoutFactory.fillDefaults().applyTo(yAxis); + GridDataFactory.fillDefaults().grab(false, true).applyTo(yAxis); + maxY = new Text(yAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(maxY); + maxY.addKeyListener(enterListener); + maxY.addModifyListener(getAxisBoundModifyListener()); + maxY.setText("" + rangeAxis.getUpperBound()); + Composite fillY = new Composite(yAxis, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(false, true).applyTo(fillY); + GridLayoutFactory.fillDefaults().applyTo(fillY); + unit = new Label(fillY, SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(unit); + unit.setText(""); //TODO: how to get and update units? + unit.addKeyListener(enterListener); + minY = new Text(yAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(minY); + minY.addKeyListener(enterListener); + minY.addModifyListener(getAxisBoundModifyListener()); + minY.setText("" + rangeAxis.getLowerBound()); + + SWTAWTComponent c = new SWTAWTComponent(container, SWT.BORDER) { + @Override + protected JComponent createSwingComponent() { + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(1, 1)); + panel.setPreferredSize(new java.awt.Dimension(500, 270)); + panel.add(chartPanel); + panel.doLayout(); + return panel; + } + }; + GridDataFactory.fillDefaults().hint(500, 300).applyTo(c); + c.populate(); + + + Composite valueTableComposite = new Composite(container, SWT.NONE); + GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(valueTableComposite); + GridLayoutFactory.fillDefaults().numColumns(3).applyTo(valueTableComposite); + + + table = new LookupInputOutputTable(valueTableComposite, SWT.NONE); + GridDataFactory.fillDefaults().span(3, 1).grab(true, true).applyTo(table); + chartPanel.setTable(table); + table.getTableViewer().setCellModifier(new InputOutputCellModifier()); + table.getTableViewer().getTable().addMouseListener(new MouseListener() { + + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) { + if(e.button == MouseEvent.BUTTON3) { + Table table = (Table)e.widget; + TableItem item = (TableItem)table.getItem(new org.eclipse.swt.graphics.Point(e.x, e.y)); + chartPanel.removeItemFromSeries(table.indexOf(item)); + } + } + @Override + public void mouseDown(org.eclipse.swt.events.MouseEvent e) { } + @Override + public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) { } + }); + for(Point2D location : this.dataPoints) { + chartPanel.addLocationToSeries(location); + } + + input = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(60, SWT.DEFAULT).applyTo(input); + input.setText(""); + output = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(60, SWT.DEFAULT).applyTo(output); + output.setText(""); + + Button add = new Button(valueTableComposite, SWT.None); + add.setText("Add"); + add.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + try { + Double in = Double.parseDouble(input.getText()); + Double out = Double.parseDouble(output.getText()); + chartPanel.addLocationToSeries(new Point2D.Double(in, out)); + } catch (NumberFormatException e1) { + input.setText(""); + output.setText(""); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + }); + + FocusListener flistener = new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + Text text = (Text)e.widget; + text.setSelection(0, text.getCharCount()); + } + @Override + public void focusLost(FocusEvent e) { } + }; + + + KeyListener listener = new KeyListener() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) { + try { + Double in = Double.parseDouble(input.getText()); + Double out = Double.parseDouble(output.getText()); + chartPanel.addLocationToSeries(new Point2D.Double(in, out)); + } catch (NumberFormatException e1) { + if(input.getText().isEmpty() && output.getText().isEmpty()) { + getButton(IDialogConstants.OK_ID).forceFocus(); + return; + } + } + input.setText(""); + output.setText(""); + input.setFocus(); + } + } + + @Override + public void keyReleased(KeyEvent e) { } + + }; + + input.addFocusListener(flistener); + input.addKeyListener(listener); + output.addFocusListener(flistener); + output.addKeyListener(listener); + + Label l = new Label(container, SWT.NONE); + l.setText(""); + + Composite xAxis = new Composite(container, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(xAxis); + GridLayoutFactory.fillDefaults().numColumns(3).applyTo(xAxis); + minX = new Text(xAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(minX); + minX.addKeyListener(enterListener); + minX.addModifyListener(getAxisBoundModifyListener()); + minX.setText("" + domainAxis.getLowerBound()); + Composite fillX = new Composite(xAxis, SWT.CENTER); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(true, false).applyTo(fillX); + GridLayoutFactory.fillDefaults().applyTo(fillX); + l = new Label(fillX, SWT.NONE); + l.setText(chartInfo.expression); + maxX = new Text(xAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(maxX); + maxX.addKeyListener(enterListener); + maxX.addModifyListener(getAxisBoundModifyListener()); + maxX.setText("" + domainAxis.getUpperBound()); + + return null; + } + + protected void createButtonsForButtonBar(Composite parent) { + // create OK and Cancel buttons by default + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, + false); + createButton(parent, IDialogConstants.CANCEL_ID, + IDialogConstants.CANCEL_LABEL, false); + } + + public LookupChartInfo open(Boolean bool) { + Shell shell = this.getShell(); + if (shell == null || shell.isDisposed()) { + shell = null; + create(); + shell = this.getShell(); + } + constrainShellSize(); + shell.open(); + getButton(IDialogConstants.OK_ID).setFocus(); + Display display = getParentShell().getDisplay(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + return chartInfo; + } + + @Override + public void okPressed() { + chartInfo.lookupTable = graphToModelicaTable(); + chartInfo.minX = Double.parseDouble(minX.getText()); + chartInfo.maxX = Double.parseDouble(maxX.getText()); + chartInfo.minY = Double.parseDouble(minY.getText()); + chartInfo.maxY = Double.parseDouble(maxY.getText()); + super.okPressed(); + } + + @SuppressWarnings("unchecked") + private String graphToModelicaTable() { + StringBuilder b = new StringBuilder(); + b.append("{"); + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + XYSeries series = collection.getSeries(0); + if(series.isEmpty()) + return ""; + Iterator iterator = series.getItems().iterator(); + while(iterator.hasNext()){ + XYDataItem item = (XYDataItem)iterator.next(); + b.append("{" + item.getX() + "," + item.getY() + "}"); + if(iterator.hasNext()) + b.append(","); + } + b.append("}"); + return b.toString(); + } + + private JFreeChart createChart() { + XYDataset dataset = createDataset(); + chart = ChartFactory.createXYLineChart(null, null, null, + dataset, PlotOrientation.VERTICAL, false, true, false); + XYPlot plot = (XYPlot) chart.getPlot(); + XYLineAndShapeRenderer renderer + = (XYLineAndShapeRenderer) plot.getRenderer(); + renderer.setBaseShapesVisible(true); + renderer.setDrawOutlines(true); + renderer.setUseFillPaint(true); + renderer.setBaseFillPaint(Color.white); + renderer.setSeriesStroke(0, new BasicStroke(3.0f)); + renderer.setSeriesOutlineStroke(0, new BasicStroke(2.0f)); + renderer.setSeriesShape(0, new Ellipse2D.Double(-5.0, -5.0, 10.0, 10.0)); + + ValueAxis rangeAxis = plot.getRangeAxis(); + rangeAxis.setAutoRange(false); + rangeAxis.setRange(chartInfo.minY, chartInfo.maxY); + ValueAxis domainAxis = plot.getDomainAxis(); + domainAxis.setAutoRange(false); + domainAxis.setRange(chartInfo.minX, chartInfo.maxX); + return chart; + } + + public XYDataset createDataset() { + XYSeries series = new XYSeries("Series"); + XYSeriesCollection dataset = new XYSeriesCollection(); + dataset.addSeries(series); + return dataset; + } + + private ModifyListener getAxisBoundModifyListener() { + return new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + Widget widget = e.widget; + if(widget instanceof Text) { + Text text = (Text)widget; + Double value; + try { + value = Double.parseDouble(text.getText()); + } catch (NumberFormatException e1 ) { + return; + } + XYPlot plot = (XYPlot) chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + ValueAxis domainAxis = plot.getDomainAxis(); + if(text == minX) { + domainAxis.setLowerBound(value); + } else if (text == maxX) { + domainAxis.setUpperBound(value); + } else if (text == minY) { + rangeAxis.setLowerBound(value); + } else if (text == maxY) { + rangeAxis.setUpperBound(value); + } + } + } + }; + } + + private class InputOutputCellModifier implements ICellModifier { + + XYSeries series; + + public InputOutputCellModifier() { + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + series = collection.getSeries(0); + } + + public boolean canModify(Object element, String property) { + return true; + } + + public Object getValue(Object element, String property) { + InputOutput io = (InputOutput)element; + if (LookupInputOutputTable.INPUT.equals(property)) + return (String)io.getInput(String.class); + else if (LookupInputOutputTable.OUTPUT.equals(property)) + return (String)io.getOutput(String.class); + else + return null; + } + + public void modify(Object element, String property, Object value) { + if (element instanceof Item) element = ((Item) element).getData(); + + InputOutput io = (InputOutput)element; + Double x = (Double)io.getInput(Double.class); + int item = series.indexOf(x); + series.remove(item); + + if (LookupInputOutputTable.INPUT.equals(property)) { + Double newX = io.setInput((String)value); + // if has the same x-value, revert back + if(newX != null && series.indexOf(newX) >= 0) { + io.setInput(x); + } + } else if (LookupInputOutputTable.OUTPUT.equals(property)) { + io.setOutput((String)value); + } + + series.add((Double)io.getInput(Double.class), (Double)io.getOutput(Double.class)); + + table.refresh(); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ParameterExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ParameterExpressionViewFactor.java new file mode 100644 index 00000000..fe234848 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/ParameterExpressionViewFactor.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ParameterExpressionViewFactor implements IExpressionViewFactor { + + private Label equationLabel; + private ExpressionField expression; + + @Override + public void createView(Composite parent, Map data) { + + final String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + + + GridLayoutFactory.fillDefaults().numColumns(2).spacing(3, 3).applyTo(parent); + equationLabel = new Label(parent, SWT.NONE); + equationLabel.setFont(FONT); + equationLabel.setText("="); + GridDataFactory.fillDefaults().applyTo(equationLabel); + + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setFont(FONT); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + } + + @Override + public void focus() { + if(this.expression != null) this.expression.focus(); + } + + @Override + public void readData(final Resource variable, Map data) { + String equation = null; + if (variable != null && data.get("equation") == null) { + try { + equation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.ParameterExpression)) { + return graph.getRelatedValue(expression, sr.HasEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", equation); + } + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void writeData(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + if(currentText != null) { + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.ParameterExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasEquation, currentText); + } + + }); + } + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } + +} + diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/StockExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/StockExpressionViewFactor.java new file mode 100644 index 00000000..ac8b7455 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/StockExpressionViewFactor.java @@ -0,0 +1,208 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class StockExpressionViewFactor implements IExpressionViewFactor { + + private Label integralLabel; + private Text integral; + private Label equationLabel; + private ExpressionField expression; + + @Override + public void createView(Composite parent, Map data) { + + final String initialEquation = data.get("initialEquation") != null ? (String)data.get("initialEquation") : ""; + final String integralEquation = data.get("integral") != null ? (String)data.get("integral") : ""; + + GridLayoutFactory.fillDefaults().numColumns(2).spacing(3, 3).applyTo(parent); + + integralLabel = new Label(parent, SWT.NONE); + integralLabel.setFont(FONT); + integralLabel.setText("Integral"); + GridDataFactory.fillDefaults().applyTo(integralLabel); + + integral = new Text(parent, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER); + integral.setEditable(false); + integral.setFont(FONT); + integral.setText(integralEquation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(integral); + + equationLabel = new Label(parent, SWT.NONE); + equationLabel.setFont(FONT); + equationLabel.setText("Initial\nValue"); + GridDataFactory.fillDefaults().applyTo(equationLabel); + + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setFont(FONT); + expression.setExpression(initialEquation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + } + + @Override + public void readData(final Resource variable, Map data) { + String initialEquation = null; + + if (variable != null && data.get("initialEquation") == null) { + try { + initialEquation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.StockExpression)) { + return graph.getRelatedValue(expression, sr.HasInitialEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("initialEquation", initialEquation); + } + + data.put("integral", getIntegral(variable)); + } + + @Override + public void writeData(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + if(currentText != null) { + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.StockExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasInitialEquation, currentText); + } + + }); + } + } + + private String getIntegral(final Resource variable) { + String integral = ""; + try { + integral = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + Collection heads = graph.getObjects(variable, sr.IsHeadOf); + Collection tails = graph.getObjects(variable, sr.IsTailOf); + + StringBuilder builder = new StringBuilder(); + builder.append(""); + for (Resource r : heads) { + if(graph.isInstanceOf(r, sr.Flow)) { + Resource tail = graph.getPossibleObject(r, sr.HasTail); + if(tail != null) { + Object name = graph.getPossibleRelatedValue(tail, b.HasName); + if (name != null) + builder.append(" + " + name); + } + } + } + for (Resource r : tails) { + if(graph.isInstanceOf(r, sr.Flow)) { + Resource head = graph.getPossibleObject(r, sr.HasHead); + if(head != null) { + Object name = graph.getPossibleRelatedValue(head, b.HasName); + if (name != null) + builder.append(" - " + name); + } + } + } + if (builder.indexOf(" + ") == 0) + builder.delete(0, 3); + return builder.toString().trim(); + } + + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return integral; + } + + @Override + public void focus() { + if(this.expression != null) this.expression.focus(); + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("initialEquation", this.expression.getExpression()); + if(this.integral != null && this.integral.getText() != null) + data.put("integral", this.integral.getText()); + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/WithLookupExpressionViewFactor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/WithLookupExpressionViewFactor.java new file mode 100644 index 00000000..43218e06 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/equation/expressions/WithLookupExpressionViewFactor.java @@ -0,0 +1,221 @@ +/******************************************************************************* + * 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.sysdyn.ui.equation.expressions; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class WithLookupExpressionViewFactor implements IExpressionViewFactor { + + + private Label expressionLabel; + private ExpressionField expression; + private Label lookupLabel; + private ExpressionField lookup; + private Button asGraph; + private ExpressionField lastSelectedText = expression; + private Resource variable; + private LookupChartInfo chartInfo; + + public WithLookupExpressionViewFactor(Resource variable) { + super(); + this.variable = variable; + } + + @Override + public void createView(Composite parent, final Map data) { + String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + String lookupTable = data.get("lookup") != null ? (String)data.get("lookup") : ""; + + GridLayoutFactory.fillDefaults().numColumns(2).spacing(3, 3).applyTo(parent); + + expressionLabel = new Label(parent, SWT.NONE); + expressionLabel.setFont(FONT); + expressionLabel.setText("With\nLookup"); + GridDataFactory.fillDefaults().applyTo(expressionLabel); + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setFont(FONT); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + expression.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + lastSelectedText = expression; + } + }); + + lookupLabel = new Label(parent, SWT.NONE); + lookupLabel.setFont(FONT); + lookupLabel.setText("Lookup\ntable"); + GridDataFactory.fillDefaults().applyTo(lookupLabel); + + lookup = new ExpressionField(parent, SWT.BORDER); + lookup.setFont(FONT); + lookup.setExpression(lookupTable); + GridDataFactory.fillDefaults().grab(true, true).applyTo(lookup); + + lookup.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + lastSelectedText = lookup; + } + }); + + asGraph = new Button(parent, SWT.None); + asGraph.setText("As graph"); + asGraph.setFont(FONT); + asGraph.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if(e.widget == asGraph) { + if(chartInfo == null) chartInfo = new LookupChartInfo(expression.getExpression(), lookup.getExpression(), variable, data); + LookupPopup pud = new LookupPopup(asGraph.getParent().getShell(), chartInfo); + LookupChartInfo newInfo = pud.open(false); + if(pud.getReturnCode() == org.eclipse.jface.window.Window.OK) { + chartInfo = newInfo; + lookup.setExpression(chartInfo.lookupTable); + } + } + } + }); + + } + + @Override + public void readData(final Resource variable, Map data) { + String[] results = null; + if (variable != null && data.get("equation") == null) { + try { + results = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String[] perform(ReadGraph graph) throws DatabaseException { + String[] results = new String[2]; + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) { + results[0] = graph.getRelatedValue(expression, sr.HasEquation); + results[1] = graph.getRelatedValue(expression, sr.HasLookup); + } else { + results[0] = ""; + results[1] = ""; + } + return results; + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", results[0]); + data.put("lookup", results[1]); + } + } + + @Override + public void writeData(final Resource variable, Map data) { + final String currentExpression = expression.getExpression(); + final String currentLookupTable = lookup.getExpression(); + + if(currentExpression != null && currentLookupTable != null) { + data.putAll(data); + data.put("equation", currentExpression); + data.put("lookup", currentLookupTable); + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.WithLookupExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasEquation, currentExpression); + g.claimValue(expression, sr.HasLookup, currentLookupTable); + g.claimValue(expression, sr.HasMinX, chartInfo.minX); + g.claimValue(expression, sr.HasMaxX, chartInfo.maxX); + g.claimValue(expression, sr.HasMinY, chartInfo.minY); + g.claimValue(expression, sr.HasMaxY, chartInfo.maxY); + } + }); + } + } + + @Override + public void focus() { + if(this.lastSelectedText != null) this.lastSelectedText.focus(); + } + + @Override + public void replaceSelection(String var) { + if(lastSelectedText != null) { + IDocument doc = lastSelectedText.getDocument(); + try { + Point selection = lastSelectedText.getSelection(); + doc.replace(selection.x, selection.y, var); + lastSelectedText.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + if(this.lookup != null && this.lookup.getExpression() != null) + data.put("lookup", this.lookup.getExpression()); + if(this.chartInfo != null) { + data.put("minX", chartInfo.minX); + data.put("maxX", chartInfo.maxX); + data.put("minY", chartInfo.minY); + data.put("maxY", chartInfo.maxY); + } + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression, this.lookup); + } +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateAuxiliaryHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateAuxiliaryHandler.java new file mode 100644 index 00000000..cc32ba40 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateAuxiliaryHandler.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.sysdyn.ui.actions.CreateAuxiliary; + +public class CreateAuxiliaryHandler extends DiagramContextMenuActionHandler { + + protected void handleEvent(IDiagramEditor editor, IEvent event) { + CreateAuxiliary ca = new CreateAuxiliary(); + ca.handle(editor, event); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateCloudHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateCloudHandler.java new file mode 100644 index 00000000..2beded5c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateCloudHandler.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.sysdyn.ui.actions.CreateCloud; + +public class CreateCloudHandler extends DiagramContextMenuActionHandler { + + protected void handleEvent(IDiagramEditor editor, IEvent event) { + CreateCloud cc = new CreateCloud(); + cc.handle(editor, event); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateStockHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateStockHandler.java new file mode 100644 index 00000000..2716596a --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateStockHandler.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.sysdyn.ui.actions.CreateStock; + +public class CreateStockHandler extends DiagramContextMenuActionHandler { + + protected void handleEvent(IDiagramEditor editor, IEvent event) { + CreateStock cs = new CreateStock(); + cs.handle(editor, event); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateValveHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateValveHandler.java new file mode 100644 index 00000000..e4fe83b1 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/CreateValveHandler.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.sysdyn.ui.actions.CreateValve; + +public class CreateValveHandler extends DiagramContextMenuActionHandler { + + protected void handleEvent(IDiagramEditor editor, IEvent event) { + CreateValve cv = new CreateValve(); + cv.handle(editor, event); + } + +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/DiagramContextMenuActionHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/DiagramContextMenuActionHandler.java new file mode 100644 index 00000000..b13abfab --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/DiagramContextMenuActionHandler.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.sysdyn.ui.actions.DiagramContextMenuData; +import org.simantics.sysdyn.ui.editor.SysdynDiagramEditor; + +public abstract class DiagramContextMenuActionHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IWorkbenchPart ap = HandlerUtil.getActivePart(event); + if(ap instanceof SysdynDiagramEditor) { + Event ci = (Event)event.getTrigger(); + MenuItem mi = (MenuItem) ci.widget; + Menu m = mi.getParent(); + while(m.getParentMenu() != null) + m = m.getParentMenu(); + DiagramContextMenuData cmd = (DiagramContextMenuData) m.getData(); + IDiagramEditor de = cmd.diagramEditor; + IEvent evnt = cmd.event; + handleEvent(de, evnt); + } + return null; + } + + + protected void handleEvent(IDiagramEditor editor, IEvent event) { + // Implement in another class + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/DisposeExperiment.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/DisposeExperiment.java new file mode 100644 index 00000000..13bc387c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/DisposeExperiment.java @@ -0,0 +1,35 @@ +package org.simantics.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.simantics.project.IExperimentDescriptor; +import org.simantics.project.IProject; +import org.simantics.project.ProjectKeys; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.ui.SimanticsUI; + +public class DisposeExperiment extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IProject project = SimanticsUI.getProject(); + IExperimentManager manager = + project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); + IExperiment experiment = manager.getActiveExperiment(); + if (experiment != null) + experiment.shutdown(); + + /* + // Keep the UI happy. + IExperimentDescriptor ed = project.getHint(ProjectKeys.KEY_SELECTED_UI_EXPERIMENT); + if (ed != null) { + ed.getParent().removeHint(ProjectKeys.KEY_SELECTED_EXPERIMENT); + project.removeHint(ProjectKeys.KEY_SELECTED_UI_EXPERIMENT); + } + */ + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewExperimentNodeHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewExperimentNodeHandler.java new file mode 100644 index 00000000..3b101a20 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewExperimentNodeHandler.java @@ -0,0 +1,47 @@ +package org.simantics.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.utils.ResourceAdaptionUtils; + +public class NewExperimentNodeHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + System.out.println("New Experiment"); + + ISelection sel = HandlerUtil.getCurrentSelection(event); + Resource[] resources = ResourceAdaptionUtils.toResources(sel); + if (resources.length != 1) + return null; + + final Resource model = resources[0]; + + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) throws DatabaseException { + Builtins b = g.getBuiltins(); + Resource report = GraphUtils.create2(g, b.Report, b.HasDocumentation, "===Report==="); + @SuppressWarnings("unused") + Resource experiment = GraphUtils.create2(g, b.Experiment, + b.HasName, "Experiment", + b.HasLabel, "Experiment", + b.HasReportFactory, report, + b.PartOf, model); + } + }); + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModelHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModelHandler.java new file mode 100644 index 00000000..b4c6265c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModelHandler.java @@ -0,0 +1,76 @@ +package org.simantics.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.DiagramConstants; +import org.simantics.diagram.synchronization.graph.layer.GraphLayer; +import org.simantics.diagram.synchronization.graph.layer.GraphLayerUtil; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.ModelingUtils; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class NewModelHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) throws DatabaseException { + // Same as in SysdynProject.java. Should use the same code, not copy. + Builtins b = g.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(g); + ModelingResources mr = ModelingResources.getInstance(g); + ModelingUtils mu = new ModelingUtils(g); + + Resource model = g.newResource(); + g.claimValue(model, b.HasName, "Model1"); + g.claimValue(model, b.HasLabel, "Model1"); + g.claim(model, b.InstanceOf, sr.SysdynModel); + g.claim(model, b.PartOf, SimanticsUI.getProject().get()); + + + Resource diagram = OrderedSetUtils.create(g, sr.ConfigurationDiagram); + GraphLayer l = new GraphLayerUtil(g).createLayer(DiagramConstants.DEFAULT_LAYER_NAME, true); + g.claim(diagram, mu.dr.HasLayer, l.getLayer()); + g.claimValue(diagram, b.HasName, "Diagrammi", StringBindingDefault.INSTANCE); + + Resource conf = GraphUtils.create2(g, + sr.Configuration, + b.PartOf, model, + b.HasName, "Configuration", + sr.HasStartTime, 0.0, + sr.HasStopTime, 10.0); + + g.claim(conf, mr.CompositeToDiagram, diagram); + g.claim(model, b.HasConfiguration, conf); + + Resource mapping = g.newResource(); + g.claim(mapping, b.InstanceOf, null, sr.DiagramToCompositeMapping); + g.claim(diagram, b.HasTrigger, mapping); + + Resource report = GraphUtils.create2(g, mu.b.Report, mu.b.HasDocumentation, "===Report==="); + + Resource experiment = GraphUtils.create2(g, mu.b.Experiment, + mu.b.HasName, "Experiment", + mu.b.HasLabel, "Experiment", + mu.b.HasReportFactory, report, + mu.b.PartOf, model); + } + }); + return null; + } + + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModuleNodeHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModuleNodeHandler.java new file mode 100644 index 00000000..cd1484ed --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/NewModuleNodeHandler.java @@ -0,0 +1,95 @@ +package org.simantics.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.diagram.DiagramConstants; +import org.simantics.diagram.synchronization.graph.layer.GraphLayer; +import org.simantics.diagram.synchronization.graph.layer.GraphLayerUtil; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.modeling.ModelingUtils; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.utils.ResourceAdaptionUtils; + +public class NewModuleNodeHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + + ISelection sel = HandlerUtil.getCurrentSelection(event); + Resource[] resources = ResourceAdaptionUtils.toResources(sel); + if (resources.length != 1) + return null; + + final Resource model = resources[0]; + + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) throws DatabaseException { + // Same as in SysdynProject.java. Should use the same code, not copy. + SysdynResource sr = SysdynResource.getInstance(g); + ModelingUtils mu = new ModelingUtils(g); + + Resource moduleType = g.newResource(); + g.claimValue(moduleType, mu.b.HasName, "New Module Type"); + g.claim(moduleType, mu.b.Inherits, sr.Module); + g.claim(moduleType, mu.b.PartOf, model); + + Resource diagram = OrderedSetUtils.create(g, sr.ConfigurationDiagram); + GraphLayer l = new GraphLayerUtil(g).createLayer(DiagramConstants.DEFAULT_LAYER_NAME, true); + g.claim(diagram, mu.dr.HasLayer, l.getLayer()); + Resource mapping = g.newResource(); + g.claim(mapping, mu.b.InstanceOf, null, sr.DiagramToCompositeMapping); + g.claim(diagram, mu.b.HasTrigger, mapping); + + + Resource configuration = GraphUtils.create2(g, + sr.Configuration, + mu.b.HasName, "ModuuliConffi", + mu.mr.CompositeToDiagram, diagram); + + g.claim(moduleType, mu.sr.IsDefinedBy , configuration); + + + Resource moduleSymbol = g.newResource(); + g.claimValue(moduleSymbol, mu.b.HasName, "ModuuliSymboli"); + g.claimValue(moduleSymbol, mu.b.HasLabel, "ModuuliSymboliLabel"); + g.claim(moduleSymbol, mu.b.Inherits, sr.ModuleSymbol); + g.claim(moduleSymbol, mu.mr.SymbolToComponentType, moduleType); + + Resource terminal = g.newResource(); + g.claim(terminal, mu.b.InstanceOf, sr.SysdynTerminal); + Resource connectionVariable = g.newResource(); + g.claim(connectionVariable, mu.b.InstanceOf, mu.sr.ConnectionVariable); + g.claim(connectionVariable, mu.sr.Binds, sr.IsHeadOfTerminal); + g.claim(connectionVariable, mu.sr.IsParameterOf, sr.ModuleSymbol); + g.claim(terminal, mu.dr.HasConnectionVariable, connectionVariable); + + + Resource terminal2 = g.newResource(); + g.claim(terminal2, mu.b.InstanceOf, sr.SysdynTerminal); + Resource connectionVariable2 = g.newResource(); + g.claim(connectionVariable2, mu.b.InstanceOf, mu.sr.ConnectionVariable); + g.claim(connectionVariable2, mu.sr.Binds, sr.IsTailOfTerminal); + g.claim(connectionVariable2, mu.sr.IsParameterOf, sr.ModuleSymbol); + g.claim(terminal2, mu.dr.HasConnectionVariable, connectionVariable2); + + g.claim(moduleSymbol, mu.sr.IsDefinedBy, OrderedSetUtils.create(g, mu.sr.Composite, terminal, terminal2)); + + + } + }); + return null; + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RemoveHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RemoveHandler.java new file mode 100644 index 00000000..b5edcc2c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RemoveHandler.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.event.IEvent; +import org.simantics.h2d.event.handler.Delete; + +public class RemoveHandler extends DiagramContextMenuActionHandler { + + protected void handleEvent(IDiagramEditor editor, IEvent event) { + Delete d = new Delete(); + d.handle(editor, event); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RemoveNodeHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RemoveNodeHandler.java new file mode 100644 index 00000000..2ac9756a --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RemoveNodeHandler.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.CancelTransactionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.RemoverUtil; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.utils.ResourceAdaptionUtils; +import org.simantics.utils.ui.ExceptionUtils; + +/** + * @author Tuukka Lehtonen + */ +public class RemoveNodeHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + Shell shell = HandlerUtil.getActiveShellChecked(event); + ISelection sel = HandlerUtil.getCurrentSelection(event); + Resource[] resources = ResourceAdaptionUtils.toResources(sel); + if (resources.length == 0) + return null; + + MessageDialog dialog = new MessageDialog(shell, "Remove Item", null, "Are you sure?", 0, + new String[] { "OK", "Cancel" }, 0); + dialog.create(); + if (dialog.open() == 0) + deleteItem(resources); + + return null; + } + + private void deleteItem(final Resource[] resources) { + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException, CancelTransactionException { + for (Resource r : resources) + RemoverUtil.remove(graph, r); + } + }); + } catch (DatabaseException e) { + ExceptionUtils.logAndShowError(e); + } + } + +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RenameHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RenameHandler.java new file mode 100644 index 00000000..a187806f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RenameHandler.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.simantics.h2d.editor.IDiagramEditor; +import org.simantics.h2d.element.IElement; +import org.simantics.h2d.event.IEvent; +import org.simantics.h2d.event.ILocatableEvent; +import org.simantics.sysdyn.ui.elements.TextElement; + +public class RenameHandler extends DiagramContextMenuActionHandler { + + protected void handleEvent(IDiagramEditor editor, IEvent event) { + ILocatableEvent e = (ILocatableEvent)event; + if(e.getPickedElements().size() <= 0) return; + IElement element = e.getPickedElements().get(0); + if(element instanceof TextElement) { + TextElement te = (TextElement)element; + te.beginRenameAction(editor); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RenameNodeHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RenameNodeHandler.java new file mode 100644 index 00000000..7e836b52 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RenameNodeHandler.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.browsing.ui.GraphExplorer; +import org.simantics.browsing.ui.NodeContext; +import org.simantics.browsing.ui.common.ColumnKeys; +import org.simantics.utils.ui.ISelectionUtils; + +public class RenameNodeHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection sel = HandlerUtil.getCurrentSelection(event); + NodeContext ctx = ISelectionUtils.filterSingleSelection(sel, NodeContext.class); + if (ctx == null) + return null; + + IWorkbenchPart part = HandlerUtil.getActivePart(event); + if (part == null) + return null; + + GraphExplorer graphExplorer = (GraphExplorer) part.getAdapter(GraphExplorer.class); + if (graphExplorer != null) + graphExplorer.startEditing(ctx, ColumnKeys.SINGLE); + + return null; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RunBasicExperiment.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RunBasicExperiment.java new file mode 100644 index 00000000..8b81ffc1 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/RunBasicExperiment.java @@ -0,0 +1,47 @@ +package org.simantics.sysdyn.ui.handlers; + + +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.commands.IElementUpdater; +import org.eclipse.ui.menus.UIElement; +import org.simantics.simulation.experiment.IDynamicExperiment; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.sysdyn.ui.actions.ToggleSimulation; +import org.simantics.ui.SimanticsUI; + +public class RunBasicExperiment extends AbstractHandler implements IElementUpdater { + + public static final String COMMAND = "org.simantics.sysdyn.ui.run"; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IExperimentManager manager = + SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); + IExperiment experiment = manager.getActiveExperiment(); + if(experiment instanceof IDynamicExperiment) + ((IDynamicExperiment)experiment).simulate(true); + return null; + } + + @SuppressWarnings("unchecked") + @Override + public void updateElement(UIElement element, Map parameters) { + ICommandService commandService = + (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = commandService.getCommand(ToggleSimulation.COMMAND); + boolean checked = (Boolean) command.getState(ToggleSimulation.STATE).getValue(); + if(checked) + this.setBaseEnabled(false); + else + this.setBaseEnabled(true); + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/SaveResultsHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/SaveResultsHandler.java new file mode 100644 index 00000000..9d7beedf --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/SaveResultsHandler.java @@ -0,0 +1,24 @@ +package org.simantics.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.simantics.simulation.experiment.IDynamicExperiment; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.ui.SimanticsUI; + +public class SaveResultsHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IExperimentManager manager = + SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); + IExperiment experiment = manager.getActiveExperiment(); + if(experiment instanceof IDynamicExperiment) { + ((IDynamicExperiment)experiment).saveState(); + } + return null; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ShowModuleHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ShowModuleHandler.java new file mode 100644 index 00000000..eff51ec0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ShowModuleHandler.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.ResourceArray; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.modeling.ComponentUtils; +import org.simantics.modeling.ModelingResources; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.structural2.StructuralVariables; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.editor.DiagramViewer; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.utils.ResourceAdaptionUtils; +import org.simantics.ui.workbench.ResourceEditorInput2; +import org.simantics.utils.ui.workbench.WorkbenchUtils; + +/** + * Style Edit + * + * TODO : should we have extension point for expanding styles? + * TODO : default ColorChooser is not suitable for this task + * TODO : how to store MetricsFormat template list + * + * @author Marko Luukkainen + * + */ +public class ShowModuleHandler extends AbstractHandler { + + private static final String EDITOR_ID = "org.simantics.sysdyn.ui.diagramViewer"; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + + ISelection s = HandlerUtil.getCurrentSelectionChecked(event); + final Resource resources[] = ResourceAdaptionUtils.toResources(s); + final DiagramViewer viewer = (DiagramViewer)HandlerUtil.getActiveEditor(event); + + SimanticsUI.getSession().asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + + DiagramResource dr = DiagramResource.getInstance(graph); + Resource runtime = viewer.getRuntime(); + String uri = graph.getPossibleRelatedValue(runtime, dr.HasVariable, StringBindingDefault.INSTANCE); + String currentRVI = graph.getPossibleRelatedValue(runtime, dr.HasRVI, StringBindingDefault.INSTANCE); + Variable variable = Variables.getVariable(graph, uri); + Resource model = Variables.getModel(graph, variable); + final String modelURI = graph.getURI(model); + + for(Resource element : resources) { + + Builtins b = graph.getBuiltins(); + ModelingResources mr = ModelingResources.getInstance(graph); + SysdynResource sr = SysdynResource.getInstance(graph); + StructuralResource2 st = StructuralResource2.getInstance(graph); + + final Resource component = graph.getPossibleObject(element, mr.ElementToComponent); + final Resource componentType = graph.getPossibleType(component, sr.Module); + final Resource configuration = graph.getPossibleObject(componentType, st.IsDefinedBy); + final Resource diagram = ComponentUtils.getPossibleCompositeDiagram(graph, configuration); + + if(diagram == null) return; + + final String rvi = currentRVI + "/" + graph.getPossibleRelatedValue(component, b.HasName, StringBindingDefault.INSTANCE); + if(rvi == null) return; + + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + // for (Triple in : ins) { + try { + String editorId = EDITOR_ID; + System.out.println("Activating diagram: model=" + modelURI + " rvi='" + rvi + "'"); + WorkbenchUtils.openEditor(editorId, new ResourceEditorInput2(editorId, diagram, modelURI, rvi)); + } catch (PartInitException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // } + } + }); + + } + + } + }); + + return null; + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/SysdynExperimentActivator.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/SysdynExperimentActivator.java new file mode 100644 index 00000000..85823f83 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/SysdynExperimentActivator.java @@ -0,0 +1,172 @@ +package org.simantics.sysdyn.ui.handlers; + +import java.util.concurrent.Semaphore; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.exception.AdaptionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.message.MessageService; +import org.simantics.project.IExperimentDescriptor; +import org.simantics.project.IModelDescriptor; +import org.simantics.project.IProject; +import org.simantics.project.IProjectElement; +import org.simantics.project.ProjectKeys; +import org.simantics.project.exception.ProjectException; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.simulation.model.ExperimentLoadingFailed; +import org.simantics.simulation.project.IExperimentActivationListener; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.sysdyn.ui.listeners.SysdynExperimentManagerListener; +import org.simantics.utils.DataContainer; +import org.simantics.utils.ui.ErrorLogger; +import org.simantics.utils.ui.ExceptionUtils; +import org.simantics.utils.ui.dialogs.ShowMessage; + +public class SysdynExperimentActivator { + /** + * @param project + * @param experimentManager + * @param experiment + */ + public static void scheduleActivation(RequestProcessor processor, final IProject project, final IExperimentManager experimentManager, final Resource experiment) { + String jobName = "Activate Experiment"; + String experimentName = getName(processor, experiment); + if (experimentName != null) + jobName += " '" + experimentName + "'"; + /* + // Shut down the previous active experiment + IExperiment activeExperiment = experimentManager.getActiveExperiment(); + if (experiment != null) + activeExperiment.shutdown(); + */ + // Activate a new experiment + scheduleActivation(jobName, project, experimentManager, experiment); + } + + /** + * @param project + * @param experimentManager + * @param experiment + */ + public static void scheduleActivation(String jobName, final IProject project, final IExperimentManager experimentManager, final Resource experiment) { + new Job(jobName) { + @Override + protected IStatus run(final IProgressMonitor monitor) { + return SysdynExperimentActivator.activate(monitor, project, experimentManager, experiment); + } + }.schedule(); + } + + public static IStatus activate(IProgressMonitor monitor, IProject project, IExperimentManager experimentManager, Resource experiment) { + return new SysdynExperimentActivator().activateExperiment(monitor, project, experimentManager, experiment); + } + + private static String getName(RequestProcessor processor, final Resource resource) { + try { + return processor.syncRequest(new Read() { + @Override + public String perform(ReadGraph graph) throws DatabaseException { + try { + return graph.adapt(resource, String.class); + } catch (AdaptionException e) { + return GraphUtils.getReadableName(graph, resource); + } + } + }); + } catch (DatabaseException e) { + ErrorLogger.defaultLogWarning(e); + return null; + } + } + + private IStatus activateExperiment(final IProgressMonitor monitor, final IProject project, final IExperimentManager manager, final Resource experimentResource) { + monitor.beginTask("Activating experiment", IProgressMonitor.UNKNOWN); + try { + SysdynExperimentManagerListener.listenManager(manager); + IExperiment experiment = manager.getActiveExperiment(); + if(experiment != null) { + experiment.shutdown(); + } + final Semaphore activated = new Semaphore(0); + final DataContainer problem = new DataContainer(); + manager.startExperiment(experimentResource, new IExperimentActivationListener() { + + @Override + public void onExperimentActivated(final IExperiment experiment) { + + MessageService.defaultLog(new org.eclipse.core.runtime.Status(IStatus.INFO, "org.simantics.simulation.ui", 0, "Activated experiment " + experiment.getIdentifier() , null)); + + + activated.release(); + // Set the selected experiment into the the model descriptor. + new Thread("Set Selected Experiment") { + @Override + public void run() { + setSelectedExperiment(project, experimentResource); + } + }.start(); + } + @Override + public void onFailure(Throwable e) { + problem.set(e); + activated.release(); + } + @Override + public void onMessage(IStatus message) { + MessageService.getDefault().log(message); + /*ILogger logger = MessageService.getDefault(); + MultiStatus init = new MultiStatus(Activator.PLUGIN_ID, 0, "Activating experiment", null); + for (String msg : messages) { + init.add(new Status(IStatus.INFO, Activator.PLUGIN_ID, msg)); + } + logger.log(init);*/ + } + }, true); + try { + activated.acquire(); + Throwable t = problem.get(); + if (t != null) { + if (t instanceof ExperimentLoadingFailed) { + ErrorLogger.defaultLogError(t); + ShowMessage.showError("Experiment Activation Failed", t.getMessage()); + } else { + ExceptionUtils.logAndShowError(t); + } + } + + return Status.OK_STATUS; + //return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Experiment activation failed, see exception for details.", problem.get()); + } catch (InterruptedException e) { + return Status.CANCEL_STATUS; + } + } finally { + monitor.done(); + } + } + + private void setSelectedExperiment(IProject project, Resource experiment) { + try { + for (IProjectElement model : project.members()) { + if (model instanceof IModelDescriptor) { + for (IProjectElement member : ((IModelDescriptor) model).members()) { + if (member instanceof IExperimentDescriptor && experiment.equals(member.get())) { + model.setHint(ProjectKeys.KEY_SELECTED_EXPERIMENT, member); + project.setHint(ProjectKeys.KEY_SELECTED_UI_EXPERIMENT, member); + break; + } + } + } + } + } catch (ProjectException e) { + ErrorLogger.defaultLogError(e); + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ToggleResultActivation.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ToggleResultActivation.java new file mode 100644 index 00000000..3a470de0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ToggleResultActivation.java @@ -0,0 +1,55 @@ +package org.simantics.sysdyn.ui.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.utils.ResourceAdaptionUtils; + +public class ToggleResultActivation extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection sel = HandlerUtil.getCurrentSelection(event); + Resource[] resources = ResourceAdaptionUtils.toResources(sel); + if (resources.length == 0) + return null; + + toggleActivation(resources); + + return null; + } + + private void toggleActivation(final Resource[] resources) { + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + for(Resource r : resources) { + if(graph.isInstanceOf(r, sr.Result)) { + if (graph.hasStatement(r, b.IsActive)) { + graph.denyStatement(r, b.IsActive, r); + } else { + graph.claim(r, b.IsActive, r); + } + } + } + } + + }); + } catch (DatabaseException e) { + + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/UnlinkNodeHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/UnlinkNodeHandler.java new file mode 100644 index 00000000..171007aa --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/UnlinkNodeHandler.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * 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.sysdyn.ui.handlers; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.CancelTransactionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.editor.SysdynDiagramEditor; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.utils.ResourceAdaptionUtils; +import org.simantics.utils.ui.ExceptionUtils; + +/** + * @author Tuukka Lehtonen + */ +public class UnlinkNodeHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + Shell shell = HandlerUtil.getActiveShellChecked(event); + ISelection sel = HandlerUtil.getCurrentSelection(event); + Resource[] resources = ResourceAdaptionUtils.toResources(sel); + if (resources.length == 0) + return null; + + MessageDialog dialog = new MessageDialog(shell, "Remove Item", null, "Are you sure?", 0, + new String[] { "OK", "Cancel" }, 0); + dialog.create(); + if (dialog.open() == 0) + deleteItem(resources); + + return null; + } + + private void deleteItem(final Resource[] resources) { + final ArrayList configurations = new ArrayList(); + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException, CancelTransactionException { + SysdynResource sr = SysdynResource.getInstance(graph); + for (Resource r : resources) { + if (graph.isInstanceOf(r, sr.SysdynModel)) { + unlinkModel(graph, r); + configurations.add(graph.getSingleObject(r, graph.getBuiltins().HasConfiguration)); + } + else if (graph.isInstanceOf(r, graph.getBuiltins().Experiment)) + unlinkExperiment(graph, r); + else if (graph.isInstanceOf(r, sr.Result)) + unlinkResult(graph, r); + } + } + }); + } catch (DatabaseException e) { + ExceptionUtils.logAndShowError(e); + } + + for (Resource r : configurations) { + IEditorReference[] editorReferences = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences(); + for(IEditorReference er : editorReferences) { + if(er.getEditor(false) instanceof SysdynDiagramEditor) { + SysdynDiagramEditor editor = (SysdynDiagramEditor)er.getEditor(false); + if(editor.getResourceInput().getResource().equals(r)) { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeEditor(editor, false); + } + } + } + } + + } + + private void unlinkModel(WriteGraph graph, Resource model) throws DatabaseException { + Builtins b = graph.getBuiltins(); + + for(Resource r : graph.getObjects(model, b.ConsistsOf)) + if(graph.isInstanceOf(r, SysdynResource.getInstance(graph).Result)) + deleteResultFiles(graph, r); + + graph.deny(model, b.PartOf); + } + + private void unlinkExperiment(WriteGraph graph, Resource experiment) throws DatabaseException { + Builtins b = graph.getBuiltins(); + Collection results = graph.getObjects(experiment, SysdynResource.getInstance(graph).HasResult); + if(results != null) + for(Resource result : results) + unlinkResult(graph, result); + graph.deny(experiment, b.PartOf); + + } + + private void unlinkResult(WriteGraph graph, Resource result) throws DatabaseException { + Builtins b = graph.getBuiltins(); + deleteResultFiles(graph, result); + graph.deny(result, b.PartOf); + graph.deny(result, graph.getInverse(SysdynResource.getInstance(graph).HasResult)); + + } + + private void deleteResultFiles(WriteGraph graph, Resource result) throws DatabaseException { + String path; + path = graph.getPossibleRelatedValue(result, SysdynResource.getInstance(graph).HasResultFile); + if(path != null) { + File file = new File(path); + file.delete(); + File parent = file.getParentFile(); + if(parent.listFiles().length == 0) + parent.delete(); + } + } + +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynExperimentListener.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynExperimentListener.java new file mode 100644 index 00000000..bd81f37a --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynExperimentListener.java @@ -0,0 +1,40 @@ +package org.simantics.sysdyn.ui.listeners; + +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.State; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.contexts.IContextActivation; +import org.simantics.simulation.experiment.ExperimentState; +import org.simantics.simulation.experiment.IExperimentListener; +import org.simantics.sysdyn.ui.actions.ToggleSimulation; +import org.simantics.sysdyn.ui.handlers.RunBasicExperiment; + +public class SysdynExperimentListener implements IExperimentListener { + + IContextActivation contextActivation; + + @Override + public void stateChanged(final ExperimentState state) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + ICommandService commandService = + (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = commandService.getCommand(ToggleSimulation.COMMAND); + State buttonState = command.getState(ToggleSimulation.STATE); + + switch(state) { + case DISPOSED: + buttonState.setValue(false); + break; + } + commandService.refreshElements(command.getId(), null); + commandService.refreshElements(RunBasicExperiment.COMMAND, null); + } + + }); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynExperimentManagerListener.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynExperimentManagerListener.java new file mode 100644 index 00000000..5c385fd3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynExperimentManagerListener.java @@ -0,0 +1,96 @@ +package org.simantics.sysdyn.ui.listeners; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.contexts.IContextActivation; +import org.eclipse.ui.contexts.IContextService; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.simulation.project.IExperimentManagerListener; + +public class SysdynExperimentManagerListener implements IExperimentManagerListener{ + + public static final String BASIC_EXPERIMENT_CONTEXT = "org.simantics.sysdyn.ui.basicExperiment"; + + static Set managers = + new HashSet(); + + IExperimentManager manager; + + Collection contextActivations = + new ArrayList(); + + public SysdynExperimentManagerListener(IExperimentManager manager) { + this.manager = manager; + } + + public static void listenManager(IExperimentManager manager) { + synchronized(managers) { + if(managers.contains(manager)) + return; + SysdynExperimentManagerListener listener = + new SysdynExperimentManagerListener(manager); + manager.addListener(listener); + managers.add(manager); + } + } + + @Override + public void activeExperimentLoaded(final IExperiment experiment) { + experiment.addListener(new SysdynExperimentListener()); + + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + IContextService contextService = + (IContextService)PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getService(IContextService.class); + synchronized(contextActivations) { + contextActivations.add(contextService.activateContext(BASIC_EXPERIMENT_CONTEXT)); + } + } + + }); + } + + @Override + public void activeExperimentUnloaded() { + + synchronized(contextActivations) { + final Collection oldContextActivations = + contextActivations; + + contextActivations = new ArrayList(); + + final IWorkbench workbench = PlatformUI.getWorkbench(); + workbench.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if (workbench.isClosing()) + return; + + IContextService contextService = + (IContextService)workbench.getActiveWorkbenchWindow().getService(IContextService.class); + contextService.deactivateContexts(oldContextActivations); + } + + }); + } + + } + + @Override + public void managerDisposed() { + synchronized(managers) { + managers.remove(manager); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/ModelicaSourceViewerConfiguration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/ModelicaSourceViewerConfiguration.java new file mode 100644 index 00000000..c27ebaa0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/ModelicaSourceViewerConfiguration.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * 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.sysdyn.ui.modelica; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; + +public class ModelicaSourceViewerConfiguration extends SourceViewerConfiguration { + + public IPresentationReconciler getPresentationReconciler( + ISourceViewer sourceViewer) { + PresentationReconciler pr = new PresentationReconciler(); + DefaultDamagerRepairer ddr = new DefaultDamagerRepairer( + new RuleBasedScanner() { + { + setRules(new IRule[] {new IRule() { + + @Override + public IToken evaluate(ICharacterScanner scanner) { + int ch; + try { + scanner.unread(); + ch = scanner.read(); + } catch (Throwable t) { + ch = -1; + } + if (ch <= 0 || !isIdentifierChar((char) ch)) { + ch = scanner.read(); + if(isIdentifierChar((char)ch)) { + StringBuilder b = new StringBuilder(); + do { + b.append((char)ch); + ch = scanner.read(); + } while(isIdentifierChar((char) ch)); + String str = b.toString(); + if(keywords.contains(str)) + return getModelicaKeywordToken(); + } + scanner.unread(); + } + return Token.UNDEFINED; + } + + }}); + } + } + ); + pr.setRepairer(ddr, IDocument.DEFAULT_CONTENT_TYPE); + pr.setDamager(ddr, IDocument.DEFAULT_CONTENT_TYPE); + return pr; + } + + static boolean isIdentifierChar(char c) { + return + (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') || c == '_'; + } + + static final Set keywords = new HashSet(); + + static { + keywords.add("within"); + keywords.add("final"); + keywords.add("public"); + keywords.add("protected"); + keywords.add("connect"); + keywords.add("when"); + keywords.add("then"); + keywords.add("elsewhen"); + keywords.add("if"); + keywords.add("end"); + keywords.add("elseif"); + keywords.add("else"); + keywords.add("for"); + keywords.add("while"); + keywords.add("loop"); + keywords.add("der"); + keywords.add("enumeration"); + keywords.add("extends"); + keywords.add("class"); + keywords.add("partial"); + keywords.add("encapsulated"); + keywords.add("model"); + keywords.add("record"); + keywords.add("block"); + keywords.add("expandable"); + keywords.add("connector"); + keywords.add("type"); + keywords.add("package"); + keywords.add("function"); + keywords.add("import"); + keywords.add("external"); + keywords.add("constrainedby"); + keywords.add("redeclare"); + keywords.add("replaceable"); + keywords.add("flow"); + keywords.add("discrete"); + keywords.add("parameter"); + keywords.add("constant"); + keywords.add("input"); + keywords.add("output"); + keywords.add("annotation"); + keywords.add("false"); + keywords.add("true"); + keywords.add("each"); + keywords.add("initial"); + keywords.add("algorithm"); + keywords.add("equation"); + keywords.add("or"); + keywords.add("and"); + keywords.add("not"); + keywords.add("break"); + keywords.add("return"); + } + + static IToken modelicaKeywordToken = null; + public IToken getModelicaKeywordToken() { + if(modelicaKeywordToken == null) { + modelicaKeywordToken = + new Token( + new TextAttribute( + new Color(null, 127, 0, 85), + new Color(null, 255, 255, 255), + SWT.BOLD + )); + } + return modelicaKeywordToken; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/SysdynModelicaEditor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/SysdynModelicaEditor.java new file mode 100644 index 00000000..6547280e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/SysdynModelicaEditor.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * 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.sysdyn.ui.modelica; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.PaintManager; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.AnnotationPainter; +import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.MatchingCharacterPainter; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.texteditor.AbstractDocumentProvider; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.modelica.ModelicaWriter; +import org.simantics.sysdyn.representation.Configuration; +import org.simantics.sysdyn.representation.LoadRepresentation; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.workbench.ResourceEditorInput; + + +public class SysdynModelicaEditor extends TextEditor { + + AnnotationModel annotationModel = new AnnotationModel(); + AnnotationPainter apainter; + + public SysdynModelicaEditor() { + super(); + showOverviewRuler(); + setDocumentProvider(new AbstractDocumentProvider() { + + @Override + protected IAnnotationModel createAnnotationModel(Object element) + throws CoreException { + return annotationModel; + } + + @Override + protected IDocument createDocument(Object element) + throws CoreException { + try { + Configuration configuration = + LoadRepresentation.loadConfiguration(SimanticsUI.getSession(), ((ResourceEditorInput)element).getResource()); + ModelicaWriter writer = new ModelicaWriter(); + writer.write(configuration); + + return new Document(writer.toString()); + } catch (DatabaseException e) { + e.printStackTrace(); + throw new CoreException(STATUS_ERROR); + } + } + + @Override + protected void doSaveDocument(IProgressMonitor monitor, + Object element, IDocument document, boolean overwrite) + throws CoreException { + } + + @Override + protected IRunnableContext getOperationRunner( + IProgressMonitor monitor) { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + } + + @Override + public boolean isModifiable(Object element) { + return false; + } + + @Override + public boolean isReadOnly(Object element) { + return true; + } + + }); + + setSourceViewerConfiguration(new ModelicaSourceViewerConfiguration()); + + } + + @Override + protected void createActions() { + super.createActions(); + + PaintManager paintManager = new PaintManager(getSourceViewer()); + MatchingCharacterPainter matchingCharacterPainter = new MatchingCharacterPainter(getSourceViewer(), + new DefaultCharacterPairMatcher( new char[] {'(', ')', '{', '}', '[', ']'} )); + matchingCharacterPainter.setColor(new Color(Display.getCurrent(), new RGB(160, 160, 160))); + paintManager.addPainter(matchingCharacterPainter); + } + + +} + diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/TextEditorActionBarContributor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/TextEditorActionBarContributor.java new file mode 100644 index 00000000..9c090cf0 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/modelica/TextEditorActionBarContributor.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.sysdyn.ui.modelica; + +import org.eclipse.ui.part.EditorActionBarContributor; + +public class TextEditorActionBarContributor extends EditorActionBarContributor { + + public TextEditorActionBarContributor() { + // TODO Auto-generated constructor stub + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/DefaultRealizationVirtualGraph.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/DefaultRealizationVirtualGraph.java new file mode 100644 index 00000000..7a07c88c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/DefaultRealizationVirtualGraph.java @@ -0,0 +1,34 @@ +package org.simantics.sysdyn.ui.project; + +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.VirtualGraphContext; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.RealizationVirtualGraph; +import org.simantics.db.layer0.adapter.ResourceData; +import org.simantics.sysdyn.SysdynResource; + +public class DefaultRealizationVirtualGraph extends RealizationVirtualGraph { + + public DefaultRealizationVirtualGraph(Session session, Resource model) throws DatabaseException { + super(session, model, SysdynResource.getInstance(session).DefaultRealization); + } + + @Override + public void initialize(final VirtualGraphContext context, WriteGraph graph) throws DatabaseException { + + Resource configuration = graph.getPossibleObject(model, b.HasConfiguration); + + Resource defaultsResource = graph.newResource(); + int modelNode = context.getIndex(model); + int defaultsNode = context.getIndex(defaultsResource); + graph.claim(model, b.ConsistsOf, null, defaultsResource); + graph.claim(model, b.HasBaseRealization, null, defaultsResource); + + undiscovered.put(defaultsNode, new ResourceData(modelNode, configuration, b.Realization, "BaseRealization", null, null)); + + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/DefaultVariable.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/DefaultVariable.java new file mode 100644 index 00000000..909cab6d --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/DefaultVariable.java @@ -0,0 +1,55 @@ +package org.simantics.sysdyn.ui.project; + +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.java.DoubleBindingDefault; +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.ResourceVariable; +import org.simantics.sysdyn.SysdynResource; + +public class DefaultVariable extends ResourceVariable { + + public DefaultVariable(Resource resource) { + super(resource); + } + + @Override + public T getValue(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + Resource represents = graph.getPossibleObject(resource, b.Represents); + if(represents == null) return null; + Resource expression = graph.getPossibleObject(represents, sr.HasExpression); + if(expression == null) return null; + if(!graph.isInstanceOf(expression, sr.ParameterExpression)) return null; + String text = graph.getPossibleRelatedValue(expression, sr.HasEquation); + if(text == null) return null; + Double value = Double.parseDouble(text); + return (T)value; + } + + @Override + public T getValue(ReadGraph graph, Binding binding) throws DatabaseException { + if(!DoubleBindingDefault.INSTANCE.equals(binding)) return null; + return getValue(graph); + } + + @Override + public void setValue(WriteGraph graph, Object object, Binding binding) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + if(!DoubleBindingDefault.INSTANCE.equals(binding)) return; + Resource represents = graph.getPossibleObject(resource, b.Represents); + if(represents == null) return; + Resource expression = graph.getPossibleObject(represents, sr.HasExpression); + if(expression == null) return; + if(!graph.isInstanceOf(expression, sr.ParameterExpression)) return; + Double value = (Double)object; + graph.claimValue(expression, sr.HasEquation, value.toString(), StringBindingDefault.INSTANCE); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/HistoryRealizationVirtualGraph.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/HistoryRealizationVirtualGraph.java new file mode 100644 index 00000000..aa398eea --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/HistoryRealizationVirtualGraph.java @@ -0,0 +1,110 @@ +package org.simantics.sysdyn.ui.project; + +import java.util.Collection; +import java.util.HashSet; + +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.VirtualGraph; +import org.simantics.db.VirtualGraphContext; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.procedure.single.SingleSetSyncListener; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.adapter.RealizationVirtualGraph; +import org.simantics.db.layer0.adapter.ResourceData; +import org.simantics.db.layer0.adapter.RuntimeValuations; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; + +public class HistoryRealizationVirtualGraph extends RealizationVirtualGraph { + + public HistoryRealizationVirtualGraph(Session session, Resource model) throws DatabaseException { + super(session, model, SysdynResource.getInstance(session).HistoryRealization); + } + + @Override + public void initialize(final VirtualGraphContext context, WriteGraph graph) throws DatabaseException { + + graph.asyncRequest(new Read>() { + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { +// System.out.println("Compute runs starts"); + HashSet result = new HashSet(); + Builtins b = graph.getBuiltins(); + for(Resource config : graph.getObjects(model, b.ConsistsOf)) { + if(graph.isInstanceOf(config, b.Experiment)) { + for(Resource run : graph.getObjects(config, b.ConsistsOf)) { + if(graph.isInstanceOf(run, b.Run)) { +// System.out.println("found run " + run); + result.add(run); + } + } + } + } +// System.out.println("Compute runs ends"); + return result; + } + + }, new SingleSetSyncListener() { + + @Override + public void add(ReadGraph graph, final Resource run) throws DatabaseException { + + final String experimentName = graph.getPossibleRelatedValue(run, b.HasName, StringBindingDefault.INSTANCE); + +// System.out.println("RealizationVirtualGraph new experiment " + experimentName); + + RuntimeValuations vs = graph.getService(RuntimeValuations.class); + if(vs.supports(experimentName)) { + +// System.out.println("RealizationVirtualGraph scheduling " + experimentName); + + graph.getSession().asyncRequest(new WriteRequest(graph.getService(VirtualGraph.class)) { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + +// System.out.println("RealizationVirtualGraph about to serve " + experimentName); + + int runNode = context.getIndex(run); + + Resource configuration = graph.getPossibleObject(model, b.HasConfiguration); + for(Resource part : graph.getObjects(configuration, b.ConsistsOf)) { + String partName = graph.getPossibleRelatedValue(part, b.HasName, StringBindingDefault.INSTANCE); + if(partName != null) { + Resource partResource = graph.newResource(); + int partNode = context.getIndex(partResource); + graph.claim(run, b.ConsistsOf, null, partResource); + undiscovered.put(partNode, new ResourceData(runNode, part, valuation, partName, experimentName, null)); + } + } + + } + }); + + } + + } + + @Override + public void exception(ReadGraph graph, Throwable throwable) { + throwable.printStackTrace(); + } + + @Override + public boolean isDisposed() { + return false; + } + + }); + + + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/HistoryVariable.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/HistoryVariable.java new file mode 100644 index 00000000..b686274d --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/HistoryVariable.java @@ -0,0 +1,52 @@ +package org.simantics.sysdyn.ui.project; + +import org.simantics.databoard.Accessors; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.accessor.Accessor; +import org.simantics.databoard.accessor.error.AccessorConstructionException; +import org.simantics.databoard.binding.error.RuntimeBindingConstructionException; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.ResourceVariable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.sysdyn.manager.SysdynDataSet; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.manager.SysdynResult; + +public class HistoryVariable extends ResourceVariable { + + public HistoryVariable(Resource resource) { + super(resource); + } + + @Override + public T getInterface(ReadGraph graph, Class clazz) throws DatabaseException { + if(Accessor.class.equals(clazz)) { + + Builtins b = graph.getBuiltins(); + Resource model = Variables.getModel(graph, this); + Resource configuration = graph.getPossibleObject(model, b.HasConfiguration); + SysdynModel sm = SysdynModelManager.getInstance(graph.getSession()).getModel(graph, configuration); + SysdynResult sr = sm.getSysdynResult(); + String rvi = Variables.getRVI(graph, this); + System.out.println("HistoryVariable rvi='" + rvi + "'"); + rvi = rvi.substring(1).replace("/", "."); + SysdynDataSet ds = sr.getDataSet(rvi); + + try { + return (T)Accessors.getAccessor(Bindings.getBindingUnchecked(SysdynDataSet.class), ds); + } catch (RuntimeBindingConstructionException e) { + e.printStackTrace(); + } catch (AccessorConstructionException e) { + e.printStackTrace(); + } + return null; + + } + return super.getInterface(graph, clazz); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java new file mode 100644 index 00000000..15371b07 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * 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.sysdyn.ui.project; + +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; +import org.eclipse.ui.cheatsheets.OpenCheatSheetAction; +import org.eclipse.ui.console.IConsoleConstants; +import org.osgi.service.prefs.BackingStoreException; +import org.simantics.sysdyn.ui.Activator; +import org.simantics.utils.ui.ErrorLogger; + +public class SysdynPerspectiveFactory implements IPerspectiveFactory { + + private static final String CHEATSHEET_ID = "org.simantics.sysdyn.ui.cheatsheet1"; + + private static final String FIRST_SYSDYN_PROJECT = "firstSysdynProject"; + + @Override + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(true); + String editorArea = layout.getEditorArea(); + + IFolderLayout bottom1 = layout.createFolder("bottom1", IPageLayout.BOTTOM, 0.75f, editorArea); + IFolderLayout bottom2 = layout.createFolder("bottom2", IPageLayout.LEFT, 0.4f, "bottom1"); + bottom1.addView("org.simantics.browsing.ui.graph.propertyView"); + bottom1.addView(IConsoleConstants.ID_CONSOLE_VIEW); + bottom2.addView("org.simantics.sysdyn.ui.trend.view"); + bottom2.addView("org.simantics.sysdyn.ui.dependencies.view"); + + IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.25f, editorArea); + left.addView("org.simantics.sysdyn.ui.browser"); + + IFolderLayout right = layout.createFolder("right", IPageLayout.RIGHT, 0.7f, editorArea); + right.addView("org.simantics.diagram.symbollibrary"); + + // Open cheatsheets view on the first time the user creates a sysdyn project + // for a particular workspace. + IEclipsePreferences prefs = new InstanceScope().getNode(Activator.PLUGIN_ID); + boolean firstSysdynProject = prefs.getBoolean(FIRST_SYSDYN_PROJECT, true); + if (firstSysdynProject) { + new OpenCheatSheetAction(CHEATSHEET_ID).run(); + + // Make a note that the user has created a sysdyn project. + try { + prefs.putBoolean(FIRST_SYSDYN_PROJECT, false); + prefs.flush(); + } catch (BackingStoreException e) { + ErrorLogger.defaultLogError(e); + } + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProject.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProject.java new file mode 100644 index 00000000..2b18c8d7 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProject.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * 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.sysdyn.ui.project; + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PartInitException; +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.Queries; +import org.simantics.db.common.utils.OrderedSetUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.service.GraphChangeListenerSupport; +import org.simantics.db.service.LifecycleSupport; +import org.simantics.diagram.DiagramConstants; +import org.simantics.diagram.synchronization.graph.layer.GraphLayer; +import org.simantics.diagram.synchronization.graph.layer.GraphLayerUtil; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.ModelingUtils; +import org.simantics.modeling.services.CaseInsensitiveComponentNamingStrategy2; +import org.simantics.modeling.services.ComponentNamingStrategy; +import org.simantics.modeling.ui.features.EditorNamingService2; +import org.simantics.project.ProjectElementType; +import org.simantics.project.ProjectElements; +import org.simantics.project.ProjectKeys; +import org.simantics.project.exception.ProjectException; +import org.simantics.project.features.AbstractProjectFeature; +import org.simantics.project.features.UIModelManager; +import org.simantics.project.features.UIModelManagerBase; +import org.simantics.project.features.UIModelManagerBase.WriteRunnable; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.workbench.IEditorNamingService; +import org.simantics.ui.workbench.action.ChooseActionRequest; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.ui.workbench.WorkbenchUtils; + +public class SysdynProject extends AbstractProjectFeature { + private static final String DEFAULT_PERSPECTIVE = "org.simantics.sysdyn.ui.perspective"; + + class ModelManager extends UIModelManagerBase { + @Override + public void create(ProjectElementType kind, Shell parentShell, Session session, Resource container, + Callback callback, Callback errorCallback) { + + if (ProjectElements.MODEL.equals(kind)) { + request(session, container, callback, errorCallback, CREATE_MODEL); + return; + } + + super.create(kind, parentShell, session, container, callback, errorCallback); + } + + /** + * + * + * @see org.simantics.project.features.UIModelManager#openEditor(org.simantics.db.Session, java.lang.String) + */ + @Override + public void openEditor(Session session, String uri) throws PartInitException { + try { + Resource resource = session.syncRequest(Queries.resource(uri)); + session.syncRequest(new ChooseActionRequest(null, resource, WorkbenchUtils.getCurrentPerspectiveId())); + } catch (DatabaseException e) { + LifecycleSupport ls = session.getService(LifecycleSupport.class); + throw new PartInitException("Failed to open editor for URI '" + uri + "' with session '" + ls.getSessionReference() + "', see exception for details.", e); + } + } + } + + private final WriteRunnable CREATE_MODEL = new WriteRunnable() { + @Override + public void run(WriteGraph g, Resource library, Callback callback, Callback errorCallback) { + try { + Builtins b = g.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(g); + ModelingResources mr = ModelingResources.getInstance(g); + ModelingUtils mu = new ModelingUtils(g); + + Resource model = g.newResource(); + + String modelName = GraphUtils.findFreshName(g, "Model", library, b.ConsistsOf, "%s%d"); + + g.claimValue(model, b.HasName, modelName); + g.claimValue(model, b.HasLabel, modelName); + g.claim(model, b.InstanceOf, sr.SysdynModel); + g.claim(model, b.PartOf, library); + + Resource diagram = OrderedSetUtils.create(g, sr.ConfigurationDiagram); + GraphLayer l = new GraphLayerUtil(g).createLayer(DiagramConstants.DEFAULT_LAYER_NAME, true); + g.claim(diagram, mu.dr.HasLayer, l.getLayer()); + g.claimValue(diagram, b.HasName, "Diagrammi", StringBindingDefault.INSTANCE); + + + Resource conf = g.newResource(); + g.claimValue(conf, b.HasName, "Configuration"); + g.claim(conf, b.InstanceOf, sr.Configuration); + g.claimValue(conf, sr.HasStartTime, 0.0); + g.claimValue(conf, sr.HasStopTime, 10.0); + + g.claim(conf, mr.CompositeToDiagram, diagram); + g.claim(model, b.HasConfiguration, conf); + + Resource mapping = g.newResource(); + g.claim(mapping, b.InstanceOf, null, mr.DiagramToCompositeMapping); + g.claim(diagram, b.HasTrigger, mapping); + + Resource report = GraphUtils.create2(g, mu.b.Report, mu.b.HasDocumentation, "===Report==="); + + GraphUtils.create2(g, mu.b.Experiment, + mu.b.HasName, "Experiment", + mu.b.HasLabel, "Experiment", + mu.b.HasReportFactory, report, + mu.b.PartOf, model); + + callback.run(model); + } catch(Exception e) { + errorCallback.run(e); + } + } + }; + + ModelManager mm; + + @Override + public void configure() throws ProjectException { + addToCollectionHint(ProjectKeys.PERSPECTIVES, DEFAULT_PERSPECTIVE); + addToCollectionHint(ProjectKeys.OPEN_PERSPECTIVES, DEFAULT_PERSPECTIVE); + getProjectElement().setHint(ProjectKeys.DEFAULT_PERSPECTIVE, DEFAULT_PERSPECTIVE); + + getProjectElement().setHint(IEditorNamingService.KEY_EDITOR_NAMING_SERVICE, new EditorNamingService2()); + + mm = new ModelManager(); + getProjectElement().setHint(UIModelManager.KEY_MODEL_MANAGER, mm); + + // Install naming strategy for model components. + Session session = getProject().getSession(); + GraphChangeListenerSupport changeSupport = session.peekService(GraphChangeListenerSupport.class); + if (changeSupport != null) { + getProjectElement().setHint(ComponentNamingStrategy.PROJECT_KEY, new CaseInsensitiveComponentNamingStrategy2(changeSupport, "%s%d")); + } + } + + @Override + public void deconfigure() throws ProjectException { + if (getProjectElement().getHint(UIModelManager.KEY_MODEL_MANAGER) == mm) + getProjectElement().removeHint(UIModelManager.KEY_MODEL_MANAGER); + mm = null; + + getProjectElement().removeHint(ComponentNamingStrategy.PROJECT_KEY); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProjectLifeCycle.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProjectLifeCycle.java new file mode 100644 index 00000000..7b26b65a --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynProjectLifeCycle.java @@ -0,0 +1,238 @@ +package org.simantics.sysdyn.ui.project; + +import java.io.File; +import java.util.HashMap; + +import org.eclipse.core.runtime.Platform; +import org.simantics.databoard.accessor.Accessor; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.VirtualGraph; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.procedure.single.SingleSetListener; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.ServiceException; +import org.simantics.db.exception.ValidationException; +import org.simantics.db.layer0.adapter.ActivationManager; +import org.simantics.db.layer0.adapter.RuntimeValuations; +import org.simantics.db.layer0.adapter.TrendVariable; +import org.simantics.db.layer0.util.Simantics; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.request.Read; +import org.simantics.db.service.VirtualGraphSupport; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.project.IProject; +import org.simantics.project.IProjectLifeCycle; +import org.simantics.simulation.experiment.IExperiment; +import org.simantics.simulation.project.IExperimentManager; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; + +public class SysdynProjectLifeCycle implements IProjectLifeCycle{ + + public static final Key INITIALIZED = new KeyOf(Boolean.class, "SYSDYN_LIFECYCLE_INITIALIZED"); + + @Override + public void onCreate(WriteGraph g, Resource project) { +// System.out.println("onCreate Sysdyn Project: " + GraphUtils.getReadableName(g, project)); + } + + @Override + public void onDestroy(WriteGraph g, Resource project) { + try { + System.out.println("onDestroy Sysdyn Project: " + GraphUtils.getReadableName(g, project)); + } catch (ValidationException e) { + e.printStackTrace(); + } catch (ServiceException e) { + e.printStackTrace(); + } + } + + @Override + public void onActivated(RequestProcessor processor, final IProject project) { + + System.out.println("onActivated Sysdyn Project"); + + ISessionContext context = SimanticsUI.getSessionContext(); + if (context.getHint(INITIALIZED) == null) { + + try { + + Resource projectResource = project.get(); + + final Session session = context.getSession(); + + session.registerService(RuntimeValuations.class, new RuntimeValuations() { + + @Override + public boolean supports(String valuation) { + + IExperimentManager expMan = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER); + IExperiment experiment = expMan.getExperiment(valuation); + + return experiment != null; + + } + + @Override + public Accessor getAccessor(String variableIdentityPrefix, String valuation, String suffix) { + return null; + } + + @Override + public TrendVariable getVariable(String variableIdentityPrefix, String valuation, String suffix) { + + return null; + + } + + }); + + +// System.out.println("A1"); + + final Builtins b = session.getBuiltins(); + ActivationManager activationManager = session.getService(ActivationManager.class); + if (activationManager != null) { + activationManager.activate(processor, projectResource); + } + +// System.out.println("A2"); + + VirtualGraphSupport support = session.getService(VirtualGraphSupport.class); + final VirtualGraph graph = session.getService(VirtualGraph.class); + +// System.out.println("A3"); + + session.asyncRequest(new ObjectsWithType(projectResource, b.ConsistsOf, b.Model), new SingleSetListener() { + + @Override + public void add(final Resource model) { + // FIXME: + Simantics.async(new Runnable() { + + @Override + public void run() { + try { + // This creates experiment realizations + graph.register(new HistoryRealizationVirtualGraph(session, model)); + // This creates the BaseRealization + graph.register(new DefaultRealizationVirtualGraph(session, model)); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + }); + } + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + @Override + public boolean isDisposed() { + return false; + } + + }); + + support.getWorkspacePersistent("experiments"); + + } catch (DatabaseException e) { + + e.printStackTrace(); + + } + + + cleanProjectFolder(project.get()); + context.setHint(INITIALIZED, Boolean.TRUE); + + } + + } + + @Override + public void onDeactivated(IProject project) { +// System.out.println("onDeactivated Sysdyn Project: " + project.getName()); + } + + public void cleanProjectFolder(final Resource projectResource) { + System.out.println("cleaning up project folder"); + ISessionContext context = SimanticsUI.getSessionContext(); + final Session session = context.getSession(); + String projectName = null; + final HashMap resultPaths = new HashMap(); + try { + projectName = session.syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + for(Resource model : graph.getObjects(projectResource, b.ConsistsOf)) { + if(graph.isInstanceOf(model, sr.SysdynModel)){ + for(Resource experiment : graph.getObjects(model, b.ConsistsOf)) { + if(graph.isInstanceOf(experiment, b.Experiment)) { + for(Resource result : graph.getObjects(experiment, sr.HasResult)) { + String resultFile = (String)graph.getPossibleRelatedValue(result, sr.HasResultFile); + if(result != null) resultPaths.put(resultFile, result); + } + } + } + } + } + return graph.getPossibleRelatedValue(projectResource, b.HasName); + + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + if(projectName != null) { + File root = new File(Platform.getLocation().toOSString(), "www.simantics.org"); + if(!root.isDirectory()) return; + File projectRoot = new File(root, projectName); + if(!projectRoot.isDirectory()) return; + File[] files = projectRoot.listFiles(); + + for(File file : files) { + if(resultPaths.get(file.getAbsolutePath()) == null) { + file.delete(); + } else { + resultPaths.remove(file.getAbsolutePath()); + } + } + + if (!resultPaths.keySet().isEmpty()) { + session.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + for(String key : resultPaths.keySet()) { + Resource result = resultPaths.get(key); + graph.deny(result, b.PartOf); + graph.deny(result, graph.getInverse(SysdynResource.getInstance(graph).HasResult)); + } + } + }) ; + + + } + + + + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ConfigurationTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ConfigurationTab.java new file mode 100644 index 00000000..cc061e97 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ConfigurationTab.java @@ -0,0 +1,86 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.management.ISessionContext; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactory; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier; + +public class ConfigurationTab extends PropertyTabContributorImpl { + + + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + Composite composite = new Composite(body, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(composite); + + Label label = new Label(composite, SWT.NONE); + label.setText("Name"); + + TrackedText name = new TrackedText(composite, support, SWT.BORDER); + name.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasName)); + name.addModifyListener(new StringPropertyModifier(context, Builtins.URIs.HasName)); + name.setInputValidator(new IInputValidator() { + + @Override + public String isValid(String newText) { + if (newText.contains(" ")) + return "Sorry but spaces are not allowed for names right now"; + return null; + } + }); + + GridDataFactory.fillDefaults().hint(200, SWT.DEFAULT).applyTo(name.getWidget()); + + label = new Label(composite, SWT.NONE); + label.setText("Start time"); + + TrackedText startTime = new TrackedText(composite, support, SWT.BORDER | SWT.RIGHT); + startTime.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasStartTime)); + startTime.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasStartTime)); + startTime.setInputValidator(new DoubleValidator()); + GridDataFactory.fillDefaults().hint(200, SWT.DEFAULT).applyTo(startTime.getWidget()); + + label = new Label(composite, SWT.NONE); + label.setText("Stop time"); + + TrackedText stopTime = new TrackedText(composite, support, SWT.BORDER | SWT.RIGHT); + stopTime.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasStopTime)); + stopTime.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasStopTime)); + stopTime.setInputValidator(new DoubleValidator()); + GridDataFactory.fillDefaults().hint(200, SWT.DEFAULT).applyTo(stopTime.getWidget()); + + + } + + private class DoubleValidator implements IInputValidator { + + @Override + public String isValid(String newText) { + for(int i = 0; i < newText.length(); i++){ + if(!Character.isDigit(newText.charAt(i))){ + if(newText.charAt(i) != '.') { + return "Invalid character '" + newText.charAt(i) + "'"; + } else if(newText.indexOf('.') != newText.lastIndexOf('.')) { + return "There can be only one '.'"; + } + } + } + return null; + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/DependencyTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/DependencyTab.java new file mode 100644 index 00000000..30eebee6 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/DependencyTab.java @@ -0,0 +1,30 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.management.ISessionContext; + +public class DependencyTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + Composite composite = new Composite(body, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(6).applyTo(composite); + TrackedText nameText = new TrackedText(composite, support, SWT.BORDER); + nameText.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasName)); + nameText.addModifyListener(new StringPropertyModifier(context, Builtins.URIs.HasName)); + GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText.getWidget()); + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java new file mode 100644 index 00000000..8e43dd3a --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java @@ -0,0 +1,240 @@ +package org.simantics.sysdyn.ui.properties; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier; +import org.simantics.browsing.ui.swt.widgets.TrackedCombo; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.ComboModifyListenerImpl; +import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl; +import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListener; +import org.simantics.browsing.ui.swt.widgets.impl.TrackedModifyEvent; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes; +import org.simantics.sysdyn.ui.properties.widgets.ExpressionWidget; +import org.simantics.sysdyn.ui.properties.widgets.ShortcutTabWidget; +import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes.ExpressionType; + +public class EquationTab extends PropertyTabContributorImpl { + + TrackedCombo expressionTypeCombo, unitCombo; + ShortcutTabWidget shortcutTabWidget; + ExpressionWidget expressionWidget; + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + Composite composite = new Composite(body, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(6).applyTo(composite); + TrackedText nameText = new TrackedText(composite, support, SWT.BORDER); + nameText.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasName)); + nameText.addModifyListener(new StringPropertyModifier(context, Builtins.URIs.HasName)); + GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText.getWidget()); + + + Label label = new Label(composite, SWT.SINGLE ); + label.setText("Type:"); + GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); + + expressionTypeCombo = new TrackedCombo(composite, support, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); + + + label = new Label(composite, SWT.SINGLE ); + label.setText("Unit:"); + GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); + + + unitCombo = new TrackedCombo(composite, support, SWT.DROP_DOWN | SWT.BORDER); + + shortcutTabWidget = new ShortcutTabWidget(composite, support, SWT.NONE); + + + Composite expressionComposite = new Composite(composite, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).span(5, 1).applyTo(expressionComposite); + expressionWidget = new ExpressionWidget(expressionComposite, support, SWT.NONE); + expressionWidget.setVariableTable(shortcutTabWidget.getVariableTable()); + + addListeners(); + } + + private void addListeners() { + + expressionTypeCombo.setItemFactory(new ReadFactoryImpl>() { + + @Override + public Map perform(ReadGraph graph, final Resource input) throws DatabaseException { + + Map map = new HashMap(); + SysdynResource sr = SysdynResource.getInstance(graph); + + final ExpressionType[] expressionTypes; + if(graph.isInstanceOf(input, sr.Auxiliary)) + expressionTypes = ExpressionTypes.auxiliaryExpressions; + else if(graph.isInstanceOf(input, sr.Stock)) + expressionTypes = ExpressionTypes.stockExpressions; + else if(graph.isInstanceOf(input, sr.Valve)) + expressionTypes = ExpressionTypes.valveExpressions; + else + expressionTypes = new ExpressionType[] {}; + + for(ExpressionType et : expressionTypes) { + map.put(et.toString(), et); + } + return map; + } + }); + + expressionTypeCombo.setSelectionFactory(new ReadFactoryImpl() { + + @Override + public String perform(ReadGraph graph, final Resource input) throws DatabaseException { + return ExpressionTypes.getExpressionTypeForVariable(graph, input).toString(); + } + }); + + expressionTypeCombo.addModifyListener(new TextModifyListener() { + + @Override + public void modifyText(TrackedModifyEvent e) { + System.out.println(e.getText()); + expressionWidget.displayExpression(e.getText(), false); + expressionWidget.save(); + } + }); + + + unitCombo.setItemFactory(new ReadFactoryImpl>() { + + @Override + public Map perform(ReadGraph graph, final Resource input) throws DatabaseException { + Map map = new HashMap(); + + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + Resource model = graph.getPossibleObject(input, b.PartOf); + if (model != null) { + Collection variables = graph.getObjects(model, b.ConsistsOf); + for(Resource v : variables) { + Object unit = graph.getPossibleRelatedValue(v, sr.HasUnit); + if (unit != null && !map.keySet().contains((String) unit)) { + map.put((String)unit, (String)unit); + + } + } + } + return map; + } + }); + unitCombo.setSelectionFactory(new ReadFactoryImpl() { + + @Override + public String perform(ReadGraph graph, final Resource input) throws DatabaseException { + String unit = graph.getPossibleRelatedValue(input, SysdynResource.getInstance(graph).HasUnit); + if(unit == null) + return ""; + else + return unit; + } + }); + + unitCombo.addModifyListener(new ComboModifyListenerImpl() { + + @Override + public void applyText(WriteGraph graph, Resource input, String text) throws DatabaseException { + graph.claimValue(input, SysdynResource.getInstance(graph).HasUnit, text); + } + }); + + + shortcutTabWidget.addMouseListener(new MouseListener(){ + + @Override + public void mouseDoubleClick(MouseEvent e) { + Table table = (Table)e.widget; + TableItem item = table.getItem(new Point(e.x, e.y)); + if(item != null) { + final String var = (String)item.getData(); + table.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if(expressionWidget!= null) { + expressionWidget.getExpression().replaceSelection(var); + expressionWidget.getExpression().focus(); + } + } + }); + } + } + + @Override + public void mouseDown(MouseEvent e) { + expressionWidget.getExpression().focus(); + } + + @Override + public void mouseUp(MouseEvent e) { + } + + }); + shortcutTabWidget.addFocusListener(new FocusListener() { + + @Override + public void focusGained(FocusEvent e) { + } + + @Override + public void focusLost(FocusEvent e) { + ((Table)e.widget).deselectAll(); + } + + }); + + expressionWidget.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + expressionWidget.validateFields(); + } + }); + + expressionWidget.addFocusListener(new FocusListener() { + + @Override + public void focusLost(FocusEvent e) { + expressionWidget.save(); + } + + @Override + public void focusGained(FocusEvent e) { + expressionWidget.validateFields(); + } + }); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ExperimentTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ExperimentTab.java new file mode 100644 index 00000000..1db9ef95 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ExperimentTab.java @@ -0,0 +1,16 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.management.ISessionContext; + +public class ExperimentTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/InputVariableTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/InputVariableTab.java new file mode 100644 index 00000000..4cba9abb --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/InputVariableTab.java @@ -0,0 +1,70 @@ +package org.simantics.sysdyn.ui.properties; + + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier; +import org.simantics.browsing.ui.swt.widgets.TrackedCombo; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.management.ISessionContext; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.IsOutputWidget; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactory; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier; + +public class InputVariableTab extends PropertyTabContributorImpl { + + TrackedCombo expressionTypeCombo; + IsOutputWidget isOutput; + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + Composite composite = new Composite(body, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(composite); + + TrackedText nameText = new TrackedText(composite, support, SWT.BORDER); + nameText.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasName)); + nameText.addModifyListener(new StringPropertyModifier(context, Builtins.URIs.HasName)); + GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText.getWidget()); + + isOutput = new IsOutputWidget(composite, support, SWT.NULL); + + Label label = new Label(composite, SWT.NULL); + label.setText("Default Value"); + + TrackedText defaultValue = new TrackedText(composite, support, SWT.RIGHT | SWT.BORDER); + defaultValue.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasDefaultInputValue)); + defaultValue.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasDefaultInputValue)); + defaultValue.setInputValidator(new DoubleValidator()); + GridDataFactory.fillDefaults().grab(true, false).applyTo(defaultValue.getWidget()); + + + } + + private class DoubleValidator implements IInputValidator { + + @Override + public String isValid(String newText) { + for(int i = 0; i < newText.length(); i++){ + if(!Character.isDigit(newText.charAt(i))){ + if(newText.charAt(i) != '.') { + return "Invalid character '" + newText.charAt(i) + "'"; + } else if(newText.indexOf('.') != newText.lastIndexOf('.')) { + return "There can be only one '.'"; + } + } + } + return null; + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/LookupTableTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/LookupTableTab.java new file mode 100644 index 00000000..0fb17cf9 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/LookupTableTab.java @@ -0,0 +1,77 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.management.ISessionContext; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.ChartTableWidget; +import org.simantics.sysdyn.ui.properties.widgets.ChartWidget; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactory; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier; + +public class LookupTableTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + + + Composite baseContainer = new Composite(body, SWT.NONE); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(baseContainer); + GridDataFactory.fillDefaults().grab(true, true).applyTo(baseContainer); + + Composite Ycontainer = new Composite(baseContainer, SWT.NONE); + GridLayoutFactory.fillDefaults().applyTo(Ycontainer); + GridDataFactory.fillDefaults().grab(false, true).applyTo(Ycontainer); + + TrackedText maxYText = new TrackedText(Ycontainer, support, SWT.BORDER); + maxYText.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasMaxY)); + maxYText.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasMaxY)); + + Label l = new Label(Ycontainer, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(false, true).applyTo(l); + + TrackedText minYText = new TrackedText(Ycontainer, support, SWT.BORDER); + minYText.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasMinY)); + minYText.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasMinY)); + + + Composite chartContainer = new Composite(baseContainer, SWT.NONE); + GridLayoutFactory.fillDefaults().numColumns(2).applyTo(chartContainer); + GridDataFactory.fillDefaults().grab(true, true).applyTo(chartContainer); + + @SuppressWarnings("unused") + ChartWidget chartWidget = new ChartWidget(chartContainer, support, SWT.NONE); + + Composite chartTableContainer = new Composite(baseContainer, SWT.NONE); + GridLayoutFactory.fillDefaults().applyTo(chartTableContainer); + GridDataFactory.fillDefaults().grab(false, true).span(1, 2).applyTo(chartTableContainer); + + @SuppressWarnings("unused") + ChartTableWidget chartTableWidget = new ChartTableWidget(chartTableContainer, support, SWT.NONE); + + l = new Label(baseContainer, SWT.NONE); + + Composite Xcontainer = new Composite(baseContainer, SWT.NONE); + GridLayoutFactory.fillDefaults().numColumns(3).applyTo(Xcontainer); + GridDataFactory.fillDefaults().grab(true, false).applyTo(Xcontainer); + + TrackedText minXText = new TrackedText(Xcontainer, support, SWT.BORDER); + minXText.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasMinX)); + minXText.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasMinX)); + + l = new Label(Xcontainer, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(true, false).applyTo(l); + + TrackedText maxXText = new TrackedText(Xcontainer, support, SWT.BORDER); + maxXText.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasMaxX)); + maxXText.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasMaxX)); + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModelTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModelTab.java new file mode 100644 index 00000000..235c34c7 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModelTab.java @@ -0,0 +1,15 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.management.ISessionContext; + +public class ModelTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleInputTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleInputTab.java new file mode 100644 index 00000000..f8fccc79 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleInputTab.java @@ -0,0 +1,78 @@ +package org.simantics.sysdyn.ui.properties; + +import java.util.ArrayList; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.ModuleInputEditingSupport; +import org.simantics.sysdyn.ui.properties.widgets.ReferenceTable; +import org.simantics.sysdyn.ui.properties.widgets.ReferenceRow; +import org.simantics.sysdyn.ui.properties.widgets.RowProvider; +import org.simantics.sysdyn.ui.properties.widgets.ReferenceRowLabelProvider; + +public class ModuleInputTab extends PropertyTabContributorImpl { + + public static final String FIRSTCOLUMN = "Input in Module"; + public static final String SECONDCOLUMN = "Refers to output"; + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + ReferenceTable referenceTable = new ReferenceTable(body, support, SWT.NONE); + + String[] titles = { FIRSTCOLUMN, SECONDCOLUMN}; + int[] bounds = { 100, 100, 100, 100 }; + for (int i = 0; i < titles.length; i++) { + TableViewerColumn column = new TableViewerColumn(referenceTable.getTableViewer(), SWT.NONE); + column.getColumn().setText(titles[i]); + column.getColumn().setWidth(bounds[i]); + column.getColumn().setResizable(true); + column.getColumn().setMoveable(false); + // enable editing support + column.setEditingSupport(new ModuleInputEditingSupport(referenceTable.getTableViewer(), i)); + } + referenceTable.setContentProvider (new ArrayContentProvider()); + referenceTable.setLabelProvider (new ReferenceRowLabelProvider()); + + RowProvider rp = new RowProvider() { + + @Override + public ArrayList getRows(ReadGraph graph, Resource module) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + StructuralResource2 sr2 = StructuralResource2.getInstance(graph); + ArrayList result = new ArrayList(); + Resource instanceOf = graph.getPossibleObject(module, b.InstanceOf); + if(instanceOf == null) return result; + Resource configuration = graph.getSingleObject(instanceOf, sr2.IsDefinedBy); + for(Resource input : graph.syncRequest(new ObjectsWithType(configuration, b.ConsistsOf, sr.Input))) { + Resource dependency = null; + for(Resource dep : graph.getObjects(module, sr.IsHeadOf)) { + Resource refersTo = graph.getPossibleObject(dep, sr.RefersTo); + if(refersTo != null && refersTo.equals(input)) { + dependency = dep; + break; + } + } + ReferenceRow rr = new ReferenceRow(module, dependency, input); + result.add(rr); + } + return result; + } + }; + referenceTable.setRowProvider(rp); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleOutputTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleOutputTab.java new file mode 100644 index 00000000..a12623a4 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleOutputTab.java @@ -0,0 +1,79 @@ +package org.simantics.sysdyn.ui.properties; + +import java.util.ArrayList; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.ModuleOutputEditingSupport; +import org.simantics.sysdyn.ui.properties.widgets.ReferenceRow; +import org.simantics.sysdyn.ui.properties.widgets.ReferenceRowLabelProvider; +import org.simantics.sysdyn.ui.properties.widgets.ReferenceTable; +import org.simantics.sysdyn.ui.properties.widgets.RowProvider; + +public class ModuleOutputTab extends PropertyTabContributorImpl { + + public static final String FIRSTCOLUMN = "Output in module"; + public static final String SECONDCOLUMN = "Referes to input"; + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + ReferenceTable referenceTable = new ReferenceTable(body, support, SWT.NONE); + + String[] titles = { FIRSTCOLUMN, SECONDCOLUMN}; + int[] bounds = { 100, 100, 100, 100 }; + for (int i = 0; i < titles.length; i++) { + TableViewerColumn column = new TableViewerColumn(referenceTable.getTableViewer(), SWT.NONE); + column.getColumn().setText(titles[i]); + column.getColumn().setWidth(bounds[i]); + column.getColumn().setResizable(true); + column.getColumn().setMoveable(false); + // enable editing support + column.setEditingSupport(new ModuleOutputEditingSupport(referenceTable.getTableViewer(), i)); + } + referenceTable.setContentProvider (new ArrayContentProvider()); + referenceTable.setLabelProvider (new ReferenceRowLabelProvider()); + + RowProvider rp = new RowProvider() { + + @Override + public ArrayList getRows(ReadGraph graph, Resource module) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + StructuralResource2 sr2 = StructuralResource2.getInstance(graph); + ArrayList result = new ArrayList(); + Resource instanceOf = graph.getPossibleObject(module, b.InstanceOf); + if(instanceOf == null) return result; + Resource configuration = graph.getSingleObject(instanceOf, sr2.IsDefinedBy); + for(Resource variable : graph.syncRequest(new ObjectsWithType(configuration, b.ConsistsOf, sr.Variable))) { + if(!graph.hasStatement(variable, sr.IsOutput)) continue; + + Resource dependency = null; + for(Resource dep : graph.getObjects(module, sr.IsTailOf)) { + Resource refersTo = graph.getPossibleObject(dep, sr.RefersTo); + if(refersTo != null && refersTo.equals(variable)) { + dependency = dep; + break; + } + } + ReferenceRow rr = new ReferenceRow(module, dependency, variable); + result.add(rr); + } + return result; + } + }; + referenceTable.setRowProvider(rp); + } +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleTab.java new file mode 100644 index 00000000..bcf9047f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleTab.java @@ -0,0 +1,28 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.management.ISessionContext; + +public class ModuleTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + Composite composite = new Composite(body, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(6).applyTo(composite); + TrackedText nameText = new TrackedText(composite, support, SWT.BORDER); + nameText.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasName)); + nameText.addModifyListener(new StringPropertyModifier(context, Builtins.URIs.HasName)); + GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText.getWidget()); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleTypeTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleTypeTab.java new file mode 100644 index 00000000..ef019921 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ModuleTypeTab.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.management.ISessionContext; + +public class ModuleTypeTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + Composite composite = new Composite(body, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(6).applyTo(composite); + TrackedText nameText = new TrackedText(composite, support, SWT.BORDER); + nameText.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasName)); + nameText.addModifyListener(new StringPropertyModifier(context, Builtins.URIs.HasName)); + GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText.getWidget()); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ReferenceDependencyTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ReferenceDependencyTab.java new file mode 100644 index 00000000..56fa1044 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ReferenceDependencyTab.java @@ -0,0 +1,15 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.management.ISessionContext; + +public class ReferenceDependencyTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ResourceSelectionProcessor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ResourceSelectionProcessor.java new file mode 100644 index 00000000..267cae35 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ResourceSelectionProcessor.java @@ -0,0 +1,147 @@ +package org.simantics.sysdyn.ui.properties; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.simantics.browsing.ui.SelectionProcessor; +import org.simantics.browsing.ui.swt.ComparableTabContributor; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; +import org.simantics.db.exception.ServiceException; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.modeling.ModelingResources; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.utils.AdaptionUtils; + +public class ResourceSelectionProcessor implements SelectionProcessor { + + @Override + public Collection process(Object selection, ReadGraph backend) { + Resource r = AdaptionUtils.adaptToSingle(selection, Resource.class); + if(r == null) + return Collections.emptyList(); + + try { + SysdynResource sr = SysdynResource.getInstance(backend); + DiagramResource dr = DiagramResource.getInstance(backend); + ModelingResources mr = ModelingResources.getInstance(backend); + Collection tabs = new ArrayList(); + if (backend.isInstanceOf(r, dr.Element)) { + Resource component = backend.getPossibleObject(r, mr.ElementToComponent); + if (component != null) { + r = component; + } else { + Resource connection = backend.getPossibleObject(r, mr.DiagramConnectionToConnection); + if(connection != null) + r = connection; + } + } + if (backend.isInstanceOf(r, sr.IndependentVariable)) { + Resource expression = backend.getPossibleObject(r, sr.HasExpression); + tabs.add(new ComparableTabContributor( + new EquationTab(), + 2, + r, + "Equation")); + if(expression != null && backend.isInstanceOf(expression, sr.WithLookupExpression)) { + tabs.add(new ComparableTabContributor( + new LookupTableTab(), + 1, + expression, + "Lookup Table")); + } + tabs.add(new ComparableTabContributor( + new VariableInformationTab(), + 0, + r, + "Additional Information")); + return tabs; + } + if (backend.isInstanceOf(r, sr.Input)) { + return Collections.singleton(new ComparableTabContributor( + new InputVariableTab(), + 2, + r, + "Input")); + } + if (backend.isInstanceOf(r, sr.Configuration)) + return Collections.singleton( + new ComparableTabContributor( + new ConfigurationTab(), + 0, + r, + "Configuration Properties")); + if (backend.isInstanceOf(r, sr.Module)){ + tabs.add(new ComparableTabContributor( + new ModuleTab(), + 3, + r, + "Module Properties")); + tabs.add(new ComparableTabContributor( + new ModuleInputTab(), + 2, + r, + "Inputs")); + tabs.add(new ComparableTabContributor( + new ModuleOutputTab(), + 1, + r, + "Outputs")); + return tabs; + } + if (backend.isInstanceOf(r, sr.Experiment)) + return Collections.singleton( + new ComparableTabContributor( + new ExperimentTab(), + 0, + r, + "Experiment Properties")); + if (backend.isInstanceOf(r, sr.SysdynModel)) + return Collections.singleton( + new ComparableTabContributor( + new ModelTab(), + 0, + r, + "Model Properties")); + if (backend.isInstanceOf(r, sr.Result)) + return Collections.singleton( + new ComparableTabContributor( + new ResultTab(), + 0, + r, + "Result Properties")); + if (backend.isInstanceOf(r, sr.Dependency)) + if (backend.hasStatement(r, sr.RefersTo)) + return Collections.singleton( + new ComparableTabContributor( + new ReferenceDependencyTab(), + 0, + r, + "Reference Properties")); + else + return Collections.singleton( + new ComparableTabContributor( + new DependencyTab(), + 0, + r, + "Dependency Properties")); + if (backend.isInheritedFrom(r, sr.ModuleSymbol)) { + r = backend.getPossibleObject(r, mr.SymbolToComponentType); + if(r != null) + return Collections.singleton( + new ComparableTabContributor( + new ModuleTypeTab(), + 0, + r, + "Module Type Properties")); + } + } catch (ServiceException e) { + e.printStackTrace(); + } catch (ManyObjectsForFunctionalRelationException e) { + e.printStackTrace(); + } + return Collections.emptyList(); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ResultTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ResultTab.java new file mode 100644 index 00000000..fc25355f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/ResultTab.java @@ -0,0 +1,15 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.management.ISessionContext; + +public class ResultTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java new file mode 100644 index 00000000..9f3e56f9 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java @@ -0,0 +1,23 @@ +package org.simantics.sysdyn.ui.properties; + +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPartSite; +import org.simantics.browsing.ui.swt.StandardPropertyPage; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.modeling.ModelingUtils; + +public class SysdynPropertyPage extends StandardPropertyPage { + + public SysdynPropertyPage(IWorkbenchPartSite site, Set set) { + super(site, set); + } + + @Override + protected String computeTitle(ReadGraph graph, ISelection selection) throws DatabaseException { + return ModelingUtils.computeTitle(graph, selection, MAX_SELECTION_LENGTH_TO_SHOW, true); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/VariableInformationTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/VariableInformationTab.java new file mode 100644 index 00000000..8a3e3fa8 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/VariableInformationTab.java @@ -0,0 +1,96 @@ +package org.simantics.sysdyn.ui.properties; + +import org.eclipse.jface.dialogs.IInputValidator; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; +import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; +import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier; +import org.simantics.browsing.ui.swt.widgets.TrackedText; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.management.ISessionContext; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.IsOutputWidget; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyFactory; +import org.simantics.sysdyn.ui.properties.widgets.factories.DoublePropertyModifier; + +public class VariableInformationTab extends PropertyTabContributorImpl { + + @Override + public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { + Composite composite = new Composite(body, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); + GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(composite); + + Group informationGroup = new Group(composite, SWT.SHADOW_ETCHED_IN); + informationGroup.setText("Information"); + GridDataFactory.fillDefaults().grab(false, true).applyTo(informationGroup); + GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(informationGroup); + + TrackedText information = new TrackedText(informationGroup, support, SWT.MULTI | SWT.BORDER); + information.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasDescription)); + information.addModifyListener(new StringPropertyModifier(context, Builtins.URIs.HasDescription)); + GridDataFactory.fillDefaults().grab(true, true).applyTo(information.getWidget()); + + Group rangeGroup = new Group(composite, SWT.SHADOW_ETCHED_IN); + rangeGroup.setText("Range"); + GridDataFactory.fillDefaults().applyTo(rangeGroup); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(6).applyTo(rangeGroup); + + Label label = new Label(rangeGroup, SWT.NONE); + label.setText("Start"); + + TrackedText rangeStart = new TrackedText(rangeGroup, support, SWT.RIGHT | SWT.BORDER); + rangeStart.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasRangeStart)); + rangeStart.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasRangeStart)); + rangeStart.setInputValidator(new DoubleValidator()); + GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeStart.getWidget()); + + + label = new Label(rangeGroup, SWT.NONE); + label.setText("End"); + + + TrackedText rangeEnd = new TrackedText(rangeGroup, support, SWT.RIGHT | SWT.BORDER); + rangeEnd.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasRangeEnd)); + rangeEnd.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasRangeEnd)); + rangeEnd.setInputValidator(new DoubleValidator()); + GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeEnd.getWidget()); + + label = new Label(rangeGroup, SWT.NONE); + label.setText("Step"); + + TrackedText rangeStep = new TrackedText(rangeGroup, support, SWT.RIGHT | SWT.BORDER); + rangeStep.setTextFactory(new DoublePropertyFactory(SysdynResource.URIs.HasRangeStep)); + rangeStep.addModifyListener(new DoublePropertyModifier(context, SysdynResource.URIs.HasRangeStep)); + rangeStep.setInputValidator(new DoubleValidator()); + GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeStep.getWidget()); + + new IsOutputWidget(composite, support, SWT.NULL); + + } + + private class DoubleValidator implements IInputValidator { + + @Override + public String isValid(String newText) { + for(int i = 0; i < newText.length(); i++){ + if(!Character.isDigit(newText.charAt(i))){ + if(newText.charAt(i) != '.') { + return "Invalid character '" + newText.charAt(i) + "'"; + } else if(newText.indexOf('.') != newText.lastIndexOf('.')) { + return "There can be only one '.'"; + } + } + } + return null; + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ChartTableWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ChartTableWidget.java new file mode 100644 index 00000000..b0e6e63e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ChartTableWidget.java @@ -0,0 +1,231 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.procedure.Listener; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.tableParser.ParseException; +import org.simantics.sysdyn.tableParser.TableParser; +import org.simantics.sysdyn.tableParser.Token; +import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupInputOutputTable; +import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupInputOutputTable.InputOutput; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; + +public class ChartTableWidget implements Widget { + + Text input, output; + Button add; + LookupInputOutputTable table; + Resource expression; + + public ChartTableWidget(Composite parent, WidgetSupport support, int style) { + support.register(this); + Composite valueTableComposite = new Composite(parent, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(valueTableComposite); + GridLayoutFactory.fillDefaults().numColumns(3).applyTo(valueTableComposite); + + table = new LookupInputOutputTable(valueTableComposite, SWT.NONE); + GridDataFactory.fillDefaults().span(3, 1).grab(false, true).applyTo(table); + table.getTableViewer().getTable().addMouseListener(new MouseListener() { + + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) { + if(e.button == MouseEvent.BUTTON3) { + Table t = (Table)e.widget; + TableItem item = (TableItem)t.getItem(new org.eclipse.swt.graphics.Point(e.x, e.y)); + table.removeItem(t.indexOf(item)); + tableModified(); + } + } + @Override + public void mouseDown(org.eclipse.swt.events.MouseEvent e) { } + @Override + public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) { } + }); + + input = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT); + input.setText(""); + output = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT); + output.setText(""); + + add = new Button(valueTableComposite, SWT.None); + add.setText("Add"); + add.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + try { + Double in = Double.parseDouble(input.getText()); + Double out = Double.parseDouble(output.getText()); + table.addLocation(new Point2D.Double(in, out)); + tableModified(); + } catch (NumberFormatException e1) { + } + input.setText(""); + output.setText(""); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + }); + + FocusListener flistener = new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + Text text = (Text)e.widget; + text.setSelection(0, text.getCharCount()); + } + @Override + public void focusLost(FocusEvent e) { } + }; + + + KeyListener listener = new KeyListener() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) { + try { + Double in = Double.parseDouble(input.getText()); + Double out = Double.parseDouble(output.getText()); + table.addLocation(new Point2D.Double(in, out)); + tableModified(); + } catch (NumberFormatException e1) { + if(input.getText().isEmpty() && output.getText().isEmpty()) { + add.forceFocus(); + return; + } + } + input.setText(""); + output.setText(""); + input.setFocus(); + } + } + + @Override + public void keyReleased(KeyEvent e) { } + + }; + + input.addFocusListener(flistener); + input.addKeyListener(listener); + output.addFocusListener(flistener); + output.addKeyListener(listener); + } + + @Override + public void setInput(ISessionContext context, Object input) { + + expression = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class); + + + try { + SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + String lookup = graph.getRelatedValue(expression, sr.HasLookup); + return lookup; + } + }, new Listener() { + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + @Override + public void execute(String lookup) { + TableParser parser = new TableParser(new StringReader("")); + parser.ReInit(new StringReader(lookup)); + table.clearTable(); + try { + parser.table(); + ArrayList xTokens = parser.getXTokens(); + ArrayList yTokens = parser.getYTokens(); + for(int i = 0; i < xTokens.size(); i++) { + table.addLocation(new Point2D.Double( + Double.parseDouble(xTokens.get(i).image), + Double.parseDouble(yTokens.get(i).image))); + } + } catch (ParseException e1) { + } + } + + @Override + public boolean isDisposed() { + return table.isDisposed(); + } + + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + table.addListener(SWT.Modify, new org.eclipse.swt.widgets.Listener() { + + @Override + public void handleEvent(Event event) { + tableModified(); + } + }); + } + + + @SuppressWarnings("unchecked") + private void tableModified() { + StringBuilder b = new StringBuilder(); + b.append("{"); + Iterator iterator = ((ArrayList)table.getTableViewer().getInput()).iterator(); + while(iterator.hasNext()){ + InputOutput io = iterator.next(); + b.append("{" + io.getInput(String.class) + "," + io.getOutput(String.class) + "}"); + if(iterator.hasNext()) + b.append(","); + } + b.append("}"); + final String table = b.toString(); + + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + graph.claimValue(expression, sr.HasLookup, table); + } + }); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ChartWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ChartWidget.java new file mode 100644 index 00000000..2f3aa635 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ChartWidget.java @@ -0,0 +1,221 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.GridLayout; +import java.awt.geom.Ellipse2D; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Iterator; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.general.SeriesChangeEvent; +import org.jfree.data.general.SeriesChangeListener; +import org.jfree.data.xy.XYDataItem; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.procedure.Listener; +import org.simantics.db.request.Read; +import org.simantics.g2d.chassis.SWTAWTComponent; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.tableParser.ParseException; +import org.simantics.sysdyn.tableParser.TableParser; +import org.simantics.sysdyn.tableParser.Token; +import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupChartPanel; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; + +public class ChartWidget implements Widget { + + JFreeChart chart; + LookupChartPanel chartPanel; + SWTAWTComponent swtawtcomponent; + + public ChartWidget(Composite parent, WidgetSupport support, int style) { + support.register(this); + chartPanel = new LookupChartPanel(createChart()); + chartPanel.setMouseZoomable(true, false); + chartPanel.setDomainZoomable(false); + chartPanel.setRangeZoomable(false); + + swtawtcomponent = new SWTAWTComponent(parent, SWT.BORDER) { + @Override + protected JComponent createSwingComponent() { + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(1, 1)); + panel.add(chartPanel); + panel.doLayout(); + return panel; + } + }; + GridDataFactory.fillDefaults().grab(true, true).applyTo(swtawtcomponent); + swtawtcomponent.populate(); + + } + + @Override + public void setInput(ISessionContext context, Object input) { + + final Resource expression = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class); + + class Auxiliary { + Double minX, minY, maxX, maxY; + String table; + } + + try { + SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Auxiliary perform(ReadGraph graph) throws DatabaseException { + Auxiliary auxiliary = new Auxiliary(); + SysdynResource sr = SysdynResource.getInstance(graph); + auxiliary.minX = graph.getRelatedValue(expression, sr.HasMinX); + auxiliary.maxX = graph.getRelatedValue(expression, sr.HasMaxX); + auxiliary.minY = graph.getRelatedValue(expression, sr.HasMinY); + auxiliary.maxY = graph.getRelatedValue(expression, sr.HasMaxY); + auxiliary.table = graph.getRelatedValue(expression, sr.HasLookup); + return auxiliary; + } + }, new Listener() { + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + @Override + public void execute(Auxiliary result) { + + XYDataset dataset = createDataset(result.table); + chartPanel.resetChart(dataset); + chartPanel.addSeriesChangeListener(new _SeriesChangeListener(expression)); + + XYPlot plot = (XYPlot) chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + rangeAxis.setAutoRange(false); + rangeAxis.setRange(result.minY, result.maxY); + ValueAxis domainAxis = plot.getDomainAxis(); + domainAxis.setAutoRange(false); + domainAxis.setRange(result.minX, result.maxX); + + } + + @Override + public boolean isDisposed() { + return swtawtcomponent.isDisposed(); + } + + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + private JFreeChart createChart() { + XYDataset dataset = createDataset(null); + chart = ChartFactory.createXYLineChart(null, null, null, + dataset, PlotOrientation.VERTICAL, false, true, false); + XYPlot plot = (XYPlot) chart.getPlot(); + XYLineAndShapeRenderer renderer + = (XYLineAndShapeRenderer) plot.getRenderer(); + renderer.setBaseShapesVisible(true); + renderer.setDrawOutlines(true); + renderer.setUseFillPaint(true); + renderer.setBaseFillPaint(Color.white); + renderer.setSeriesStroke(0, new BasicStroke(3.0f)); + renderer.setSeriesOutlineStroke(0, new BasicStroke(2.0f)); + renderer.setSeriesShape(0, new Ellipse2D.Double(-5.0, -5.0, 10.0, 10.0)); + return chart; + } + + public XYDataset createDataset(String table) { + XYSeries series = new XYSeries("Series"); + + if(table != null) { + TableParser parser = new TableParser(new StringReader("")); + parser.ReInit(new StringReader(table)); + try { + parser.table(); + ArrayList xTokens = parser.getXTokens(); + ArrayList yTokens = parser.getYTokens(); + for(int i = 0; i < xTokens.size(); i++) { + series.add( + Double.parseDouble(xTokens.get(i).image), + Double.parseDouble(yTokens.get(i).image)); + } + } catch (ParseException e1) { + } + } + + XYSeriesCollection dataset = new XYSeriesCollection(); + dataset.addSeries(series); + return dataset; + } + + public LookupChartPanel getChartPanel() { + return this.chartPanel; + } + + public JFreeChart getChart() { + return this.chart; + } + + private class _SeriesChangeListener implements SeriesChangeListener { + + Resource expression; + + public _SeriesChangeListener(Resource expression) { + this.expression = expression; + } + @Override + public void seriesChanged(SeriesChangeEvent event) { + if(chartPanel.isDragging()) return; + + StringBuilder b = new StringBuilder(); + b.append("{"); + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + XYSeries series = collection.getSeries(0); + if(series.isEmpty()) + return; + Iterator iterator = series.getItems().iterator(); + while(iterator.hasNext()){ + XYDataItem item = (XYDataItem)iterator.next(); + b.append("{" + item.getX() + "," + item.getY() + "}"); + if(iterator.hasNext()) + b.append(","); + } + b.append("}"); + final String table = b.toString(); + + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + graph.claimValue(expression, sr.HasLookup, table); + } + }); + + } + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java new file mode 100644 index 00000000..3741a34e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java @@ -0,0 +1,88 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ExpressionTypes { + + public static enum ExpressionType {Auxiliary, Parameter, Constant, Lookup, WithLookup, Stock, Delay, Empty}; + + public static ExpressionType[] auxiliaryExpressions = new ExpressionType[] { + ExpressionType.Parameter, + ExpressionType.Auxiliary, + ExpressionType.Constant, + ExpressionType.Lookup, + ExpressionType.WithLookup}; + + public static ExpressionType[] valveExpressions = new ExpressionType[] { + ExpressionType.Auxiliary, + ExpressionType.Parameter, + ExpressionType.Constant, + ExpressionType.WithLookup}; + + public static ExpressionType[] stockExpressions = new ExpressionType[] { + ExpressionType.Stock}; + + public static ExpressionType getExpressionTypeForVariable(final Resource variable) { + try { + return SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public ExpressionType perform(ReadGraph graph) throws DatabaseException { + return getExpressionTypeForVariable(graph, variable); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + return null; + } + + } + + public static ExpressionType getExpressionTypeForVariable(ReadGraph graph, final Resource variable) { + ExpressionType et = null; + try { + SysdynResource sr = SysdynResource.getInstance(graph); + + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if(expression == null) { + if(graph.isInstanceOf(variable, sr.Auxiliary)) { + et = ExpressionType.Auxiliary; + } + else if(graph.isInstanceOf(variable, sr.Valve)) { + et = ExpressionType.Auxiliary; + } + else if(graph.isInstanceOf(variable, sr.Stock)) { + et = ExpressionType.Stock; + } else + et = ExpressionType.Empty; + } else { + if(graph.isInstanceOf(expression, sr.NormalExpression)) { + et = ExpressionType.Auxiliary; + } else if (graph.isInstanceOf(expression, sr.StockExpression)) { + et = ExpressionType.Stock; + } else if (graph.isInstanceOf(expression, sr.ParameterExpression)) { + et = ExpressionType.Parameter; + } else if (graph.isInstanceOf(expression, sr.ConstantExpression)) { + et = ExpressionType.Constant; + } else if (graph.isInstanceOf(expression, sr.DelayExpression)) { + et = ExpressionType.Delay; + } else if (graph.isInstanceOf(expression, sr.LookupExpression)) { + et = ExpressionType.Lookup; + } else if (graph.isInstanceOf(expression, sr.WithLookupExpression)) { + et = ExpressionType.WithLookup; + } else { + et = ExpressionType.Empty; + } + } + } catch (DatabaseException e) { + e.printStackTrace(); + } + return et; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java new file mode 100644 index 00000000..94643afa --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java @@ -0,0 +1,160 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes.ExpressionType; +import org.simantics.sysdyn.ui.properties.widgets.expressions.AuxiliaryExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.ConstantExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.DelayExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.EmptyExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionValidation; +import org.simantics.sysdyn.ui.properties.widgets.expressions.IExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.ParameterExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.StockExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.WithLookupExpression; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; + +public class ExpressionWidget implements Widget { + + private Resource variable; + private Composite parent; + private Map data; + private IExpression expression; + private ModifyListener modifyListener; + private FocusListener focusListener; + private Table variableTable; + + + public ExpressionWidget(Composite parent, WidgetSupport support, int style) { + support.register(this); + this.parent = parent; + this.data = new HashMap(); + } + + @Override + public void setInput(ISessionContext context, Object input) { + if(input instanceof ISelection) { + ISelection selection = (ISelection)input; + if(selection instanceof IStructuredSelection) { + Resource resource = ISelectionUtils.filterSingleSelection(selection, Resource.class); + if(resource != null) { + variable = resource; + } + } + } + + ExpressionType et = ExpressionTypes.getExpressionTypeForVariable(variable); + + displayExpression(et.toString(), true); + } + + + public void displayExpression(String expressionType, boolean original) { + if(expressionType == null) + return; + + if(this.expression != null) expression.updateData(data); + ExpressionType et = ExpressionType.valueOf(expressionType); + IExpression exp = null; + switch (et) { + case Auxiliary: + exp = new AuxiliaryExpression(); break; + case Parameter: + exp = new ParameterExpression(); break; + case Constant: + exp = new ConstantExpression(); break; + case Lookup: + exp = new LookupExpression(); break; + case WithLookup: + exp = new WithLookupExpression(variable); break; + case Stock: + exp = new StockExpression(); break; + case Delay: + exp = new DelayExpression(); break; + default: + exp = new EmptyExpression(); + } + + if (exp != null) { + for(Control c : parent.getChildren()) { + c.dispose(); + } + + if(original) + exp.readData(variable, data); + + exp.createExpressionFields(parent, data); + exp.addModifyListener(modifyListener); + exp.addFocusListener(focusListener); + this.expression = exp; + this.parent.layout(); + validateFields(); + } + } + + public IExpression getExpression() { + return expression; + } + + public void setVariableTable(Table table) { + this.variableTable = table; + } + + public void validateFields() { + if(this.variableTable == null) return; + TableItem[] connectedVariables = this.variableTable.getItems(); + try { + final Resource configuration = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource configuration = variable; + + do { + configuration = graph.getSingleObject(configuration, graph.getBuiltins().PartOf); + if(graph.isInstanceOf(configuration, sr.Configuration)) + return configuration; + } while (configuration != null); + + return null; + } + }); + ExpressionValidation.validateExpressionFields(expression, connectedVariables, configuration); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + } + + public void addModifyListener(ModifyListener listener) { + this.modifyListener = listener; + } + + public void addFocusListener(FocusListener listener) { + this.focusListener = listener; + } + + public void save() { + this.expression.save(variable, data); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/IsOutputWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/IsOutputWidget.java new file mode 100644 index 00000000..2c90f66c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/IsOutputWidget.java @@ -0,0 +1,91 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.utils.ui.ISelectionUtils; + +public class IsOutputWidget implements Widget{ + + Resource variable = null; + org.simantics.browsing.ui.swt.widgets.Button isOutputButton; + + public IsOutputWidget(Composite parent, WidgetSupport support, int style) { + support.register(this); + isOutputButton = new org.simantics.browsing.ui.swt.widgets.Button(parent, support, style |= SWT.CHECK); + isOutputButton.setText("Is Output"); + } + + @Override + public void setInput(ISessionContext context, Object input) { + if(input instanceof ISelection) { + ISelection selection = (ISelection)input; + if(selection instanceof IStructuredSelection) { + Resource resource = ISelectionUtils.filterSingleSelection(selection, Resource.class); + if(resource != null) { + variable = resource; + } + } + } + + if(variable == null) return; + + try { + context.getSession().syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + final boolean isOutput = graph.hasStatement(variable, sr.IsOutput); + final Button button = getWidget(); + button.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if(button.isDisposed()) return; + + if(isOutput) + button.setSelection(true); + else + button.setSelection(false); + } + }); + + + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + isOutputButton.addSelectionListener(new SelectionListenerImpl(context) { + + @Override + public void apply(WriteGraph graph, Resource input) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + if(graph.hasStatement(input, sr.IsOutput)) { + graph.deny(input, sr.IsOutput); + } else { + graph.claim(input, SysdynResource.getInstance(graph).IsOutput, null, input); + } + } + }); + } + + public Button getWidget() { + return isOutputButton.getWidget(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ModuleInputEditingSupport.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ModuleInputEditingSupport.java new file mode 100644 index 00000000..1031a792 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ModuleInputEditingSupport.java @@ -0,0 +1,126 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.util.HashMap; + +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ComboBoxCellEditor; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.swt.SWT; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ModuleInputEditingSupport extends EditingSupport { + private CellEditor editor; + private int column; + private HashMap optionResources; + private String[] options; + private TableViewer tableViewer; + + public ModuleInputEditingSupport(TableViewer viewer, int column) { + super(viewer); + this.tableViewer = (TableViewer)viewer; + this.column = column; + } + + @Override + protected boolean canEdit(Object element) { + switch (this.column) { + case 0: return false; + default: return true; + } + } + + + @Override + protected CellEditor getCellEditor(Object element) { + // Create the correct editor based on the column index + switch (column) { + case 0: + editor = new TextCellEditor(this.tableViewer.getTable()); + case 1: + ReferenceRow row = (ReferenceRow)element; + final Resource module = row.getModule(); + final Resource inputVariable = row.getVariable(); + + optionResources = new HashMap(); + try { + optionResources = SimanticsUI.getSession().syncRequest(new Read>() { + + @Override + public HashMap perform(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + HashMap result = new HashMap(); + for(Resource dependency : graph.syncRequest(new ObjectsWithType(module, sr.IsHeadOf, sr.Dependency))) { + if(graph.getPossibleObject(dependency, sr.RefersTo) == null || + graph.getPossibleObject(dependency, sr.RefersTo).equals(inputVariable)) { + Resource output = graph.getSingleObject(dependency, sr.HasTail); + result.put((String)graph.getRelatedValue(output, b.HasName), dependency); + } + } + return result; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + options = optionResources.keySet().toArray(new String[optionResources.keySet().size() + 1]); + options[optionResources.keySet().size()] = ""; + ComboBoxCellEditor ceditor = new ComboBoxCellEditor(this.tableViewer.getTable(), options, SWT.READ_ONLY); + ceditor.setActivationStyle(1); + editor = ceditor; + break; + default: + editor = null; + } + + return editor; + } + + @Override + protected Object getValue(Object element) { + ReferenceRow referenceRow = (ReferenceRow) element; + + switch (this.column) { + case 0: + return referenceRow.getName(); + case 1: + String refersToName = referenceRow.getValue(); + if (refersToName == null) return options.length - 1; + for(int i = 0; i < options.length ; i++) { + if(refersToName.equals(options[i])) return i; + } + return options[options.length - 1]; + default: + break; + } + return null; + } + + @Override + protected void setValue(Object element, Object value) { + ReferenceRow referenceRow = (ReferenceRow) element; + String valueString = String.valueOf(value); + switch (this.column) { + case 0: + break; + case 1: + referenceRow.setRefersTo(optionResources.get(options[Integer.parseInt(valueString)])); + break; + default: + break; + } + + getViewer().update(element, null); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ModuleOutputEditingSupport.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ModuleOutputEditingSupport.java new file mode 100644 index 00000000..50da2dbc --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ModuleOutputEditingSupport.java @@ -0,0 +1,126 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.util.HashMap; + +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ComboBoxCellEditor; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.swt.SWT; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ModuleOutputEditingSupport extends EditingSupport { + private CellEditor editor; + private int column; + private HashMap optionResources; + private String[] options; + private TableViewer tableViewer; + + public ModuleOutputEditingSupport(TableViewer viewer, int column) { + super(viewer); + this.tableViewer = (TableViewer)viewer; + this.column = column; + } + + @Override + protected boolean canEdit(Object element) { + switch (this.column) { + case 0: return false; + default: return true; + } + } + + + @Override + protected CellEditor getCellEditor(Object element) { + // Create the correct editor based on the column index + switch (column) { + case 0: + editor = new TextCellEditor(this.tableViewer.getTable()); + case 1: + ReferenceRow row = (ReferenceRow)element; + final Resource module = row.getModule(); + final Resource outputVariable = row.getVariable(); + + optionResources = new HashMap(); + try { + optionResources = SimanticsUI.getSession().syncRequest(new Read>() { + + @Override + public HashMap perform(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + HashMap result = new HashMap(); + for(Resource dependency : graph.syncRequest(new ObjectsWithType(module, sr.IsTailOf, sr.Dependency))) { + if(graph.getPossibleObject(dependency, sr.RefersTo) == null || + graph.getPossibleObject(dependency, sr.RefersTo).equals(outputVariable)) { + Resource input = graph.getSingleObject(dependency, sr.HasHead); + result.put((String)graph.getRelatedValue(input, b.HasName), dependency); + } + } + return result; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + options = optionResources.keySet().toArray(new String[optionResources.keySet().size() + 1]); + options[optionResources.keySet().size()] = ""; + ComboBoxCellEditor ceditor = new ComboBoxCellEditor(this.tableViewer.getTable(), options, SWT.READ_ONLY); + ceditor.setActivationStyle(1); + editor = ceditor; + break; + default: + editor = null; + } + + return editor; + } + + @Override + protected Object getValue(Object element) { + ReferenceRow referenceRow = (ReferenceRow) element; + + switch (this.column) { + case 0: + return referenceRow.getName(); + case 1: + String refersToName = referenceRow.getValue(); + if (refersToName == null) return options.length - 1; + for(int i = 0; i < options.length ; i++) { + if(refersToName.equals(options[i])) return i; + } + return options[options.length - 1]; + default: + break; + } + return null; + } + + @Override + protected void setValue(Object element, Object value) { + ReferenceRow referenceRow = (ReferenceRow) element; + String valueString = String.valueOf(value); + switch (this.column) { + case 0: + break; + case 1: + referenceRow.setRefersTo(optionResources.get(options[Integer.parseInt(valueString)])); + break; + default: + break; + } + + getViewer().update(element, null); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceRow.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceRow.java new file mode 100644 index 00000000..d3e4f8a5 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceRow.java @@ -0,0 +1,100 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import org.simantics.databoard.binding.java.StringBindingDefault; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ReferenceRow { + + Resource variable, module, dependency; + String name; + + public ReferenceRow(Resource module, Resource dependency, Resource variable) { + this.module = module; + this.variable = variable; + this.dependency = dependency; + } + + + public Resource getModule() { + return this.module; + } + + public Resource getVariable() { + return this.variable; + } + + public Resource getDependency() { + return this.dependency; + } + + public String getName() { + String name = null; + try { + name = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + return (String)graph.getRelatedValue(getVariable(), graph.getBuiltins().HasName); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return name; + } + + public String getValue() { + if(dependency == null) return ""; + + String value = null; + try { + value = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + Builtins b = graph.getBuiltins(); + SysdynResource sr = SysdynResource.getInstance(graph); + Resource valueResource = graph.getPossibleObject(dependency, sr.HasTail); + if(!graph.isInstanceOf(valueResource, sr.Variable)) + valueResource = graph.getPossibleObject(dependency, sr.HasHead); + if(!graph.isInstanceOf(valueResource, sr.Variable)) + return ""; + return (String)graph.getRelatedValue(valueResource, b.HasName, StringBindingDefault.INSTANCE); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return value; + } + + public void setRefersTo(final Resource dependency) { + if(dependency != null && dependency.equals(this.dependency)) return; + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + if(getDependency() != null && graph.hasStatement(getDependency(), sr.RefersTo)) + graph.deny(getDependency(), sr.RefersTo); + setDependency(null); + if(dependency != null) { + setDependency(dependency); + graph.claim(getDependency(), SysdynResource.getInstance(graph).RefersTo, getVariable()); + } + } + }); + } + + private void setDependency(Resource dependency) { + this.dependency = dependency; + } +} + diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceRowLabelProvider.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceRowLabelProvider.java new file mode 100644 index 00000000..93668d26 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceRowLabelProvider.java @@ -0,0 +1,26 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + +public class ReferenceRowLabelProvider extends LabelProvider implements ITableLabelProvider { + + @Override + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + ReferenceRow referenceRow = (ReferenceRow) element; + switch (columnIndex) { + case 0: + return referenceRow.getName(); + case 1: + return referenceRow.getValue(); + default: + throw new RuntimeException("Should not happen"); + } + } +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceTable.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceTable.java new file mode 100644 index 00000000..32bb8339 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ReferenceTable.java @@ -0,0 +1,121 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.util.ArrayList; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.procedure.Listener; +import org.simantics.db.request.Read; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; + +public class ReferenceTable implements Widget{ + + private TableViewer tableViewer; + private RowProvider rowProvider; + + public static final String FIRSTCOLUMN = "Inputs"; + public static final String SECONDCOLUMN = "Outputs"; + + public ReferenceTable(Composite parent, WidgetSupport support, int style) { + support.register(this); + + Composite base = new Composite(parent, style); + GridLayoutFactory.fillDefaults().applyTo(base); + GridDataFactory.fillDefaults().grab(true, true).applyTo(base); + + Table table = new Table(base, SWT.BORDER|SWT.SINGLE|SWT.FULL_SELECTION); + GridDataFactory.fillDefaults().grab(true, true).applyTo(table); + table.setHeaderVisible (true); + table.setLinesVisible(true); + table.getVerticalBar().setVisible(true); + + tableViewer = new TableViewer (table); + tableViewer.setComparator(new ReferenceRowComparator()); + } + + public TableViewer getTableViewer() { + return this.tableViewer; + } + + public void setRowProvider(RowProvider rowProvider) { + this.rowProvider = rowProvider; + } + + public void setContentProvider(IContentProvider provider) { + tableViewer.setContentProvider(provider); + } + + public void setLabelProvider(IBaseLabelProvider labelProvider) { + tableViewer.setLabelProvider(labelProvider); + } + + @Override + public void setInput(ISessionContext context, Object input) { + final Resource module = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class); + if(this.rowProvider != null) { + try { + SimanticsUI.getSession().syncRequest(new Read>() { + + @Override + public ArrayList perform(ReadGraph graph) throws DatabaseException { + return rowProvider.getRows(graph, module); + } + } , new Listener>() { + + @Override + public boolean isDisposed() { + if(tableViewer != null && tableViewer.getTable() != null) + return getTableViewer().getTable().isDisposed(); + else + return true; + } + + @Override + public void execute(final ArrayList result) { + if(!isDisposed()) + getTableViewer().getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if(!isDisposed()) + getTableViewer().setInput(result); + } + }); + } + + @Override + public void exception(Throwable t) { + } + } + ); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } + + private class ReferenceRowComparator extends ViewerComparator { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + ReferenceRow rr1 = (ReferenceRow)e1; + ReferenceRow rr2 = (ReferenceRow)e2; + return rr1.getName().compareTo(rr2.getName()); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/RowProvider.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/RowProvider.java new file mode 100644 index 00000000..4c1bce70 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/RowProvider.java @@ -0,0 +1,11 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.util.ArrayList; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; + +public abstract class RowProvider { + public abstract ArrayList getRows(ReadGraph graph, Resource module) throws DatabaseException; +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java new file mode 100644 index 00000000..b43486c5 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java @@ -0,0 +1,143 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.util.Collection; +import java.util.HashSet; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ExceptionUtils; +import org.simantics.utils.ui.ISelectionUtils; + +public class ShortcutTabWidget implements Widget { + + TabFolder tabFolder; + TabItem variables; + TabItem functions; + Table variableTable; + Table functionTable; + + public ShortcutTabWidget(Composite parent, WidgetSupport support, int style) { + support.register(this); + + Composite composite = new Composite(parent, style); + GridDataFactory.fillDefaults().span(1, 2).grab(false, true).applyTo(composite); + GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite); + + tabFolder = new TabFolder (composite, SWT.NONE); + GridDataFactory.fillDefaults().grab(false, true).applyTo(tabFolder); + GridLayoutFactory.fillDefaults().applyTo(tabFolder); + variables = new TabItem(tabFolder, SWT.NULL); + variables.setText("Variables"); + variableTable = new Table (tabFolder, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); + + variables.setControl(variableTable); + + functions = new TabItem(tabFolder, SWT.NULL); + functions.setText("Functions"); + functionTable = new Table (tabFolder, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); + TableItem item = new TableItem(functionTable, SWT.NONE); + item.setText("min()"); + item.setData("min({ })"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("max()"); + item.setData("max({ })"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("abs()"); + item.setData("abs({ })"); + item = new TableItem(functionTable, SWT.NONE); + item.setText("if then else"); + item.setData("if then else"); + functions.setControl(functionTable); + } + + @Override + public void setInput(ISessionContext context, Object input) { + if(input instanceof IStructuredSelection) { + final Resource variable = ISelectionUtils.filterSingleSelection((IStructuredSelection)input, Resource.class); + if(variable != null) { + HashSet dependencies = getDependencies(variable); + TableItem item; + for(String d : dependencies) { + item = new TableItem(variableTable, SWT.NONE); + item.setText(d); + item.setData(d); + } + } + } + } + + // Returns the names of the related variables (dependencies) + private HashSet getDependencies(final Resource r){ + HashSet variables = null; + if(r != null) + try { + variables = SimanticsUI.getSession().syncRequest(new Read>() { + + @Override + public HashSet perform(ReadGraph graph) + throws DatabaseException { + HashSet variables = new HashSet(); + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + + Collection dependencies = graph.getObjects(r, sr.IsHeadOf); + + for(Resource d : dependencies) { + if(graph.isInstanceOf(d, sr.Dependency)) { + Resource tail = graph.getPossibleObject(d, sr.HasTail); + if(tail != null) { + Object name = graph.getPossibleRelatedValue(tail, b.HasName); + if(name != null) + variables.add((String)name); + } + } + } + + return variables; + + } + + + }); + } catch (DatabaseException ee) { + ExceptionUtils.logAndShowError(ee); + } + + return variables; + } + + public void addFocusListener(FocusListener listener) { + this.functionTable.addFocusListener(listener); + this.variableTable.addFocusListener(listener); + } + + public void addMouseListener(MouseListener listener) { + this.functionTable.addMouseListener(listener); + this.variableTable.addMouseListener(listener); + } + + public Table getVariableTable() { + return variableTable; + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java new file mode 100644 index 00000000..2f4c1906 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java @@ -0,0 +1,26 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class AuxiliaryExpression extends BasicExpression { + + public AuxiliaryExpression() { + try { + this.expressionType = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return SysdynResource.getInstance(graph).NormalExpression; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java new file mode 100644 index 00000000..fe27bb3e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java @@ -0,0 +1,150 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class BasicExpression implements IExpression { + + private ExpressionField expression; + protected Resource expressionType; + + @Override + public void createExpressionFields(Composite parent, Map data) { + GridLayoutFactory.fillDefaults().numColumns(2).applyTo(parent); + String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + + Label l = new Label(parent, SWT.NONE); + l.setText("="); + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + } + + @Override + public void focus() { + this.expression.focus(); + + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } + + @Override + public void readData(final Resource variable, Map data) { + String equation = null; + if (variable != null && data.get("equation") == null && expressionType != null) { + try { + equation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, expressionType)) { + return graph.getRelatedValue(expression, sr.HasEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", equation); + } + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void save(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + String oldEquation = (String)data.get("equation"); + if(oldEquation == null || + (currentText != null && expressionType != null && !currentText.equals(oldEquation))) { + data.put("equation", currentText); + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null && !g.isInstanceOf(expression, expressionType)) { + g.deny(variable, sr.HasExpression); + expression = null; + } + if(expression == null) { + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, expressionType); + g.claim(variable, sr.HasExpression, expression); + } + g.claimValue(expression, sr.HasEquation, currentText); + } + + }); + } + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + } + + @Override + public void addKeyListener(KeyListener listener) { + this.expression.getSourceViewer().getTextWidget().addKeyListener(listener); + + } + + @Override + public void addModifyListener(ModifyListener listener) { + this.expression.getSourceViewer().getTextWidget().addModifyListener(listener); + + } + + @Override + public void addFocusListener(FocusListener listener) { + this.expression.getSourceViewer().getTextWidget().addFocusListener(listener); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java new file mode 100644 index 00000000..9a733b98 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * 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.sysdyn.ui.properties.widgets.expressions; + +import java.util.HashMap; + +import org.eclipse.jface.text.source.ISharedTextColors; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +public class ColorManager implements ISharedTextColors { + + protected HashMap colorTable = new HashMap(); + + @Override + public void dispose() { + for(Color c : colorTable.values()) + c.dispose(); + colorTable.clear(); + } + + @Override + public Color getColor(RGB rgb) { + Color color = colorTable.get(rgb); + if (color == null) { + color = new Color(Display.getCurrent(), rgb); + colorTable.put(rgb, color); + } + return color; + + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java new file mode 100644 index 00000000..a0b52542 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java @@ -0,0 +1,25 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ConstantExpression extends BasicExpression { + + public ConstantExpression() { + try { + this.expressionType = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return SysdynResource.getInstance(graph).ConstantExpression; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java new file mode 100644 index 00000000..8c9eb5de --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java @@ -0,0 +1,74 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class DelayExpression implements IExpression { + + @Override + public void createExpressionFields(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void readData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void save(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void addKeyListener(KeyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addModifyListener(ModifyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addFocusListener(FocusListener listener) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java new file mode 100644 index 00000000..f2a99fd3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java @@ -0,0 +1,74 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class EmptyExpression implements IExpression { + + @Override + public void createExpressionFields(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void readData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void save(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void addKeyListener(KeyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addModifyListener(ModifyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addFocusListener(FocusListener listener) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java new file mode 100644 index 00000000..d564d062 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * 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.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.PaintManager; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.AnnotationPainter; +import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; +import org.eclipse.jface.text.source.IAnnotationAccess; +import org.eclipse.jface.text.source.MatchingCharacterPainter; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; +import org.eclipse.swt.graphics.Point; +import org.simantics.sysdyn.expressionParser.Token; + +public class ExpressionField extends Composite { + + protected SourceViewer _sourceViewer; + protected IDocument _document; + protected AnnotationModel _annotationModel; + + String oldExpression; + + ColorManager cManager = new ColorManager(); + + IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess(); + + public ExpressionField(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + + int styles = SWT.V_SCROLL + | SWT.MULTI + | SWT.FULL_SELECTION + | SWT.WRAP; + + _document = new Document(); + _document.set(""); + + _annotationModel = new AnnotationModel(); + _annotationModel.connect(_document); + + _sourceViewer = new SourceViewer(this, + + null, + null, + true, + styles); + _sourceViewer.configure(new ExpressionFieldConfiguration(cManager)); + + AnnotationPainter painter = new AnnotationPainter(_sourceViewer, annotationAccess); + _sourceViewer.addPainter(painter); + + painter.addAnnotationType("MissingLink"); + painter.setAnnotationTypeColor("MissingLink", new Color(this.getDisplay(), 255,0,0)); + painter.addAnnotationType("NoSuchVariable"); + painter.setAnnotationTypeColor("NoSuchVariable", new Color(this.getDisplay(), 255,0,0)); + + _sourceViewer.setDocument(_document, _annotationModel); + + GridDataFactory.fillDefaults().grab(true, true).applyTo(_sourceViewer.getControl()); +// _sourceViewer.getControl().setLayoutData(new GridData(SWT.FILL, +// SWT.FILL, +// true, +// true)); + + PaintManager paintManager = new PaintManager(_sourceViewer); + MatchingCharacterPainter matchingCharacterPainter = new MatchingCharacterPainter(_sourceViewer, + new DefaultCharacterPairMatcher( new char[] {'(', ')', '{', '}', '[', ']'} )); + matchingCharacterPainter.setColor(new Color(Display.getCurrent(), new RGB(160, 160, 160))); + paintManager.addPainter(matchingCharacterPainter); + + + _sourceViewer.getTextWidget().addKeyListener(new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if(e.keyCode == SWT.ESC && getExpression() != null) { + ((StyledText)e.widget).setText(oldExpression); + ((StyledText)e.widget).setSelection(getExpression().length()); + } + } + }); + + } + + public SourceViewer getSourceViewer() { + return this._sourceViewer; + } + + public void setMissingLinkAnnotations(List positions){ + for(Position p : positions) { + Annotation annotation = new Annotation(false); + annotation.setType("MissingLink"); + annotation.setText("No link to this variable"); + _annotationModel.addAnnotation(annotation, p); + } + } + + public void setNoSuchVariableAnnotations(List positions){ + for(Position p : positions) { + Annotation annotation = new Annotation(false); + annotation.setType("NoSuchVariable"); + annotation.setText("No such variable in model"); + _annotationModel.addAnnotation(annotation, p); + } + } + + public void setSyntaxError(Token token){ + int start = 0; + int offset = this._document.getLength(); + if(token.image != null && this._document.getLength() > 0) { + try { + start = this._document.getLineOffset(token.beginLine - 1) + token.beginColumn - 1; + offset = this._document.getLineOffset(token.endLine - 1) + token.endColumn - start; + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + Annotation annotation = new Annotation(false); + annotation.setType("MissingLink"); + annotation.setText("Syntax error"); + Position p = new Position(start, offset); + _annotationModel.addAnnotation(annotation, p); + } + + public void resetAnnotations() { + _annotationModel.removeAllAnnotations(); + } + public void setExpression(String expression) { + _document.set(expression); + this.oldExpression = expression; + } + + public String getExpression() { + return this._document.get(); + } + + public Point getSelection() { + return _sourceViewer.getSelectedRange(); + } + + public void setSelection(int selection) { + this._sourceViewer.setSelectedRange(selection, 0); + } + + public IDocument getDocument() { + return _document; + } + + public void focus() { + this._sourceViewer.getTextWidget().forceFocus(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java new file mode 100644 index 00000000..68d46d86 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * 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.sysdyn.ui.properties.widgets.expressions; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.text.DefaultTextHover; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.ITokenScanner; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; +import org.eclipse.jface.text.source.DefaultAnnotationHover; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.RGB; + +public class ExpressionFieldConfiguration extends SourceViewerConfiguration { + + + ColorManager colorManager; + + public ExpressionFieldConfiguration(ColorManager colorManager) { + super(); + this.colorManager = colorManager; + } + + public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { + return new String[] { + IDocument.DEFAULT_CONTENT_TYPE + }; + } + + /* + @Override + public IAutoEditStrategy[] getAutoEditStrategies( + ISourceViewer sourceViewer, String contentType) { + return new IAutoEditStrategy[] { + new ReplaceTabsBySpaces(), + new IndentLineEditStrategy(), + new MatchingBracketsEditStrategy() + }; + } + */ + + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + PresentationReconciler reconciler = new PresentationReconciler(); + + DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getSclTokenScanner()); + + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + + return reconciler; + } + + /* + * + */ + ITokenScanner getSclTokenScanner() { + RuleBasedScanner scanner = new RuleBasedScanner(); + + final Token reserved = new Token( + new TextAttribute( + colorManager.getColor(new RGB(127, 0, 85)), + null, + SWT.BOLD + )); + + + WordRule reservedWord = new WordRule(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + return Character.isLetter(c); + } + + @Override + public boolean isWordPart(char c) { + return Character.isLetter(c); + } + }); + + for(String s : keywords) { + reservedWord.addWord(s, reserved); + } + + IRule[] rules = new IRule[] { + reservedWord + }; + scanner.setRules(rules); + + return scanner; + } + + @Override + public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { + return new DefaultTextHover(sourceViewer); + } + + @Override + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new DefaultAnnotationHover(); + } + + static final Set keywords = new HashSet(); + + static { + keywords.add("within"); + keywords.add("final"); + keywords.add("public"); + keywords.add("protected"); + keywords.add("connect"); + keywords.add("when"); + keywords.add("then"); + keywords.add("elsewhen"); + keywords.add("if"); + keywords.add("end"); + keywords.add("elseif"); + keywords.add("else"); + keywords.add("for"); + keywords.add("while"); + keywords.add("loop"); + keywords.add("der"); + keywords.add("enumeration"); + keywords.add("extends"); + keywords.add("class"); + keywords.add("partial"); + keywords.add("encapsulated"); + keywords.add("model"); + keywords.add("record"); + keywords.add("block"); + keywords.add("expandable"); + keywords.add("connector"); + keywords.add("type"); + keywords.add("package"); + keywords.add("function"); + keywords.add("import"); + keywords.add("external"); + keywords.add("constrainedby"); + keywords.add("redeclare"); + keywords.add("replaceable"); + keywords.add("flow"); + keywords.add("discrete"); + keywords.add("parameter"); + keywords.add("constant"); + keywords.add("input"); + keywords.add("output"); + keywords.add("annotation"); + keywords.add("false"); + keywords.add("true"); + keywords.add("each"); + keywords.add("initial"); + keywords.add("algorithm"); + keywords.add("equation"); + keywords.add("or"); + keywords.add("and"); + keywords.add("not"); + keywords.add("break"); + keywords.add("return"); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java new file mode 100644 index 00000000..5c8a2cdd --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java @@ -0,0 +1,132 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.text.Position; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.TableItem; +import org.simantics.db.Resource; +import org.simantics.sysdyn.expressionParser.ExpressionParser; +import org.simantics.sysdyn.expressionParser.ParseException; +import org.simantics.sysdyn.expressionParser.Token; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.representation.Configuration; +import org.simantics.sysdyn.representation.IElement; +import org.simantics.sysdyn.representation.Variable; +import org.simantics.sysdyn.ui.properties.widgets.expressions.IExpression; +import org.simantics.ui.SimanticsUI; + +public class ExpressionValidation { + + static public void validateExpressionFields(IExpression expression, TableItem[] connectedVariables, Resource configuration) { + ExpressionParser parser = new ExpressionParser(new StringReader("")); + Set variables = new HashSet(); + HashMap>> references = new HashMap>>(); + + + // Build references and variable array + for(ExpressionField ef : expression.getExpressionFields()) { + ef.resetAnnotations(); + String textString = ef.getExpression(); + parser.ReInit(new StringReader(textString)); + try { + parser.expr(); + HashMap> cr = parser.getReferences(); + references.put(ef, cr); + for(String t : cr.keySet()) + variables.add(t); + } catch (ParseException e1) { + ef.setSyntaxError(e1.currentToken); + } + } + + // Remove variables from variable array that don't exist in the model. Create annotations + if(!variables.isEmpty()) { + ArrayList modelVariables = new ArrayList(); + Set noSuchVariables = new HashSet(); + SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession()); + SysdynModel model = sdm.getModel(configuration); + Configuration conf = model.getConfiguration(); + ArrayList elements = conf.getElements(); + for(IElement e : elements) { + if(e instanceof Variable) { + Variable v = (Variable) e; + modelVariables.add(v.getName()); + } + } + + + for(String v : variables) { + if(!modelVariables.contains(v)) { + noSuchVariables.add(v); + } + } + + if(!noSuchVariables.isEmpty()) { + // remove no such variables from variable list + for(String s : noSuchVariables) + variables.remove(s); + // create annotations + HashMap> positions = getPositionsForVariables(references, noSuchVariables); + for(ExpressionField ef : positions.keySet()) { + ef.setNoSuchVariableAnnotations(positions.get(ef)); + } + } + } + + // Check that the variables that exist have connections and the connected variables have references in the expressions + if(!(expression instanceof StockExpression)) { + for(TableItem ti : connectedVariables) { + if(!variables.contains(ti.getText())) { + ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0)); + } else { + ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0)); + variables.remove(ti.getText()); + } + } + + if(!variables.isEmpty()) { + HashMap> positions = getPositionsForVariables(references, variables); + for(ExpressionField ef : positions.keySet()) { + ef.setMissingLinkAnnotations(positions.get(ef)); + } + + } + } + + } + + @SuppressWarnings("unchecked") + static private HashMap> getPositionsForVariables(HashMap>> references, Set variables) { + HashMap> result = new HashMap>(); + for(String s : variables) { + List tlist = new ArrayList(); + for(ExpressionField ef : references.keySet()) { + ArrayList positions = new ArrayList(); + tlist = references.get(ef).get(s); + if(tlist != null) + for(Token t : tlist) { + StyledText st = ef.getSourceViewer().getTextWidget(); + int start = st.getOffsetAtLine(t.beginLine - 1) + t.beginColumn - 1; + int offset = st.getOffsetAtLine(t.endLine - 1) + t.endColumn - start; + positions.add(new Position( + start, + offset)); + } + if(result.keySet().contains(ef)) { + result.get(ef).addAll((ArrayList)positions.clone()); + } else { + result.put(ef, (ArrayList)positions.clone()); + } + } + } + return result; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java new file mode 100644 index 00000000..6c8c152c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java @@ -0,0 +1,33 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public interface IExpression { + + public void createExpressionFields(Composite parent, Map data); + + public void readData(final Resource variable, Map data); + + public void save(final Resource variable, Map data); + + public void focus(); + + public void replaceSelection(String var); + + public void updateData(Map data); + + public List getExpressionFields(); + + public void addModifyListener(ModifyListener listener); + + public void addKeyListener(KeyListener listener); + + public void addFocusListener(FocusListener listener); +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java new file mode 100644 index 00000000..6258aea6 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java @@ -0,0 +1,165 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.jfree.chart.ChartPanel; +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.entity.ChartEntity; +import org.jfree.chart.entity.PlotEntity; +import org.jfree.chart.entity.XYItemEntity; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.general.SeriesChangeListener; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +@SuppressWarnings("serial") +public class LookupChartPanel extends ChartPanel { + + private XYItemEntity dragPrevEntity; + private boolean drawing; + private XYSeries series; + private JFreeChart chart; + private SeriesChangeListener changeListener; + + public LookupChartPanel(JFreeChart chart) { + super(chart); + this.chart = chart; + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + series = collection.getSeries(0); + } + + public void mouseDragged(MouseEvent e) + { + if(dragPrevEntity != null) { + + int item = dragPrevEntity.getItem(); + XYPlot plot = (XYPlot)chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + ValueAxis domainAxis = plot.getDomainAxis(); + Point2D location = getLocationOnChart(getMouseLocation(e)); + Number prevX = item == 0 ? null : series.getX(item - 1); + Number nextX = item == series.getItemCount() - 1 ? null : series.getX(item + 1); + + + if(series.indexOf(location.getX()) >= 0 && series.indexOf(location.getX()) != item) + return; + else if (prevX != null && location.getX() < prevX.doubleValue()) + location.setLocation(series.getX(item).doubleValue(), location.getY()); + else if (nextX != null && location.getX() > nextX.doubleValue()) + location.setLocation(series.getX(item).doubleValue(), location.getY()); + else if (location.getX() > domainAxis.getUpperBound()) + location.setLocation(domainAxis.getUpperBound(), location.getY()); + else if (location.getX() < domainAxis.getLowerBound()) + location.setLocation(domainAxis.getLowerBound(), location.getY()); + + if (location.getY() > rangeAxis.getUpperBound()) + location.setLocation(location.getX(), rangeAxis.getUpperBound()); + else if (location.getY() < rangeAxis.getLowerBound()) + location.setLocation(location.getX(), rangeAxis.getLowerBound()); + + removeItemFromSeries(dragPrevEntity.getItem()); + addLocationToSeries(location); + } else { + ChartEntity currEntity = this.getEntityForPoint(e.getX(),e.getY()); + if(!drawing && currEntity instanceof XYItemEntity) { + dragPrevEntity = ((XYItemEntity)currEntity); + } else if (currEntity instanceof PlotEntity){ + drawing = true; + Point2D locationOnChart = getLocationOnChart(getMouseLocation(e)); + int item = series.indexOf(locationOnChart.getX()); + if (item >= 0) { + Point2D location = new Point2D.Double(series.getX(item).doubleValue(), series.getY(item).doubleValue()); + Point2D javaLocation = getLocationOnJava2D(location); + removeItemFromSeries(item); + addLocationToSeries(getLocationOnChart(new Point2D.Double(javaLocation.getX(), e.getY()))); + } + } + } + + } + + public void mouseReleased(MouseEvent e) { + if(isDragging()) { + dragPrevEntity = null; + if(changeListener != null) + changeListener.seriesChanged(null); + } + drawing = false; + + } + + public void mouseClicked(MouseEvent e) + { + if(e.getButton() == MouseEvent.BUTTON1) { + addLocationToSeries(getLocationOnChart(getMouseLocation(e))); + } else if (e.getButton() == MouseEvent.BUTTON3) { + ChartEntity entity = this.getEntityForPoint(e.getX(),e.getY()); + if(entity instanceof XYItemEntity) { + XYItemEntity xyentity = ((XYItemEntity)entity); + removeItemFromSeries(xyentity.getItem()); + } + } + } + + private Point2D getLocationOnChart(Point2D coordinates) { + XYPlot plot = (XYPlot)chart.getPlot(); + ChartRenderingInfo info = getChartRenderingInfo(); + Rectangle2D dataArea = info.getPlotInfo().getDataArea(); + double chartX = plot.getDomainAxis().java2DToValue(coordinates.getX(), dataArea, + plot.getDomainAxisEdge()); + double chartY = plot.getRangeAxis().java2DToValue(coordinates.getY(), dataArea, + plot.getRangeAxisEdge()); + return new Point2D.Double(chartX, chartY); + } + + private Point2D getLocationOnJava2D(Point2D location) { + XYPlot plot = (XYPlot)chart.getPlot(); + ChartRenderingInfo info = getChartRenderingInfo(); + Rectangle2D dataArea = info.getPlotInfo().getDataArea(); + double javaX = plot.getDomainAxis().valueToJava2D(location.getX(), dataArea, + plot.getDomainAxisEdge()); + double javaY = plot.getRangeAxis().valueToJava2D(location.getY(), dataArea, + plot.getRangeAxisEdge()); + return new Point2D.Double(javaX, javaY); + } + + public void addLocationToSeries(Point2D location) { + if(series.indexOf(location.getX()) < 0) { + series.add(location.getX(), location.getY()); + } + } + + public void removeItemFromSeries(int item){ + series.remove(item); + } + + public void resetChart(XYDataset dataset) { + XYPlot plot = (XYPlot)chart.getPlot(); + plot.setDataset(dataset); + XYSeriesCollection collection = (XYSeriesCollection) plot.getDataset(); + series = collection.getSeries(0); + } + + private Point2D getMouseLocation(MouseEvent e) { + int mouseX = e.getX(); + int mouseY = e.getY(); + Point2D p = translateScreenToJava2D( + new Point(mouseX, mouseY)); + return p; + } + + public void addSeriesChangeListener(SeriesChangeListener listener) { + this.changeListener = listener; + this.series.addChangeListener(changeListener); + } + + public boolean isDragging() { + return dragPrevEntity != null; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java new file mode 100644 index 00000000..4bb7fb32 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java @@ -0,0 +1,74 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class LookupExpression implements IExpression { + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void readData(final Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void save(final Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void createExpressionFields(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void addKeyListener(KeyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addModifyListener(ModifyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addFocusListener(FocusListener listener) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java new file mode 100644 index 00000000..60104211 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java @@ -0,0 +1,259 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +public class LookupInputOutputTable extends Composite { + + public static final String INPUT = "Input"; + public static final String OUTPUT = "Output"; + public static final String[] PROPS = { INPUT, OUTPUT }; + + private Table table; + private TableViewer tableViewer; + private List tableRows; + + public LookupInputOutputTable(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + GridDataFactory.fillDefaults().grab(true, true).applyTo(this); + table = new Table(this, SWT.BORDER|SWT.SINGLE|SWT.FULL_SELECTION); + GridDataFactory.fillDefaults().grab(true, true).applyTo(table); + table.setHeaderVisible (true); + table.setLinesVisible(true); + table.getVerticalBar().setVisible(true); + TableColumn column1 = new TableColumn (table, SWT.LEFT); + column1.setText (INPUT); + column1.setWidth (85); + + TableColumn column2 = new TableColumn (table, SWT.LEFT); + column2.setText (OUTPUT); + column2.setWidth (85); + + // Create the viewer and connect it to the view + tableViewer = new TableViewer (table); + + tableViewer.setContentProvider (new ArrayContentProvider()); + tableViewer.setLabelProvider (new InputOutputLabelProvider()); + tableViewer.setCellModifier(new InputOutputCellModifier()); + + tableRows = new ArrayList(); + tableViewer.setInput(tableRows); + + CellEditor[] editors = new CellEditor[2]; + editors[0] = new TextCellEditor(table); + editors[1] = new TextCellEditor(table); + tableViewer.setCellEditors(editors); + tableViewer.setColumnProperties(PROPS); + + } + + private class InputOutputLabelProvider extends LabelProvider implements ITableLabelProvider { + public Image getColumnImage (Object element, int columnIndex) { + return null; + } + public String getColumnText (Object element, int columnIndex) { + if(element instanceof InputOutput) { + InputOutput io = (InputOutput)element; + switch (columnIndex) { + case 0: return (String)io.getInput(String.class); + case 1: return (String)io.getOutput(String.class); + } + } + return ""; + } + } + + public void addLocation(Point2D location) { + tableRows.add(new InputOutput(location.getX(), location.getY())); + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + refresh(); + } + }); + + } + + public void removeItem(int index) { + tableRows.remove(index); + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + refresh(); + } + }); + } + + public void clearTable() { + this.tableRows.clear(); + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + refresh(); + } + }); + } + + + public class InputOutput { + private double input, output; + + public InputOutput(double input, double output) { + this.input = input; + this.output = output; + } + + /** + * + * @param clazz String.class or Double.class + * @return input as string or double or null if asked for something else + */ + public Object getInput(Class clazz) { + if(clazz == String.class) { + return "" + input; + } else if (clazz == Double.class) { + return input; + } + return null; + } + + public Double setInput(String input) { + try { + this.input = Double.parseDouble(input); + return this.input; + } catch (NumberFormatException e) { + return null; + } + } + + public void setInput(double input) { + this.input = input; + } + + /** + * + * @param clazz String.class or Double.class + * @return output as string or double or null if asked for something else + */ + public Object getOutput(Class clazz) { + if(clazz == String.class) { + return "" + output; + } else if (clazz == Double.class) { + return output; + } + return null; + } + + public void setOutput(String output) { + try { + this.output = Double.parseDouble(output); + } catch (NumberFormatException e) { + + } + } + + public void setOutput(double output) { + this.output = output; + } + + } + + class InputOutputComparator extends ViewerComparator { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + if ((e1 instanceof InputOutput) && + (e2 instanceof InputOutput)) { + InputOutput io1 = (InputOutput)e1; + InputOutput io2 = (InputOutput)e2; + Double d1 = (Double)io1.getInput((Double.class)); + Double d2 = (Double)io2.getInput((Double.class)); + return d1.compareTo(d2); + } + return 0; + } + } + + public TableViewer getTableViewer() { + return this.tableViewer; + } + + public void refresh() { + if(!tableViewer.getTable().isDisposed()) { + tableViewer.setComparator(new InputOutputComparator()); + tableViewer.refresh(); + } + } + + class InputOutputCellModifier implements ICellModifier { + + public InputOutputCellModifier() {} + + public boolean canModify(Object element, String property) { + return true; + } + + public Object getValue(Object element, String property) { + InputOutput io = (InputOutput)element; + if (LookupInputOutputTable.INPUT.equals(property)) + return (String)io.getInput(String.class); + else if (LookupInputOutputTable.OUTPUT.equals(property)) + return (String)io.getOutput(String.class); + else + return null; + } + + public void modify(Object element, String property, Object value) { + if (element instanceof Item) element = ((Item) element).getData(); + + InputOutput io = (InputOutput)element; + + if (LookupInputOutputTable.INPUT.equals(property)) { + io.setInput((String)value); + } else if (LookupInputOutputTable.OUTPUT.equals(property)) { + io.setOutput((String)value); + } + tableModified(); + refresh(); + } + } + + private void tableModified() { + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + for (Listener listener : getListeners(SWT.Modify)) { + Event e = new Event(); + listener.handleEvent(e); + } + } + }); + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java new file mode 100644 index 00000000..7cc116de --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ParameterExpression extends BasicExpression { + + + public ParameterExpression() { + try { + this.expressionType = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return SysdynResource.getInstance(graph).ParameterExpression; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java new file mode 100644 index 00000000..6d357d73 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java @@ -0,0 +1,217 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class StockExpression implements IExpression { + + private Text integral; + private ExpressionField expression; + + @Override + public void createExpressionFields(Composite parent, Map data) { + GridLayoutFactory.fillDefaults().numColumns(2).applyTo(parent); + String initialEquation = data.get("initialEquation") != null ? (String)data.get("initialEquation") : ""; + String integralEquation = data.get("integral") != null ? (String)data.get("integral") : ""; + + + Label label = new Label(parent, SWT.NONE); + label.setText("Integral"); + + integral = new Text(parent, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER); + integral.setEditable(false); + integral.setText(integralEquation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(integral); + + + label = new Label(parent, SWT.NONE); + label.setText("Initial\nValue"); + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setExpression(initialEquation); + + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + } + + @Override + public void focus() { + this.expression.focus(); + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } + + @Override + public void readData(final Resource variable, Map data) { + String initialEquation = null; + + if (variable != null && data.get("initialEquation") == null) { + try { + initialEquation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.StockExpression)) { + return graph.getRelatedValue(expression, sr.HasInitialEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("initialEquation", initialEquation); + } + + data.put("integral", getIntegral(variable)); + + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void save(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + if(currentText != null) { + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null && !g.isInstanceOf(expression, sr.StockExpression)) { + g.deny(variable, sr.HasExpression); + expression = null; + } + if(expression == null) { + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.StockExpression); + g.claim(variable, sr.HasExpression, expression); + } + g.claimValue(expression, sr.HasInitialEquation, currentText); + } + + }); + } + expression.setExpression(currentText); + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("initialEquation", this.expression.getExpression()); + if(this.integral != null && this.integral.getText() != null) + data.put("integral", this.integral.getText()); + } + + + private String getIntegral(final Resource variable) { + String integral = ""; + try { + integral = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + Collection heads = graph.getObjects(variable, sr.IsHeadOf); + Collection tails = graph.getObjects(variable, sr.IsTailOf); + + StringBuilder builder = new StringBuilder(); + builder.append(""); + for (Resource r : heads) { + if(graph.isInstanceOf(r, sr.Flow)) { + Resource tail = graph.getPossibleObject(r, sr.HasTail); + if(tail != null) { + Object name = graph.getPossibleRelatedValue(tail, b.HasName); + if (name != null) + builder.append(" + " + name); + + } + } + } + for (Resource r : tails) { + if(graph.isInstanceOf(r, sr.Flow)) { + Resource head = graph.getPossibleObject(r, sr.HasHead); + if(head != null) { + Object name = graph.getPossibleRelatedValue(head, b.HasName); + if (name != null) + builder.append(" - " + name); + } + } + } + if (builder.indexOf(" + ") == 0) + builder.delete(0, 3); + return builder.toString().trim(); + } + + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return integral; + } + + @Override + public void addKeyListener(KeyListener listener) { + this.expression.getSourceViewer().getTextWidget().addKeyListener(listener); + + } + + @Override + public void addModifyListener(ModifyListener listener) { + this.expression.getSourceViewer().getTextWidget().addModifyListener(listener); + + } + + @Override + public void addFocusListener(FocusListener listener) { + this.expression.getSourceViewer().getTextWidget().addFocusListener(listener); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java new file mode 100644 index 00000000..8d9afd02 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java @@ -0,0 +1,369 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.awt.BasicStroke; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.Point2D; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.swing.Timer; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.awt.SWT_AWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.procedure.Listener; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.representation.Auxiliary; +import org.simantics.sysdyn.tableParser.ParseException; +import org.simantics.sysdyn.tableParser.TableParser; +import org.simantics.sysdyn.tableParser.Token; +import org.simantics.ui.SimanticsUI; + +public class WithLookupExpression implements IExpression { + + private ExpressionField expression; + private ExpressionField lookup; + private ExpressionField lastSelectedText = expression; + private Timer updateChartTimer; + + private ChartPanel smallPanel; + private Frame smallFrame; + + private Resource variable; + + public WithLookupExpression(Resource variable) { + this.variable = variable; + } + + @Override + public void createExpressionFields(Composite parent, final Map data) { + GridLayoutFactory.fillDefaults().numColumns(3).applyTo(parent); + + updateChartTimer = new Timer(1000, new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + updateChart(); + } + }); + updateChartTimer.setRepeats(false); + + String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + String lookupTable = data.get("lookup") != null ? (String)data.get("lookup") : ""; + + Label l = new Label(parent, SWT.NONE); + l.setText("With\nLookup"); + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + expression.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + lastSelectedText = expression; + } + }); + + Composite chartContainer = new Composite(parent, SWT.NONE); + createChart(chartContainer, data); + + + l = new Label(parent, SWT.NONE); + l.setText("Lookup\ntable"); + + lookup = new ExpressionField(parent, SWT.BORDER); + lookup.setExpression(lookupTable); + GridDataFactory.fillDefaults().grab(true, true).applyTo(lookup); + + lookup.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + lastSelectedText = lookup; + } + }); + + lookup.getSourceViewer().getTextWidget().addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + if(!updateChartTimer.isRunning()) + updateChartTimer.start(); + else + updateChartTimer.restart(); + } + }); + + + SimanticsUI.getSession().asyncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + String result = ""; + if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) { + result = graph.getRelatedValue(expression, sr.HasLookup); + } + return result; + } + }, new Listener() { + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + @Override + public void execute(final String result) { + if(lookup != null) + lookup.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + lookup.setExpression(result); + } + }); + updateChart(); + } + + @Override + public boolean isDisposed() { + if(lookup != null && !lookup.isDisposed()) { + return false; + } + return true; + } + }); + + updateChart(); + } + + @Override + public void focus() { + if(this.lastSelectedText != null) this.lastSelectedText.focus(); + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression, this.lookup); + } + + @Override + public void readData(final Resource variable, Map data) { + + class Auxiliary { + String equation, lookup; + } + + Auxiliary results = null; + + if (variable != null && data.get("equation") == null) { + try { + results = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Auxiliary perform(ReadGraph graph) throws DatabaseException { + Auxiliary results = new Auxiliary(); + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) { + results.equation = graph.getRelatedValue(expression, sr.HasEquation); + results.lookup = graph.getRelatedValue(expression, sr.HasLookup); + } else { + results.equation = ""; + results.lookup = ""; + } + return results; + } + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", results.equation); + data.put("lookup", results.lookup); + } + + } + + @Override + public void replaceSelection(String var) { + if(lastSelectedText != null) { + IDocument doc = lastSelectedText.getDocument(); + try { + Point selection = lastSelectedText.getSelection(); + doc.replace(selection.x, selection.y, var); + lastSelectedText.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void save(final Resource variable, Map data) { + final String currentExpression = expression.getExpression(); + final String currentLookupTable = lookup.getExpression(); + String oldExpression = (String)data.get("equation"); + String oldLookupTable = (String)data.get("lookup"); + + if(oldExpression == null || oldLookupTable == null || + (currentExpression != null && currentLookupTable != null + && (!currentExpression.equals(oldExpression) || + !currentLookupTable.equals(oldLookupTable)))) { + data.putAll(data); + data.put("equation", currentExpression); + data.put("lookup", currentLookupTable); + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null && !g.isInstanceOf(expression, sr.WithLookupExpression)) { + g.deny(variable, sr.HasExpression); + expression = null; + } + if(expression == null) { + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.WithLookupExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasMinX, 0.0); + g.claimValue(expression, sr.HasMaxX, 10.0); + g.claimValue(expression, sr.HasMinY, 0.0); + g.claimValue(expression, sr.HasMaxY, 10.0); + + } + g.claimValue(expression, sr.HasEquation, currentExpression); + g.claimValue(expression, sr.HasLookup, currentLookupTable); + } + }); + } + + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + if(this.lookup != null && this.lookup.getExpression() != null) + data.put("lookup", this.lookup.getExpression()); + } + + @Override + public void addKeyListener(KeyListener listener) { + this.expression.getSourceViewer().getTextWidget().addKeyListener(listener); + this.lookup.getSourceViewer().getTextWidget().addKeyListener(listener); + } + + @Override + public void addModifyListener(ModifyListener listener) { + this.expression.getSourceViewer().getTextWidget().addModifyListener(listener); + this.lookup.getSourceViewer().getTextWidget().addModifyListener(listener); + } + + @Override + public void addFocusListener(FocusListener listener) { + this.expression.getSourceViewer().getTextWidget().addFocusListener(listener); + this.lookup.getSourceViewer().getTextWidget().addFocusListener(listener); + } + + private void createChart(Composite composite, final Map data) { + GridLayoutFactory.fillDefaults().applyTo(composite); + GridDataFactory.fillDefaults().span(1, 2).hint(150, SWT.DEFAULT).applyTo(composite); + final Composite chartComposite = new Composite(composite, + SWT.NO_BACKGROUND | SWT.EMBEDDED); + GridDataFactory.fillDefaults().grab(true, true).applyTo(chartComposite); + smallFrame = SWT_AWT.new_Frame(chartComposite); + + XYDataset dataset = new XYSeriesCollection(new XYSeries("Lookup Table")); + JFreeChart chart = createChart(dataset); + smallPanel = new ChartPanel(chart); + smallFrame.add(smallPanel); + + } + + private static JFreeChart createChart(XYDataset dataset) { + JFreeChart chart = ChartFactory.createXYLineChart( + null, + null, + null, + dataset, + PlotOrientation.VERTICAL, + true, + true, + false + ); + chart.removeLegend(); + chart.getXYPlot().getDomainAxis().setTickLabelsVisible(true); + chart.getXYPlot().getDomainAxis().setAxisLineVisible(false); + chart.getXYPlot().getDomainAxis().setTickMarksVisible(true); + chart.getXYPlot().getRangeAxis().setTickLabelsVisible(true); + chart.getXYPlot().getRangeAxis().setAxisLineVisible(false); + chart.getXYPlot().getRangeAxis().setTickMarksVisible(true); + chart.getXYPlot().getRenderer().setSeriesStroke(0, new BasicStroke(3.0f)); + return chart; + } + + private void updateChart() { + ArrayList dataPoints = new ArrayList(); + TableParser parser = new TableParser(new StringReader("")); + parser.ReInit(new StringReader(lookup.getExpression())); + try { + parser.table(); + ArrayList xTokens = parser.getXTokens(); + ArrayList yTokens = parser.getYTokens(); + for(int i = 0; i < xTokens.size(); i++) { + dataPoints.add(new Point2D.Double( + Double.parseDouble(xTokens.get(i).image), + Double.parseDouble(yTokens.get(i).image))); + } + } catch (ParseException e1) { +// e1.printStackTrace(); + return; + } + + XYSeries series = new XYSeries("Lookup Table"); + for(Point2D point : dataPoints) { + series.add(point.getX(), point.getY()); + } + XYSeriesCollection dataset = new XYSeriesCollection(series); + smallPanel.getChart().getXYPlot().setDataset(dataset); + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/factories/DoublePropertyFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/factories/DoublePropertyFactory.java new file mode 100644 index 00000000..7727d14e --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/factories/DoublePropertyFactory.java @@ -0,0 +1,32 @@ +package org.simantics.sysdyn.ui.properties.widgets.factories; + +import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.utils.datastructures.Triple; + +public class DoublePropertyFactory extends ReadFactoryImpl { + + final private String propertyURI; + + public DoublePropertyFactory(String propertyURI) { + this.propertyURI = propertyURI; + } + + @Override + public Object getIdentity(Object inputContents) { + return new Triple((Resource)inputContents, propertyURI, getClass()); + } + + @Override + public String perform(ReadGraph graph, Resource issue) throws DatabaseException { + + Double value = graph.getPossibleRelatedValue(issue, graph.getResource(propertyURI)); + if (value != null) + return value.toString(); + else + return ""; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/factories/DoublePropertyModifier.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/factories/DoublePropertyModifier.java new file mode 100644 index 00000000..5a2f5a72 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/factories/DoublePropertyModifier.java @@ -0,0 +1,23 @@ +package org.simantics.sysdyn.ui.properties.widgets.factories; + +import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListenerImpl; +import org.simantics.databoard.binding.java.DoubleBindingDefault; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; + +public class DoublePropertyModifier extends TextModifyListenerImpl { + + final private String propertyURI; + + public DoublePropertyModifier(ISessionContext context, String propertyURI) { + this.propertyURI = propertyURI; + } + + @Override + public void applyText(WriteGraph graph, Resource input, String text) throws DatabaseException { + graph.claimValue(input, graph.getResource(propertyURI), Double.parseDouble(text), DoubleBindingDefault.INSTANCE); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/sg/SysdynSceneGraphProvider.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/sg/SysdynSceneGraphProvider.java new file mode 100644 index 00000000..be4a5077 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/sg/SysdynSceneGraphProvider.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * 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.sysdyn.ui.sg; + +import java.awt.AWTEvent; +import java.awt.event.AWTEventListener; +import java.awt.geom.Rectangle2D; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.h2d.diagram.IDiagram; +import org.simantics.h2d.diagram.IDiagramListener; +import org.simantics.h2d.element.IElement; +import org.simantics.objmap.IMapping; +import org.simantics.objmap.IMappingListener; +import org.simantics.objmap.MappingException; +import org.simantics.objmap.Mappings; +import org.simantics.scenegraph.adapters.ISceneGraphProvider; +import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.G2DSceneGraph; +import org.simantics.scenegraph.g2d.nodes.NavigationNode; +import org.simantics.scenegraph.g2d.nodes.PageBorderNode; +import org.simantics.scenegraph.g2d.nodes.TransformNode; +import org.simantics.sysdyn.ui.editor.SysdynDiagramSchema; + +public class SysdynSceneGraphProvider implements ISceneGraphProvider, AWTEventListener { + + protected Resource resource; + + IDiagram diagram; + IMapping mapping; + + public SysdynSceneGraphProvider(ReadGraph g, final Resource resource) { + this.resource = resource; + + SysdynDiagramSchema schema; + try { + schema = new SysdynDiagramSchema(g); + } catch (DatabaseException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + return; + } + + mapping = Mappings.createWithListening(schema); + + try { + diagram = (IDiagram)mapping.map(g, resource); + } catch (MappingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + final Session session = g.getSession(); + mapping.addMappingListener(new IMappingListener() { + + @Override + public void rangeModified() { + session.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) + throws DatabaseException { + try { + mapping.updateDomain(graph); + } catch(Exception e) { + e.printStackTrace(); + } + } + + }); + } + + @Override + public void domainModified() { + session.asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + try { + mapping.updateRange(graph); + } catch(Exception e) { + e.printStackTrace(); + } + } + }); + } + }); + } + + @Override + public void dispose() { + + } + + @Override + public AWTEventListener getEventListener() { + return this; + } + + @Override + public G2DSceneGraph initializeSceneGraph(G2DSceneGraph sg) { + return initializeSceneGraph(sg, null); + } + + G2DSceneGraph sceneGraph; + TransformNode diagramCoordinatesNode; + G2DParentNode elementsNode; + G2DParentNode selectionNode; + G2DParentNode actionNode; + + @Override + public G2DSceneGraph initializeSceneGraph(G2DSceneGraph sg, String view) { + sceneGraph = sg; + diagramCoordinatesNode = sceneGraph.addNode(NavigationNode.class); + + PageBorderNode border = diagramCoordinatesNode.addNode(PageBorderNode.class); + border.init(new Rectangle2D.Double(0.0, 0.0, 297.0, 210.0), new Rectangle2D.Double(10.0, 10.0, 277.0, 190.0), Boolean.TRUE); + + elementsNode = diagramCoordinatesNode.addNode(G2DParentNode.class); + elementsNode.setZIndex(0); + + selectionNode = diagramCoordinatesNode.addNode(G2DParentNode.class); + selectionNode.setZIndex(1); + + actionNode = diagramCoordinatesNode.addNode(G2DParentNode.class); + actionNode.setZIndex(2); + + for(IElement element : diagram.getElements()) + element.init(elementsNode); + diagram.addDiagramListener(new IDiagramListener() { + + @Override + public void elementAdded(IElement element) { + element.init(elementsNode); + } + + @Override + public void elementRemoved(IElement element) { + element.remove(); + } + }); + + return sg; + } + + @Override + public void setHint(Object key, Object value) { + // TODO Auto-generated method stub + + } + + @Override + public void eventDispatched(AWTEvent event) { + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/PinTrend.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/PinTrend.java new file mode 100644 index 00000000..ee6b75ed --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/PinTrend.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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.sysdyn.ui.trend; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.State; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; + + +public class PinTrend extends AbstractHandler { + + public static final String COMMAND = "org.simantics.sysdyn.ui.trend.view.pin"; + public static final String STATE = "org.simantics.sysdyn.ui.trend.view.pin.state"; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ICommandService service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = service.getCommand(COMMAND); + State state = command.getState(STATE); + Boolean value = (Boolean) state.getValue(); + value = !value; + state.setValue(value); + + return null; + } + + public static Boolean getState() { + ICommandService service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = service.getCommand(COMMAND); + State state = command.getState(STATE); + return (Boolean)state.getValue(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/TrendView.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/TrendView.java new file mode 100644 index 00000000..b9179b93 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/trend/TrendView.java @@ -0,0 +1,277 @@ +/******************************************************************************* + * 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.sysdyn.ui.trend; + +import java.awt.Frame; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import javax.swing.SwingUtilities; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.awt.SWT_AWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.part.ViewPart; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.AbstractXYDataset; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.SelectionHints; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.modeling.ModelingUtils; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.manager.SysdynDataSet; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.manager.SysdynResult; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; +import org.simantics.utils.ui.jface.ActiveSelectionProvider; + +public class TrendView extends ViewPart { + + Frame frame; + ChartPanel panel; + SysdynDatasets sysdynDatasets = new SysdynDatasets(); + + + @SuppressWarnings("serial") + class SysdynDatasets extends AbstractXYDataset { + + SysdynDataSet[] sets = new SysdynDataSet[0]; + + public void setDatasets(SysdynDataSet[] sets) { + this.sets = sets; + fireDatasetChanged(); + } + + @Override + public Number getY(int series, int item) { + return sets[series].values[item]; + } + + @Override + public Number getX(int series, int item) { + return sets[series].times[item]; + } + + @Override + public int getItemCount(int series) { + return sets[series].times.length; + } + + @Override + public Comparable getSeriesKey(int series) { + SysdynDataSet sds = sets[series]; + if(sds.result == null) + return sds.name; + else + return sds.name + " : " + sds.result; + } + + @Override + public int getSeriesCount() { + return sets.length; + } + + } + + @Override + public void createPartControl(Composite parent) { + final ActiveSelectionProvider selectionProvider = new ActiveSelectionProvider(); + getSite().setSelectionProvider(selectionProvider); + + final Composite composite = new Composite(parent, + SWT.NO_BACKGROUND | SWT.EMBEDDED); + frame = SWT_AWT.new_Frame(composite); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + XYPlot plot = new XYPlot( + sysdynDatasets, + new NumberAxis("time"), + new NumberAxis("x"), + new XYLineAndShapeRenderer(true, false) + ); + + JFreeChart chart = new JFreeChart(plot); + panel = new ChartPanel(chart); + frame.add(panel); + + panel.requestFocus(); + } + + }); + + getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(new ISelectionListener() { + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if(selection.isEmpty() || Boolean.TRUE.equals(PinTrend.getState())) + return; + if(selection instanceof IStructuredSelection) { + Set ress = ISelectionUtils.filterSetSelection(selection, Resource.class); + List runtimes = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_VARIABLE_RESOURCE, Resource.class); + if(runtimes.isEmpty()) + return; + Resource runtime = runtimes.get(0); + setSelection(ress.toArray(Resource.NONE), runtime); + } + } + }); + + } + + Resource[] resources; + Resource runtime; + + protected void setSelection(Resource[] resources, Resource runtime) { + this.resources = resources; + this.runtime = runtime; + updateView(); + } + + public void updateView() { + + Session session = SimanticsUI.peekSession(); + if (session == null) + return; + + session.asyncRequest(new ReadRequest() { + @Override + public void run(ReadGraph g) throws DatabaseException { + + final ArrayList datasets = new ArrayList(); + for(Resource resource : resources) { +// SysdynDataSet set = load(g, resource, runtime); +// if(set == null) { +// return; +// } +// datasets.add(set); + Collection activeDataSets = loadAllActive(g, resource, runtime); + if(activeDataSets != null && !activeDataSets.isEmpty()) + datasets.addAll(activeDataSets); + } + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + sysdynDatasets.setDatasets(datasets.toArray(new SysdynDataSet[datasets.size()])); + } + + }); + + } + }); + } + + /* + protected SysdynDataSet load(ReadGraph g, Resource element, Resource runtime) throws DatabaseException { + + Builtins b = g.getBuiltins(); + + SysdynResource sr = SysdynResource.getInstance(g); + + DiagramResource dr = DiagramResource.getInstance(g); + + if(runtime == null) return null; + Resource resource = ModelingUtils.getPossibleElementCorrespondendence(g, element); + if(resource == null || !g.isInstanceOf(resource, sr.Variable)) return null; + + String variableURI = g.getPossibleRelatedValue(runtime, dr.HasVariable); + + System.out.println("load dataset for '"+ g.getPossibleRelatedValue(resource, b.HasName) + "'in composite '" + variableURI + "'"); + Variable compositeVariable = Variables.getVariable(g, variableURI); + Variable item = compositeVariable.browsePossible(g, resource); + if(item == null) return null; + + System.out.println("load dataset for '" + item.getURI(g) + "'"); + + Accessor accessor = item.getInterface(g, Accessor.class); + if(accessor == null) return null; + try { + return (SysdynDataSet)accessor.getValue(Bindings.getBindingUnchecked(SysdynDataSet.class)); + } catch (RuntimeBindingConstructionException e) { + e.printStackTrace(); + } catch (AccessorException e) { + e.printStackTrace(); + } + return null; + + } + */ + + @Override + public void setFocus() { + if(panel != null) + panel.requestFocus(); + } + + protected Collection loadAllActive(ReadGraph g, Resource element, Resource runtime) throws DatabaseException { + + ArrayList dataSets = new ArrayList(); + Builtins b = g.getBuiltins(); + + SysdynResource sr = SysdynResource.getInstance(g); + + DiagramResource dr = DiagramResource.getInstance(g); + + if(runtime == null) return null; + Resource resource = ModelingUtils.getPossibleElementCorrespondendence(g, element); + if(resource == null || !g.isInstanceOf(resource, sr.Variable)) return null; + + String variableURI = g.getPossibleRelatedValue(runtime, dr.HasVariable); + + System.out.println("load dataset for '"+ g.getPossibleRelatedValue(resource, b.HasName) + "'in composite '" + variableURI + "'"); + Variable compositeVariable = Variables.getVariable(g, variableURI); + Variable item = compositeVariable.browsePossible(g, resource); + if(item == null) return null; + + String rvi = Variables.getRVI(g, item); + System.out.println("HistoryVariable rvi='" + rvi + "'"); + + System.out.println("load dataset for '" + item.getURI(g) + "'"); + + Resource model = Variables.getModel(g, item); + Resource configuration = g.getPossibleObject(model, b.HasConfiguration); + SysdynModel sm = SysdynModelManager.getInstance(g.getSession()).getModel(g, configuration); + + Collection activeResults = sm.getActiveResults(g); + for(SysdynResult sysdynResult : activeResults) { + SysdynDataSet sds = sysdynResult.getDataSet(rvi.substring(1).replace("/", ".")); + if(sds != null) + dataSets.add(sds); + } + return dataSets; + + } + +}