]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.plant3d/src/org/simantics/plant3d/editor/Plant3DEditor.java
Avoid extra write transactions when opening Plant3D editor
[simantics/3d.git] / org.simantics.plant3d / src / org / simantics / plant3d / editor / Plant3DEditor.java
index f80d3be8d63086c436116f8973e1cceea506697f..b4448e670749caef8e30b8685d33422eb922cb55 100644 (file)
@@ -1,30 +1,41 @@
 package org.simantics.plant3d.editor;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
 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.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.ISelectionProvider;
 import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
 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.Simantics;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
+import org.simantics.db.common.request.ParametrizedRead;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.exception.DatabaseException;
-import org.simantics.g3d.scenegraph.IG3DNode;
+import org.simantics.db.layer0.request.combinations.Combinators;
 import org.simantics.g3d.scenegraph.NodeMap;
 import org.simantics.g3d.scenegraph.RenderListener;
 import org.simantics.g3d.scenegraph.base.INode;
+import org.simantics.g3d.scenegraph.base.ParentNode;
+import org.simantics.g3d.toolbar.ToolComposite;
 import org.simantics.g3d.vtk.action.RemoveAction;
 import org.simantics.g3d.vtk.common.HoverHighlighter;
 import org.simantics.g3d.vtk.common.NodeSelectionProvider2;
@@ -32,6 +43,7 @@ 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.FocusAction;
 import org.simantics.g3d.vtk.swt.InteractiveVtkComposite;
 import org.simantics.g3d.vtk.swt.RotateAction;
 import org.simantics.g3d.vtk.swt.TranslateAction;
@@ -44,15 +56,19 @@ 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.ReversePipeRunAction;
 import org.simantics.plant3d.actions.RoutePipeAction;
+import org.simantics.plant3d.actions.TranslateFreeVariableLengthAction;
 import org.simantics.plant3d.actions.TranslateInlineAction;
 import org.simantics.plant3d.ontology.Plant3D;
 import org.simantics.plant3d.scenegraph.EndComponent;
 import org.simantics.plant3d.scenegraph.Equipment;
 import org.simantics.plant3d.scenegraph.IP3DNode;
+import org.simantics.plant3d.scenegraph.IP3DVisualNode;
 import org.simantics.plant3d.scenegraph.InlineComponent;
 import org.simantics.plant3d.scenegraph.Nozzle;
 import org.simantics.plant3d.scenegraph.P3DRootNode;
+import org.simantics.plant3d.scenegraph.PipeRun;
 import org.simantics.plant3d.scenegraph.PipelineComponent;
 import org.simantics.plant3d.scenegraph.SchemaBuilder;
 import org.simantics.plant3d.scenegraph.TurnComponent;
@@ -65,83 +81,117 @@ 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.ui.workbench.editor.input.InputValidationCombinators;
 import org.simantics.utils.threads.ThreadUtils;
 import org.simantics.utils.ui.ExceptionUtils;
 
 import vtk.vtkActor;
 import vtk.vtkCameraPass;
 import vtk.vtkDefaultPass;
+import vtk.vtkGaussianBlurPass;
 import vtk.vtkLightsPass;
+import vtk.vtkProp3D;
 import vtk.vtkRenderPassCollection;
 import vtk.vtkRenderer;
+import vtk.vtkSSAAPass;
 import vtk.vtkSequencePass;
+import vtk.vtkSimpleMotionBlurPass;
 
 
 public class Plant3DEditor extends ResourceEditorPart {
 
        private Composite parent;
+       protected ToolComposite toolComposite;
        private Resource input;
 //     private InteractiveVtkPanel panel;
 //     private SWTAWTComponent component;
        private InteractiveVtkComposite panel;
+
        
        private P3DRootNode rootNode;
-       private IMapping<Resource,Object> mapping;
+       private IMapping<Resource,INode> mapping;
+       
+       protected NodeSelectionProvider2<Resource, INode> selectionProvider;
        
-       private NodeSelectionProvider2<Resource,Object> 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;
+       protected vtkCameraAndSelectorAction cameraAction;
+       protected FocusAction focusAction;
+       protected TranslateAction translateAction;
+       protected TranslateInlineAction translateInlineAction;
+       protected TranslateFreeVariableLengthAction translateFreeVariableLengthAction;
+       protected RotateAction rotateAction;
+       protected RemoveAction removeAction;
+       protected RemoveAndSplitAction removeSplitAction;
+       protected RoutePipeAction routePipeAction;
+       protected AddComponentAction addComponentAction;
+       protected ReversePipeRunAction reversePipeRunAction;
        
        private P3DNodeMap nodeMap;
        
+       /** Constants for selecting the up-direction */
+       public static final int X = 0, Y = 1, Z = 2;
+       
+       protected int upDirection = 1;
+
+       ParametrizedRead<IResourceEditorInput, Boolean> INPUT_VALIDATOR =
+                       Combinators.compose(
+                                       InputValidationCombinators.hasURI(),
+                                       InputValidationCombinators.extractInputResource()
+                                       );
+
+       @Override
+       protected ParametrizedRead<IResourceEditorInput, Boolean> getInputValidator() {
+               return INPUT_VALIDATOR;
+       }
+
        @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;
-//                     }
-//             };
+
+               activateValidation();
 
                IResourceEditorInput rei = (IResourceEditorInput)getEditorInput();
                input = rei.getResource();
                
+               toolComposite = new ToolComposite(parent, SWT.BORDER);
+           toolComposite.setVisible(true);
+               
                panel = new InteractiveVtkComposite(parent);
                
+               GridLayoutFactory.fillDefaults().margins(0, 0).spacing(0, 0).applyTo(parent);
+        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(getPanel().getComponent());
                
+      
+        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(toolComposite);
+        
                //IActionBars actionBars = getEditorSite().getActionBars();
 
                hookContextMenu();
                
                createScene();
-
-               //component.syncPopulate();
                
                new ContextMenuListener(panel, contextMenu);
                
                cameraAction = createCameraAction();
+               switch (upDirection) {
+               case 0:
+                       cameraAction.setUpDirection(new double[] { 1, 0, 0 });
+                       break;
+               case 1:
+                       cameraAction.setUpDirection(new double[] { 0, 1, 0 });
+                       break;
+               case 2:
+                       cameraAction.setUpDirection(new double[] { 0, 0, 1 });
+                       break;
+               }
+               
                panel.setDefaultAction(cameraAction);
                panel.useDefaultAction();
                panel.setPickType(4);
                
                try {
-                       ControlPointFactory.preloadCache(getLibraryUri());
-                       ComponentUtils.preloadCache();
+                       ControlPointFactory.preloadCache(Simantics.getSession(), getLibraryUri());
+                       ComponentUtils.preloadCache(Simantics.getSession());
                } catch (Exception e) {
                        ExceptionUtils.logAndShowError("Cannot open Plant3D editor",e);
                        return;
@@ -150,19 +200,16 @@ public class Plant3DEditor extends ResourceEditorPart {
                try {
                        getSession().syncRequest(new ReadRequest() {
                                
-                               @SuppressWarnings({ "rawtypes", "unchecked" })
                                @Override
                                public void run(ReadGraph graph) throws DatabaseException {
-                                   System.out.println("START PLANT3D LOAD");
+                                   //System.out.println("START PLANT3D LOAD");
                                        PipingRules.setEnabled(false);
-                                       IMappingSchema<Resource, Object> schema = getSchema(graph);
+                                       IMappingSchema<Resource,INode> 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);
                                            nodeMap = createNodeMap(getSession(), mapping, panel,rootNode);
@@ -171,7 +218,7 @@ public class Plant3DEditor extends ResourceEditorPart {
                         throw new DatabaseException(e);
                     }
                                        
-                                       System.out.println("END PLANT3D LOAD");
+                                       //System.out.println("END PLANT3D LOAD");
                                }
                        });
                        
@@ -213,23 +260,26 @@ public class Plant3DEditor extends ResourceEditorPart {
                }
                
                createActions();
-               
        }
        
+       public void setUpDirection(int upDirection) {
+               this.upDirection = upDirection;
+       }
+
        protected vtkCameraAndSelectorAction createCameraAction() {
            return new vtkCameraAndSelectorAction(panel); 
        }
        
-       protected NodeSelectionProvider2<Resource,Object> createSelectionProvider() {
-           return new NodeSelectionProvider2<Resource,Object>(this,mapping,nodeMap);
+       protected NodeSelectionProvider2<Resource,INode> createSelectionProvider() {
+           return new NodeSelectionProvider2<Resource,INode>(this,mapping,nodeMap);
        }
        
-       protected HoverHighlighter createHoverHighlhighter() {
-           return new HoverHighlighter(panel,nodeMap);
+       protected HoverHighlighter<Resource> createHoverHighlhighter() {
+           return new HoverHighlighter<>(panel,nodeMap);
        }
        
-       protected SelectionHighlighter<INode> createSelectionHighlighter() {
-           return new SelectionHighlighter<INode>(panel,nodeMap);
+       protected SelectionHighlighter<Resource> createSelectionHighlighter() {
+           return new SelectionHighlighter<Resource>(panel,nodeMap);
        }
        
        protected String getLibraryUri() {
@@ -237,18 +287,16 @@ public class Plant3DEditor extends ResourceEditorPart {
        }
        
        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);
-                       }
-               };
-               
+           focusAction = new FocusAction(panel, cameraAction);
+               translateAction = new TranslateAction(panel,nodeMap,toolComposite);
+               translateInlineAction = new TranslateInlineAction(panel, nodeMap,toolComposite);
+               translateFreeVariableLengthAction = new TranslateFreeVariableLengthAction(panel, getRootNode(), toolComposite);
+               rotateAction = new RotateAction(panel,nodeMap,toolComposite);
+               removeAction = new RemoveAction(nodeMap);
                removeSplitAction = new RemoveAndSplitAction(nodeMap);
-               routePipeAction = new RoutePipeAction(panel,rootNode);
+               routePipeAction = new RoutePipeAction(panel,rootNode, toolComposite);
                addComponentAction = new AddComponentAction(panel, rootNode, getLibraryUri());
+               reversePipeRunAction = new ReversePipeRunAction(nodeMap);
        }
        
        public void populate() {
@@ -256,39 +304,52 @@ public class Plant3DEditor extends ResourceEditorPart {
                        
                        @Override
                        public void run() {
+                               nodeMap.setChangeTracking(false);
                                nodeMap.populate();
+                               nodeMap.setChangeTracking(true);
                                panel.addListener(new RenderListener() {
-                    
-                    @Override
-                    public void preRender() {
-                   
-                    }
-                    
-                    @Override
-                    public void postRender() {
-                        try {
-                            P3DUtil.finalizeDBLoad2(rootNode);
-                            if (nodeMap.isRangeModified());
-                                nodeMap.commit("Load sync");
-                        } catch (Exception e) {
-                            //throw new DatabaseException(e);
-                        }
-                        panel.removeListener(this);  
-                        
-                    }
-                });
-                               
+
+                                       @Override
+                                       public void preRender() {
+
+                                       }
+
+                                       @Override
+                                       public void postRender() {
+                                               panel.removeListener(this);
+
+                                               try {
+                                                       P3DUtil.finalizeDBLoad2(rootNode);
+                                                       if (nodeMap.getMapping().isRangeModified())
+                                                               nodeMap.commit("Load sync");
+                                               } catch (Exception e) {
+                                                       ExceptionUtils.logAndShowError("Failed to load model correctly", e);
+                                               }
+                                               
+                                               onEditorInitializationComplete();
+                                               
+                                               List<vtkProp3D> props = new ArrayList<>();
+                                               collectProps(rootNode, props);
+                                               fitToWindow(props);
+                                       }
+                               });
                        }
                });
-               
+
+       }
+
+       /**
+        * This can be overridden by clients to perform extra initialization tasks
+        */
+       protected void onEditorInitializationComplete() {
        }
        
-       protected IMappingSchema<Resource, Object> getSchema(ReadGraph graph) throws DatabaseException {
-               IMappingSchema<Resource,Object> schema = SchemaBuilder.getSchema(graph);
+       protected IMappingSchema<Resource, INode> getSchema(ReadGraph graph) throws DatabaseException {
+               IMappingSchema<Resource,INode> schema = SchemaBuilder.getSchema(graph);
                return schema;
        }
        
-       protected P3DNodeMap createNodeMap(Session session, IMapping<Resource, Object> mapping, VtkView panel, P3DRootNode rootNode) {
+       protected P3DNodeMap createNodeMap(Session session, IMapping<Resource, INode> mapping, VtkView panel, P3DRootNode rootNode) {
                return new P3DNodeMap(session, mapping, panel,rootNode);
        }
        
@@ -298,10 +359,14 @@ public class Plant3DEditor extends ResourceEditorPart {
                panel.getComponent().setFocus();
        }
        
-       private void createScene() {
+       protected void createScene() {
                vtkRenderer ren1 = panel.getRenderer();
                
                boolean multiPass = false;
+               boolean blur = false;
+               boolean ssaa = false;
+               //boolean sobel = true;
+               boolean mblur = false;
                if (multiPass) {
                        
                        vtkLightsPass lightsPass = new vtkLightsPass();
@@ -318,8 +383,26 @@ public class Plant3DEditor extends ResourceEditorPart {
                        vtkCameraPass cameraPass = new vtkCameraPass();
                        cameraPass.SetDelegatePass(seq);
                        
-                       ren1.SetPass(cameraPass);
-                       
+                       if (blur) {
+                           vtkGaussianBlurPass blurPass = new vtkGaussianBlurPass();
+                           blurPass.SetDelegatePass(cameraPass);
+                           ren1.SetPass(blurPass);
+                       } else if (ssaa) {
+                           vtkSSAAPass ssaaPass = new vtkSSAAPass();
+                           ssaaPass.SetDelegatePass(cameraPass);
+                           ren1.SetPass(ssaaPass);
+                       } else if (mblur) {
+                           vtkSimpleMotionBlurPass mBlurPass = new vtkSimpleMotionBlurPass();
+                           mBlurPass.SetDelegatePass(cameraPass);
+                ren1.SetPass(mBlurPass);
+//                     } else if (sobel) {
+//                         vtkSobelGradientMagnitudePass sobelPass = new vtkSobelGradientMagnitudePass();
+//                         sobelPass.SetDelegatePass(sobelPass);
+//                         ren1.SetPass(sobelPass);
+               } else {
+                   ren1.SetPass(cameraPass);
+               }
+                        
                }
 //             ren1.GetRenderWindow().LineSmoothingOn();
 //             ren1.GetRenderWindow().PointSmoothingOn();
@@ -333,14 +416,14 @@ public class Plant3DEditor extends ResourceEditorPart {
                ren1.SetGradientBackground(true);
 
                // vtkActor grid = vtkShape.createGridActor(8,1.0,1|2|4);
-               vtkActor grid = vtkShape.createGridActor(8,1.0, 2 );
+               int dir = 1 << upDirection;
+               vtkActor grid = vtkShape.createGridActor(8, 1.0, dir);
                grid.SetPickable(0);
                ren1.AddActor(grid);
                panel.addDeletable(grid);
                
                AxesDisplay axesDisplay = new AxesDisplay(panel);
                axesDisplay.show();
-               
        }
        
        protected Menu contextMenu;
@@ -358,18 +441,24 @@ public class Plant3DEditor extends ResourceEditorPart {
        }
        
        protected void createContextMenu(IMenuManager m) {
-               List<IG3DNode> selected = selectionProvider.getSelectedNodes();
+               List<INode> selected = selectionProvider.getSelectedNodes();
+               
+               createFocusMenu(m, selected);
+
+               m.add(new Separator());
+               
                try {
                        if (selected.size() == 0) {
-                               for (Item eq : P3DUtil.getEquipments(getLibraryUri())) {
-                                       m.add(new AddEquipmentAction(rootNode, eq));
-                               }
+                           m.add(new AddEquipmentAction(rootNode, getLibraryUri()));
+//                             for (Item eq : P3DUtil.getEquipments(getLibraryUri())) {
+//                                     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(getLibraryUri())) {
+                                       for (Item eq : P3DUtil.getNozzles(Simantics.getSession(), getLibraryUri())) {
                                                AddNozzleAction add = new AddNozzleAction(rootNode, eq);
                                                add.setEquipment((Equipment)node);
                                                m.add(add);
@@ -406,7 +495,10 @@ public class Plant3DEditor extends ResourceEditorPart {
                                } else if (node instanceof InlineComponent) {
                                        //m.add(translateInlineAction);
                                        InlineComponent component = (InlineComponent)node;
-                                       m.add(translateInlineAction);
+                                       if (component.isVariableLength())
+                                           m.add(translateFreeVariableLengthAction);
+                                       else
+                                           m.add(translateInlineAction);
                                        m.add(routePipeAction);
                                        routePipeAction.setComponent(component);
                                        m.add(addComponentAction);
@@ -414,6 +506,10 @@ public class Plant3DEditor extends ResourceEditorPart {
                                        m.add(removeAction);
                                        m.add(removeSplitAction);
                                        removeSplitAction.setNode(node);
+                               } else if (node instanceof PipeRun) {
+                                   m.add(reversePipeRunAction);
+                                   m.add(removeAction);
+                                   reversePipeRunAction.setNode(node);
                                } else {
                                    m.add(removeAction);
                                }
@@ -421,6 +517,7 @@ public class Plant3DEditor extends ResourceEditorPart {
                                
                                translateAction.setNode(node);
                                translateInlineAction.setNode(node);
+                               translateFreeVariableLengthAction.setNode(node);
                                rotateAction.setNode(node);
                                removeAction.setNode(node);
                                
@@ -429,7 +526,44 @@ public class Plant3DEditor extends ResourceEditorPart {
                        ExceptionUtils.logAndShowError(e);
                }
        }
-       
+
+       protected class FitToWindow extends Action {
+               private List<INode> selected;
+               public FitToWindow(List<INode> selected) {
+                       super("Fit to Window");
+                       this.selected = selected;
+                       //setAccelerator('1');
+               }
+               @Override
+               public void run() {
+                       List<vtkProp3D> props = new ArrayList<>();
+                       final Collection<INode> collection = !selected.isEmpty() ? selected : getRootNode().getChild();
+                       for (INode n : collection)
+                               collectProps(n, props);
+
+                       fitToWindow(props);
+                       getPanel().refresh();
+               }
+       }
+
+       protected void createFocusMenu(IMenuManager m, List<INode> selected) {
+               m.add(createFitToWindowAction(selected));
+
+               if (!selected.isEmpty()) {
+                       List<vtkProp3D> actors = new ArrayList<>();
+                       for (INode n : selected)
+                               collectProps(n, actors);
+                       if (actors.size() > 0) {
+                               focusAction.setProps(new ArrayList<>(actors));
+                               m.add(focusAction);
+                       }
+               }
+       }
+
+       protected IAction createFitToWindowAction(List<INode> selected) {
+               return new FitToWindow(selected);
+       }
+
        private IContentOutlinePage createOutline() {
                if (rootNode == null || selectionProvider == null)
                        return null;
@@ -449,30 +583,29 @@ public class Plant3DEditor extends ResourceEditorPart {
                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();
+       public <T> T getAdapter(Class<T> adapter) {
+               if (adapter.isAssignableFrom(IPropertyPage.class))
+                       return adapter.cast(new StandardPropertyPage(getSite(),getPropertyContexts()));
+               if (adapter.isAssignableFrom(ISelectionProvider.class))
+                       return adapter.cast(selectionProvider);
+               if (adapter.isAssignableFrom(IContentOutlinePage.class)) {
+                       return adapter.cast(createOutline());
                }
-               if (NodeMap.class.equals(adapter)) {
-                       return nodeMap;
+               if (adapter.isAssignableFrom(NodeMap.class)) {
+                       return adapter.cast(nodeMap);
                }
-               if (INode.class.equals(adapter)) {
-                       return rootNode;
+               if (adapter.isAssignableFrom(INode.class)) {
+                       return adapter.cast(rootNode);
                }
-               if (IMapping.class.equals(adapter)) {
-                       return mapping;
+               if (adapter.isAssignableFrom(IMapping.class)) {
+                       return adapter.cast(mapping);
                }
-//             if (InteractiveVtkPanel.class.equals(adapter)) {
-//                     return panel;
+//             if (adapter.isAssignableFrom(InteractiveVtkPanel.class)) {
+//                     return adapter.cast(panel);
 //             }
-               if (VtkView.class.equals(adapter))
-                       return panel;
-               if (ISelectionProvider.class.equals(adapter))
-                       return selectionProvider;
+               if (adapter.isAssignableFrom(VtkView.class))
+                       return adapter.cast(panel);
                return super.getAdapter(adapter);
        }
        
@@ -490,11 +623,25 @@ public class Plant3DEditor extends ResourceEditorPart {
                return rootNode;
        }
        
-       public IMapping<Resource, Object> getMapping() {
+       public IMapping<Resource, INode> getMapping() {
                return mapping;
        }
        
        public P3DNodeMap getNodeMap() {
         return nodeMap;
     }
+
+       public void fitToWindow(Collection<vtkProp3D> props) {
+               cameraAction.fitToView(props);
+       }
+
+       protected static void collectProps(INode node, List<vtkProp3D> props) {
+               if (node instanceof IP3DVisualNode)
+                       props.addAll(((IP3DVisualNode) node).getActors());
+               
+               if (node instanceof ParentNode)
+               for (INode n : ((ParentNode<?>) node).getNodes()) {
+                               collectProps(n, props);
+               }
+       }
 }