]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.proconf.processeditor/src/org/simantics/processeditor/views/ProcessEditor.java
git-svn-id: https://www.simantics.org/svn/simantics/3d/branches/dev@8676 ac1ea38d...
[simantics/3d.git] / org.simantics.proconf.processeditor / src / org / simantics / processeditor / views / ProcessEditor.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
3  * All rights reserved. This program and the accompanying materials\r
4  * are made available under the terms of the Eclipse Public License v1.0\r
5  * which accompanies this distribution, and is available at\r
6  * http://www.eclipse.org/legal/epl-v10.html\r
7  *\r
8  * Contributors:\r
9  *     VTT Technical Research Centre of Finland - initial API and implementation\r
10  *******************************************************************************/\r
11 package org.simantics.processeditor.views;\r
12 \r
13 import java.util.ArrayList;\r
14 import java.util.Collection;\r
15 import java.util.HashMap;\r
16 import java.util.List;\r
17 import java.util.Map;\r
18 \r
19 import org.eclipse.jface.viewers.ISelection;\r
20 import org.eclipse.jface.viewers.ISelectionChangedListener;\r
21 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
22 import org.eclipse.swt.widgets.Composite;\r
23 import org.eclipse.ui.IWorkbenchPart;\r
24 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
25 import org.simantics.db.Graph;\r
26 import org.simantics.db.Resource;\r
27 import org.simantics.db.Session;\r
28 import org.simantics.db.management.ISessionContext;\r
29 import org.simantics.layer0.utils.EntityFactory;\r
30 import org.simantics.layer0.utils.IEntity;\r
31 import org.simantics.layer0.utils.Property;\r
32 import org.simantics.processeditor.ProcessResource;\r
33 import org.simantics.processeditor.actions.ConfigureFloorAction;\r
34 import org.simantics.processeditor.actions.InsertComponentAction;\r
35 import org.simantics.processeditor.actions.InsertEquipmentAction;\r
36 import org.simantics.processeditor.actions.InsertNozzleAction;\r
37 import org.simantics.processeditor.actions.RoutePipeAction;\r
38 import org.simantics.processeditor.common.ControlPointTools;\r
39 import org.simantics.processeditor.common.PipingRules;\r
40 import org.simantics.processeditor.scenegraph.NonVisibleNode;\r
41 import org.simantics.processeditor.scenegraph.PipeComponentNode;\r
42 import org.simantics.processeditor.scenegraph.PipeRunNode;\r
43 import org.simantics.processeditor.scenegraph.PipelineComponentNode;\r
44 import org.simantics.processeditor.stubs.PipeControlPoint;\r
45 import org.simantics.processeditor.stubs.PipeRun;\r
46 import org.simantics.processeditor.stubs.Plant;\r
47 import org.simantics.processeditor.stubs.Plant3DResource;\r
48 import org.simantics.processeditor.tools.PlantEditContribution;\r
49 import org.simantics.processeditor.tools.PlantVisualizationContribution;\r
50 import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
51 import org.simantics.proconf.g3d.base.ScenegraphAdapter;\r
52 import org.simantics.proconf.g3d.base.ScenegraphAdapterImpl;\r
53 import org.simantics.proconf.g3d.base.SelectionAdapter;\r
54 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
55 import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
56 import org.simantics.proconf.g3d.scenegraph.IGeometryNode;\r
57 import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
58 import org.simantics.proconf.g3d.scenegraph.ISelectableNode;\r
59 import org.simantics.proconf.g3d.scenegraph.ParameterizedModelNode;\r
60 import org.simantics.proconf.g3d.shapes.FloorShape;\r
61 import org.simantics.proconf.g3d.stubs.G3DNode;\r
62 import org.simantics.utils.ui.ErrorLogger;\r
63 import org.simantics.utils.ui.jface.MenuTools;\r
64 \r
65 import com.jme.math.Vector3f;\r
66 import com.jme.scene.Geometry;\r
67 \r
68 \r
69 public class ProcessEditor extends ThreeDimensionalEditorBase {\r
70     \r
71     private Resource plantResource = null;\r
72     \r
73     private ConfigureFloorAction configureFloorAction = null;\r
74 \r
75     private Geometry floorShape = null;\r
76 \r
77     public ProcessEditor(ISessionContext session) {\r
78         super(session);\r
79         addEditorContribution(new PlantEditContribution(this));\r
80         addEditorContribution(new PlantVisualizationContribution(this));\r
81     }\r
82     \r
83     public ProcessEditor(ISessionContext session,JmeRenderingComponent component) {\r
84         super(session,component);\r
85         addEditorContribution(new PlantEditContribution(this));\r
86         addEditorContribution(new PlantVisualizationContribution(this));\r
87     }\r
88     \r
89     @Override\r
90     protected ScenegraphAdapter createScenegraphAdapter() {\r
91         return new ProcessEditorAdapter(session,getRenderingComponent());\r
92     }\r
93     \r
94     @Override\r
95     public void createControl(Graph graph,Composite parent) {\r
96         super.createControl(graph,parent);\r
97 \r
98         floorShape = FloorShape.getShape(getRenderingComponent().getDisplaySystem().getRenderer(), 100.f,0.2f);\r
99         getRenderingComponent().getNoCastRoot().attachChild(floorShape);\r
100         floorShape.setLocalTranslation(new Vector3f(0.f,-0.01f,0.f));\r
101         configureFloorAction.setFloorShape(floorShape);\r
102     }\r
103 \r
104     @Override\r
105     protected void makeActions(Graph graph) {\r
106         super.makeActions(graph);\r
107 \r
108         //actions.add(new ShowTrendsAction(this));\r
109 \r
110         configureFloorAction = new ConfigureFloorAction(this);\r
111 \r
112 //        ContextActionFactory extended[] = ContextActionRegistry.getActions("fi.vtt.proconf.shapeeditor.processeditorview");\r
113 //        for (ContextActionFactory c : extended) {\r
114 //              actions.add(c.createAction(this));\r
115 //        }\r
116     }\r
117     \r
118     protected void fillLocalPullDown() {\r
119         super.fillLocalPullDown();\r
120         MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(configureFloorAction);\r
121     }\r
122     \r
123     protected class ProcessEditorAdapter extends ScenegraphAdapterImpl {\r
124         \r
125          public ProcessEditorAdapter(Session session, JmeRenderingComponent component) {\r
126                         super(session, component);\r
127          }\r
128          \r
129          private class NormalScenegraphQuery extends ScenegraphQuery {\r
130                 \r
131                 public NormalScenegraphQuery(Resource node) {\r
132                                 super(node);\r
133                         } \r
134                  \r
135                  \r
136                  @Override\r
137                 public void shapeAdded(Graph graph, IGraphicsNode node) {\r
138                          // FIXME : this won't work like in previous ProConf\r
139                 }\r
140          }\r
141          \r
142          private Map<Resource,PipeRunControlPointQuery> pipeRunQueries = new HashMap<Resource, PipeRunControlPointQuery>();\r
143 \r
144                 protected ScenegraphQuery newSubnodeListener(G3DNode node) {\r
145                 if (node.isInstanceOf(ProcessResource.plant3Dresource.PipeRun)) {\r
146                     PipeRunControlPointQuery query = new PipeRunControlPointQuery(node.getResource());\r
147                     pipeRunQueries.put(node.getResource(), query);\r
148                     node.getGraph().performQuery(query);\r
149                 }\r
150                 return new NormalScenegraphQuery(node.getResource());\r
151                  \r
152             }\r
153                 \r
154                 @Override\r
155                 protected NodePropertyQuery newRootPropertyListener(G3DNode root) {\r
156                         // currently Plant does not have any properties.\r
157                         return null;\r
158                 }\r
159                 \r
160                 private class TransformationQuery extends NodeTransformationQuery {\r
161                         \r
162                         public TransformationQuery(Resource res) {\r
163                                 super(res);\r
164                         }\r
165                         \r
166                         @Override\r
167                         public void shapeUpdated(Graph graph, IGraphicsNode shape) {\r
168                                 //if (shape instanceof IGeometryNode) {\r
169                 //    updateGeometry((IGeometryNode)shape);\r
170                 //} else {\r
171                         shape.updateTransform(graph);\r
172                 //}\r
173                         }\r
174                 }\r
175                 \r
176                 @Override\r
177                 protected NodeTransformationQuery newTransformationListener(G3DNode root) {\r
178                         return new TransformationQuery(root.getResource());\r
179                 }\r
180                 \r
181                 private class NormalNodePropertyQuery extends org.simantics.proconf.g3d.base.ScenegraphAdapterImpl.NodePropertyQuery {\r
182                         \r
183                         public NormalNodePropertyQuery(Resource resource) {\r
184                                 super(resource);\r
185                         }\r
186 \r
187                         @Override\r
188                         public void shapeUpdated(Graph graph,IGraphicsNode shape) {\r
189                                 if (shape instanceof IGeometryNode) {\r
190                     updateGeometry((IGeometryNode)shape);\r
191                 } else {\r
192                         shape.updateTransform(graph);\r
193                 }\r
194                         }\r
195                 }\r
196          @Override\r
197         protected NodePropertyQuery newPropertyListener(G3DNode node) {\r
198                 return new NormalNodePropertyQuery(node.getResource());\r
199         }\r
200    \r
201          @Override\r
202                 protected IGraphicsNode instantiateNode(IGraphicsNode parent,\r
203                                 G3DNode node) {\r
204                         Plant3DResource p3r = ProcessResource.plant3Dresource;\r
205                         IGraphicsNode newNode = null;\r
206                         try {\r
207                                 if (node.isInstanceOf(p3r.Equipment)) {\r
208                                         newNode = new ParameterizedModelNode(\r
209                                                         ProcessEditor.this, parent, node.getGraph(),\r
210                                                         node.getResource(), p3r.HasGraphics);\r
211                                 } else if (node.isInstanceOf(p3r.PipeRun)) {\r
212                                         newNode = new PipeRunNode(parent, node.getGraph(), node.getResource());\r
213                                 } else if (node.isInstanceOf(p3r.Nozzle)) {\r
214                                         newNode = new ParameterizedModelNode(\r
215                                                         ProcessEditor.this, parent, node.getGraph(),\r
216                                                         node.getResource(), p3r.HasGraphics);\r
217                                         // CodedComponent must be handled first since it uses\r
218                                         // hard-coded geometries\r
219                                         // TODO : is this really necessary, or could we unify\r
220                                         // PipeComponentNode, InlineComponentNode,...\r
221                                 } else if (node.isInstanceOf(p3r.CodedComponent)) {\r
222                                         newNode = new PipeComponentNode(ProcessEditor.this,\r
223                                                         parent, node.getGraph(), node.getResource());\r
224                                 } else if (node.isInstanceOf(p3r.NonVisibleComponent)) {\r
225                                         newNode = new NonVisibleNode(parent, node.getGraph(), node.getResource());\r
226                                 } else if (node.isInstanceOf(p3r.PipelineComponent)) {\r
227                                         newNode = new PipelineComponentNode(ProcessEditor.this,\r
228                                                         parent, node.getGraph(), node.getResource());\r
229                                 } \r
230 \r
231                                 // } else if (node instanceof Shape) // Markers (ar/mobile)\r
232                                 // needed this\r
233                                 // newNode = new ShapeNode(TestProcessEditor.this,parent,node);\r
234                                 if (newNode != null) {\r
235                                         if (newNode instanceof ISelectableNode)\r
236                                                 ((ISelectableNode) newNode).setVisible(true);\r
237                                         if (newNode instanceof IGeometryNode) {\r
238                                                 updateGeometry((IGeometryNode) newNode);\r
239                                         }\r
240                                         return newNode;\r
241                                 }\r
242                         } catch (Exception e) {\r
243                                 ErrorLogger.defaultLogError("Cannot handle node " + node.getResource(), e);\r
244                                 return null;\r
245                         }\r
246                         ErrorLogger.defaultLogError("Cannot handle node " + node.getResource(), null);\r
247                         return null;\r
248 \r
249                 }\r
250 \r
251                 /**\r
252                  * This is used to create elbows and straight pipes to pipeline TODO :\r
253                  * this should be done with rule-engine!\r
254                  * \r
255                  * \r
256                  * @author Marko Luukkainen\r
257                  * \r
258                  */\r
259                 protected class PipeRunControlPointQuery extends NodeQuery {\r
260                         private List<Resource> removed = new ArrayList<Resource>();\r
261                         private List<Resource> added = new ArrayList<Resource>();\r
262 \r
263                         public PipeRunControlPointQuery(Resource r) {\r
264                                 super(r);\r
265                                 if (DEBUG) System.out.println("Created PipeRunControlPointQuery for " + r);\r
266 \r
267                         }\r
268 \r
269                         @Override\r
270                         protected Object compute2(Graph graph) {\r
271                                 PipeRun run = new PipeRun(graph, nodeResource);\r
272                                 Collection<IEntity> cps = run\r
273                                                 .getRelatedObjects(ProcessResource.plant3Dresource.HasControlPoints);\r
274                                 List<Resource> res = new ArrayList<Resource>();\r
275                                 for (IEntity t : cps)\r
276                                         res.add(t.getResource());\r
277                                 return res;\r
278                         }\r
279 \r
280                         @Override\r
281                         public boolean updated(Graph graph, Object oldResult,\r
282                                         Object newResult) {\r
283                                 \r
284                                 removed.clear();\r
285                                 added.clear();\r
286 \r
287                                 List<Resource> oldCps = (List<Resource>) oldResult;\r
288                                 List<Resource> newCps = (List<Resource>) newResult;\r
289                                 if (oldCps == null)\r
290                                         oldCps = new ArrayList<Resource>();\r
291 \r
292                                 for (Resource r : oldCps) {\r
293                                         if (!newCps.contains(r))\r
294                                                 removed.add(r);\r
295                                 }\r
296 \r
297                                 for (Resource r : newCps) {\r
298                                         if (!oldCps.contains(r))\r
299                                                 added.add(r);\r
300                                 }\r
301                                 for (Resource r : removed)\r
302                                         removeControlPoint(graph, r);\r
303                                 for (Resource r : added) {\r
304                                         addControlPoint(graph, r);\r
305                                         // ControlPointTools.addControlPoint(new\r
306                                         // PipeRun(graph,pipeRun), new PipeControlPoint(graph, r));\r
307                                 }\r
308 \r
309                                 return (added.size() > 0 || removed.size() > 0);\r
310                         }\r
311                         \r
312                         @Override\r
313                         public void dispose() {\r
314                                 super.dispose();\r
315                                 for (ControlPointPropertyQuery q : controlPointPropertyQueries.values())\r
316                                         q.dispose();\r
317                                 controlPointPropertyQueries.clear();\r
318                         }\r
319                         \r
320                         private Map<Resource,ControlPointPropertyQuery> controlPointPropertyQueries = new HashMap<Resource, ControlPointPropertyQuery>();\r
321                         \r
322                         private void addControlPoint(Graph graph, Resource resource) {\r
323                                 ControlPointPropertyQuery query = new ControlPointPropertyQuery(resource);\r
324                                 graph.performQuery(query);\r
325                                 controlPointPropertyQueries.put(resource,query);\r
326                         }\r
327                         \r
328                         private void removeControlPoint(Graph graph, Resource resource) {\r
329                                 ControlPointPropertyQuery query = controlPointPropertyQueries.remove(resource);\r
330                                 query.dispose();\r
331                                 ControlPointTools.removeControlPoint(new PipeControlPoint(\r
332                                                 graph, resource));\r
333                         }\r
334 \r
335                 }\r
336 \r
337                 protected class ControlPointPropertyQuery extends NodeQuery {\r
338                         boolean initialized = false;\r
339                         \r
340                         public ControlPointPropertyQuery(Resource r) {\r
341                                 super(r);\r
342                                 if (DEBUG) System.out.println("Created ControlPointPropertyQuery for " + r);\r
343                         }\r
344                         \r
345                         @Override\r
346                 public List<Object> compute2(Graph g) {\r
347                         IEntity t = EntityFactory.create(g,nodeResource);\r
348                         \r
349                         Collection<Property> properties = t.getRelatedProperties(ProcessResource.builtins.HasProperty);\r
350                         List<Object> propertyValues = new ArrayList<Object>();\r
351                         p(properties,propertyValues);\r
352 \r
353                         return propertyValues;\r
354                 }\r
355                 \r
356                 private void p(Collection<Property> properties, List<Object> propertyValues) {\r
357                         for (Property p : properties) {\r
358                                 Collection<Property> subProperties = p.getRelatedProperties(p.getGraph().getBuiltins().HasProperty);\r
359                                 if (subProperties.size() != 0) {\r
360                                         p(subProperties,propertyValues);\r
361                                 } \r
362                                 if (p.hasValue()){\r
363                                         propertyValues.add(p.getValue());\r
364                                 }\r
365                         }\r
366                 }\r
367                         \r
368                         @Override\r
369                         public boolean updated(Graph graph, Object oldResult, Object newResult) {\r
370                                 PipingRules.pipeControlPointPositionUpdate(graph, this.nodeResource);\r
371                                 if (initialized) {\r
372                                         //PipingRules.pipeControlPointPositionUpdate(graph, this.nodeResource);\r
373                                 } else {\r
374                                         initialized = true;\r
375                                 }\r
376                                 return true;\r
377                         }\r
378                 }\r
379                 \r
380                 @Override\r
381                 protected void removeNode(Resource parent, Resource r) {\r
382                         super.removeNode(parent, r);\r
383                         PipeRunControlPointQuery q = pipeRunQueries.get(r);\r
384                         if (q != null)\r
385                                 q.dispose();\r
386                 }\r
387                 \r
388                 @Override\r
389                 public void dispose() {\r
390                         super.dispose();\r
391                 }\r
392         }\r
393     \r
394     @Override\r
395     protected void pageSelectionChanged(IWorkbenchPart part, ISelection selection) {\r
396         if (!(selection instanceof StructuredResourceSelection)) {\r
397             return;\r
398         }\r
399         \r
400         StructuredResourceSelection s = (StructuredResourceSelection) selection;\r
401         selectionAdapter.setCurrentSelection(s);\r
402         viewChanged = true;\r
403         \r
404         //if (s.getRootSelection() == null) {\r
405         if (!(part instanceof ProcessEditor)) {\r
406             //System.out.println("ShapeEditorView.pageSelectionChanged() no root selection");\r
407                 ((ProcessEditorSelectionAdapter)selectionAdapter).setEditorSelection(true);\r
408             return;\r
409         } \r
410         //if (!s.getRootSelection().getResource().getId().equals(plant.getResource().getId())) {\r
411         ProcessEditor sender = (ProcessEditor)part;\r
412         if (!sender.getPlantResource().equals(plantResource)) {\r
413 //          System.out.println("ShapeEditorView.pageSelectionChanged() not right group "\r
414 //                  + s.getRootSelection().getResource().getId() + " != " + model.getResource().getId());\r
415                 selectionAdapter.setCurrentSelection(new StructuredResourceSelection());\r
416                 ((ProcessEditorSelectionAdapter)selectionAdapter).setEditorSelection(false);\r
417           return;\r
418       }\r
419         selectionAdapter.setEditorSelection();\r
420         \r
421     }\r
422 \r
423     @Override\r
424     protected void reloadFrom(IEntity thing) {\r
425         if (plantResource != null) {\r
426             throw new UnsupportedOperationException("Reloading instantiated viewer not supported");\r
427         }\r
428         if (thing.isInstanceOf(ProcessResource.plant3Dresource.Plant)) {\r
429             plantResource = thing.getResource();\r
430             G3DNode plant = new G3DNode(thing);\r
431             adapter.setRootNode(plant);\r
432             //adapter.addOutbound(plant);\r
433             ControlPointTools.reloadCache(thing.getGraph(),plant.getResource());\r
434         } else {\r
435             throw new IllegalArgumentException("Resource is not a plant");\r
436         } \r
437     }\r
438 \r
439     public Resource getPlantResource() {\r
440         return plantResource;\r
441     }\r
442     \r
443     public Plant getPlant(Graph g) {\r
444         return new Plant(g, plantResource);\r
445     }\r
446     \r
447     @Override\r
448     protected SelectionAdapter createSelectionAdapter() {\r
449         return new ProcessEditorSelectionAdapter(adapter);\r
450     }\r
451     \r
452     protected class ProcessEditorSelectionAdapter extends SelectionAdapter {\r
453         \r
454         \r
455          public ProcessEditorSelectionAdapter(ScenegraphAdapter adapter) {\r
456                         super(adapter);\r
457          }\r
458 \r
459             @Override\r
460             public void setEditorSelection() {\r
461                 List<IGraphicsNode> sel = getSelectedObjects();\r
462                 for (IGraphicsNode o : adapter.getNodes())\r
463                         if (o instanceof ISelectableNode) {\r
464                                 if (sel.contains(o)) {\r
465                                 ((ISelectableNode)o).setSelected(true);\r
466                         } else {\r
467                                 ((ISelectableNode)o).setSelected(false);\r
468                         }\r
469                         }\r
470             }\r
471             \r
472             public void setEditorSelection(boolean addShapes) {\r
473 \r
474                 List<IGraphicsNode> sel = getSelectedObjects();\r
475                 for (IGraphicsNode o : adapter.getNodes())\r
476                         if (o instanceof ISelectableNode) {\r
477                                 if (sel.contains(o)) {\r
478                                 ((ISelectableNode)o).setSelected(true);\r
479                         } else {\r
480                                 ((ISelectableNode)o).setSelected(false);\r
481                         }\r
482                         }\r
483             }\r
484 \r
485             @Override\r
486             protected void setEditorHighlightSelection() {\r
487                 List<IGraphicsNode> sel = getInteractiveSelectedObjects();\r
488                 for (IGraphicsNode o : adapter.getNodes())\r
489                         if (o instanceof ISelectableNode) {\r
490                                 if (sel.contains(o)) {\r
491                                 ((ISelectableNode)o).setHighlighted(true);\r
492                         } else {\r
493                                 ((ISelectableNode)o).setHighlighted(false);\r
494                         }\r
495                         }\r
496             }\r
497     }\r
498     \r
499     @Override\r
500     protected void hookDragAndDrop() {\r
501         super.hookDragAndDrop();\r
502         dropTarget.addDropListener(new InsertEquipmentAction(this));\r
503         dropTarget.addDropListener(new InsertNozzleAction(this));\r
504         dropTarget.addDropListener(new InsertComponentAction(this));\r
505         dropTarget.addDropListener(new RoutePipeAction(this));\r
506     }\r
507     \r
508     @Override\r
509         public Object getAdapter(Class adapter) {\r
510                 if (adapter == IContentOutlinePage.class) {\r
511                         if (getPlantResource() == null)\r
512                                 return null;\r
513                         final PlantStructureOutlinePage page = new PlantStructureOutlinePage(sessionContext,getPlantResource());\r
514                         \r
515                         getSelectionAdapter().addSelectionChangedListener(new ISelectionChangedListener() {\r
516                                 @Override\r
517                                 public void selectionChanged(SelectionChangedEvent event) {\r
518                                         page.setSelection(event.getSelection());\r
519                                         \r
520                                 }\r
521                         });\r
522                         parent.getDisplay().asyncExec(new Runnable() {\r
523                                 @Override\r
524                                 public void run() {\r
525                                         page.addSelectionChangedListener(new ISelectionChangedListener() {\r
526                                                 @Override\r
527                                                 public void selectionChanged(SelectionChangedEvent event) {\r
528                                                         selectionAdapter.setSelection(SelectionAdapter.transformSelection(event.getSelection()));\r
529                                                 }\r
530                                         });\r
531                                 }\r
532                         });\r
533 \r
534                         return page;\r
535                 }\r
536                 return null;\r
537         }\r
538 }