package org.simantics.plant3d.editor; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; 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.g3d.scenegraph.IG3DNode; import org.simantics.g3d.scenegraph.NodeMap; import org.simantics.g3d.scenegraph.base.INode; import org.simantics.g3d.vtk.action.RemoveAction; import org.simantics.g3d.vtk.common.HoverHighlighter; import org.simantics.g3d.vtk.common.NodeSelectionProvider2; import org.simantics.g3d.vtk.common.SelectionHighlighter; import org.simantics.g3d.vtk.common.VtkView; import org.simantics.g3d.vtk.shape.vtkShape; import org.simantics.g3d.vtk.swt.ContextMenuListener; import org.simantics.g3d.vtk.swt.InteractiveVtkComposite; import org.simantics.g3d.vtk.swt.RotateAction; import org.simantics.g3d.vtk.swt.TranslateAction; import org.simantics.g3d.vtk.swt.vtkCameraAndSelectorAction; import org.simantics.g3d.vtk.utils.AxesDisplay; import org.simantics.objmap.graph.IMapping; import org.simantics.objmap.graph.Mappings; import org.simantics.objmap.graph.schema.IMappingSchema; import org.simantics.plant3d.actions.AddComponentAction; import org.simantics.plant3d.actions.AddEquipmentAction; import org.simantics.plant3d.actions.AddNozzleAction; import org.simantics.plant3d.actions.RemoveAndSplitAction; import org.simantics.plant3d.actions.RoutePipeAction; import org.simantics.plant3d.actions.TranslateInlineAction; import org.simantics.plant3d.scenegraph.EndComponent; import org.simantics.plant3d.scenegraph.Equipment; import org.simantics.plant3d.scenegraph.IP3DNode; import org.simantics.plant3d.scenegraph.InlineComponent; import org.simantics.plant3d.scenegraph.Nozzle; import org.simantics.plant3d.scenegraph.P3DRootNode; import org.simantics.plant3d.scenegraph.PipelineComponent; import org.simantics.plant3d.scenegraph.SchemaBuilder; import org.simantics.plant3d.scenegraph.TurnComponent; import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory; import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; import org.simantics.plant3d.utils.ComponentUtils; import org.simantics.plant3d.utils.Item; import org.simantics.plant3d.utils.P3DUtil; import org.simantics.selectionview.StandardPropertyPage; import org.simantics.ui.workbench.IPropertyPage; import org.simantics.ui.workbench.IResourceEditorInput; import org.simantics.ui.workbench.ResourceEditorPart; import org.simantics.utils.threads.ThreadUtils; import org.simantics.utils.ui.ExceptionUtils; import vtk.vtkActor; import vtk.vtkCameraPass; import vtk.vtkDefaultPass; import vtk.vtkLightsPass; import vtk.vtkRenderPassCollection; import vtk.vtkRenderer; import vtk.vtkSequencePass; public class Plant3DEditor extends ResourceEditorPart { private Composite parent; private Resource input; // private InteractiveVtkPanel panel; // private SWTAWTComponent component; private InteractiveVtkComposite panel; private P3DRootNode rootNode; private IMapping mapping; private NodeSelectionProvider2 selectionProvider; private vtkCameraAndSelectorAction cameraAction; private TranslateAction translateAction; private TranslateInlineAction translateInlineAction; private RotateAction rotateAction; private RemoveAction removeAction; private RemoveAndSplitAction removeSplitAction; private RoutePipeAction routePipeAction; private AddComponentAction addComponentAction; private P3DNodeMap nodeMap; @Override public void createPartControl(Composite parent) { this.parent = parent; parent.setLayout (new FillLayout ()); // component = new SWTAWTComponent(parent,SWT.NONE) { // // @Override // protected Component createSwingComponent() { // if (panel == null) { // panel = new InteractiveVtkPanel(); // vtkPanelUtil.registerPanel(panel); // createScene(); // } // return panel; // } // }; IResourceEditorInput rei = (IResourceEditorInput)getEditorInput(); input = rei.getResource(); panel = new InteractiveVtkComposite(parent); //IActionBars actionBars = getEditorSite().getActionBars(); hookContextMenu(); createScene(); //component.syncPopulate(); new ContextMenuListener(panel, contextMenu); cameraAction = new vtkCameraAndSelectorAction(panel); panel.setDefaultAction(cameraAction); panel.useDefaultAction(); panel.setPickType(4); try { ControlPointFactory.preloadCache(); ComponentUtils.preloadCache(); } catch (Exception e) { ExceptionUtils.logAndShowError("Cannot open Plant3D editor",e); return; } try { getSession().syncRequest(new ReadRequest() { @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void run(ReadGraph graph) throws DatabaseException { PipingRules.setEnabled(false); IMappingSchema schema = getSchema(graph); mapping = Mappings.createWithListening(schema); rootNode = (P3DRootNode)mapping.map(graph, input); // update control points. // TODO : this should be optimized. try { P3DUtil.finalizeDBLoad(rootNode); } catch (Exception e) { throw new DatabaseException(e); } nodeMap = createNodeMap(getSession(), mapping, panel,rootNode); } }); if (rootNode == null) throw new RuntimeException("Scenegraph loading failed."); populate(); selectionProvider = new NodeSelectionProvider2(this,mapping,nodeMap); cameraAction.addSelectionChangedListener(selectionProvider); cameraAction.addHoverChangedListener(new HoverHighlighter(panel,nodeMap)); selectionProvider.addSelectionChangedListener(new SelectionHighlighter(panel,nodeMap)); getSite().setSelectionProvider(selectionProvider); getSite().getPage().addPostSelectionListener(selectionProvider); //outlinePage = new ScenegraphOutlinePage(rootNode); parent.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { getSite().getPage().removePostSelectionListener(selectionProvider); PipingRules.setEnabled(false); nodeMap.delete(); PipingRules.setEnabled(true); mapping.dispose(); // component.dispose(); //panel.getComponent().dispose(); } }); } catch (DatabaseException e1) { ExceptionUtils.logAndShowError("Cannot open Plant3D editor",e1); return; } createActions(); } protected void createActions() { translateAction = new TranslateAction(panel,nodeMap); translateInlineAction = new TranslateInlineAction(panel, nodeMap); rotateAction = new RotateAction(panel,nodeMap); removeAction = new RemoveAction(nodeMap) { public void setNode(IG3DNode node) { super.setNode(node); } }; removeSplitAction = new RemoveAndSplitAction(nodeMap); routePipeAction = new RoutePipeAction(panel,rootNode); addComponentAction = new AddComponentAction(panel, rootNode); } public void populate() { ThreadUtils.asyncExec(panel.getThreadQueue(), new Runnable() { @Override public void run() { nodeMap.populate(); } }); } protected IMappingSchema getSchema(ReadGraph graph) throws DatabaseException { IMappingSchema schema = SchemaBuilder.getSchema(graph); return schema; } protected P3DNodeMap createNodeMap(Session session, IMapping mapping, VtkView panel, P3DRootNode rootNode) { return new P3DNodeMap(session, mapping, panel,rootNode); } @Override public void setFocus() { //component.setFocus(); panel.getComponent().setFocus(); } private void createScene() { vtkRenderer ren1 = panel.getRenderer(); boolean multiPass = false; if (multiPass) { vtkLightsPass lightsPass = new vtkLightsPass(); vtkDefaultPass defaultPass = new vtkDefaultPass(); vtkRenderPassCollection passes = new vtkRenderPassCollection(); passes.AddItem(lightsPass); passes.AddItem(defaultPass); vtkSequencePass seq = new vtkSequencePass(); seq.SetPasses(passes); vtkCameraPass cameraPass = new vtkCameraPass(); cameraPass.SetDelegatePass(seq); ren1.SetPass(cameraPass); } // ren1.GetRenderWindow().LineSmoothingOn(); // ren1.GetRenderWindow().PointSmoothingOn(); // ren1.GetRenderWindow().PolygonSmoothingOn(); // ren1.GetRenderWindow().SetMultiSamples(2); ren1.SetBackground2(1,1,1); // background color white ren1.SetBackground(0.9,0.9,0.9); ren1.SetGradientBackground(true); // vtkActor grid = vtkShape.createGridActor(8,1.0,1|2|4); vtkActor grid = vtkShape.createGridActor(8,1.0, 2 ); grid.SetPickable(0); ren1.AddActor(grid); panel.addDeletable(grid); AxesDisplay axesDisplay = new AxesDisplay(panel); axesDisplay.show(); } protected Menu contextMenu; protected void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { createContextMenu(manager); } }); contextMenu = menuMgr.createContextMenu(parent); } protected void createContextMenu(IMenuManager m) { List selected = selectionProvider.getSelectedNodes(); try { if (selected.size() == 0) { for (Item eq : P3DUtil.getEquipments()) { m.add(new AddEquipmentAction(rootNode, eq)); } } else if (selected.size() == 1) { IP3DNode node = (IP3DNode)selected.get(0); if (node instanceof Equipment) { m.add(translateAction); m.add(rotateAction); for (Item eq : P3DUtil.getNozzles()) { AddNozzleAction add = new AddNozzleAction(rootNode, eq); add.setEquipment((Equipment)node); m.add(add); } m.add(removeAction); } else if (node instanceof Nozzle) { Nozzle nozzle = (Nozzle)node; if (!nozzle.isFixed()) { m.add(translateAction); m.add(rotateAction); } m.add(routePipeAction); routePipeAction.setComponent(nozzle); routePipeAction.setEnabled(nozzle.getNext() == null && nozzle.getPrevious() == null); m.add(addComponentAction); addComponentAction.setComponent(nozzle); m.add(removeAction); } else if (node instanceof TurnComponent) { m.add(translateAction); TurnComponent component = (TurnComponent)node; m.add(routePipeAction); routePipeAction.setComponent(component); routePipeAction.setEnabled(component.getNext() == null || component.getPrevious() == null); m.add(addComponentAction); addComponentAction.setComponent(component); m.add(removeAction); m.add(removeSplitAction); removeSplitAction.setNode(node); } else if (node instanceof EndComponent) { m.add(translateAction); m.add(addComponentAction); addComponentAction.setComponent((PipelineComponent)node); m.add(removeAction); } else if (node instanceof InlineComponent) { //m.add(translateInlineAction); InlineComponent component = (InlineComponent)node; m.add(translateInlineAction); m.add(routePipeAction); routePipeAction.setComponent(component); m.add(addComponentAction); addComponentAction.setComponent(component); m.add(removeAction); m.add(removeSplitAction); removeSplitAction.setNode(node); } else { m.add(removeAction); } translateAction.setNode(node); translateInlineAction.setNode(node); rotateAction.setNode(node); removeAction.setNode(node); } } catch (DatabaseException e) { ExceptionUtils.logAndShowError(e); } } private IContentOutlinePage createOutline() { if (rootNode == null || selectionProvider == null) return null; //IContentOutlinePage outlinePage = new VTKContentOutlinePage(rootNode, selectionProvider); IContentOutlinePage outlinePage = new P3DContentOutlinePage(rootNode, selectionProvider) { protected void createContextMenu(IMenuManager manager) { Plant3DEditor.this.createContextMenu(manager); }; }; outlinePage.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { selectionProvider.selectionChanged(event); } }); return outlinePage; } @SuppressWarnings("rawtypes") @Override public Object getAdapter(Class adapter) { if (IPropertyPage.class.equals(adapter)) return new StandardPropertyPage(getSite(),getPropertyContexts()); if (IContentOutlinePage.class.equals(adapter)) { return createOutline(); } if (NodeMap.class.equals(adapter)) { return nodeMap; } if (INode.class.equals(adapter)) { return rootNode; } if (IMapping.class.equals(adapter)) { return mapping; } // if (InteractiveVtkPanel.class.equals(adapter)) { // return panel; // } if (VtkView.class.equals(adapter)) return panel; if (ISelectionProvider.class.equals(adapter)) return selectionProvider; return super.getAdapter(adapter); } public Set getPropertyContexts() { Set result = new HashSet(); result.add("http://www.simantics.org/Project-1.0/ProjectBrowseContext"); return result; } public P3DRootNode getRootNode() { return rootNode; } public IMapping getMapping() { return mapping; } }