]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorBase.java
fe7a2833bda73525a90b19f276d01582b59de031
[simantics/3d.git] / org.simantics.proconf.g3d / src / org / simantics / proconf / g3d / base / ThreeDimensionalEditorBase.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.proconf.g3d.base;\r
12 \r
13 import java.awt.event.MouseEvent;\r
14 import java.util.ArrayList;\r
15 import java.util.List;\r
16 \r
17 import javax.vecmath.Tuple3d;\r
18 import javax.vecmath.Vector3d;\r
19 \r
20 import org.eclipse.jface.action.Action;\r
21 import org.eclipse.jface.action.IMenuListener;\r
22 import org.eclipse.jface.action.IMenuManager;\r
23 import org.eclipse.jface.action.IToolBarManager;\r
24 import org.eclipse.jface.action.MenuManager;\r
25 import org.eclipse.jface.action.Separator;\r
26 import org.eclipse.jface.dialogs.MessageDialog;\r
27 import org.eclipse.jface.viewers.ISelection;\r
28 import org.eclipse.jface.viewers.ISelectionChangedListener;\r
29 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
30 import org.eclipse.swt.events.PaintEvent;\r
31 import org.eclipse.swt.events.PaintListener;\r
32 import org.eclipse.swt.graphics.Point;\r
33 import org.eclipse.swt.widgets.Composite;\r
34 import org.eclipse.swt.widgets.Menu;\r
35 import org.eclipse.ui.IActionBars;\r
36 import org.eclipse.ui.ISharedImages;\r
37 import org.eclipse.ui.IWorkbenchActionConstants;\r
38 import org.eclipse.ui.IWorkbenchPart;\r
39 import org.eclipse.ui.PlatformUI;\r
40 import org.eclipse.ui.internal.WorkbenchWindow;\r
41 import org.simantics.db.Graph;\r
42 import org.simantics.db.GraphRequestAdapter;\r
43 import org.simantics.db.GraphRequestStatus;\r
44 import org.simantics.db.Resource;\r
45 import org.simantics.db.Session;\r
46 import org.simantics.db.events.GraphChangeEvent;\r
47 import org.simantics.db.management.ISessionContext;\r
48 import org.simantics.layer0.utils.EntityFactory;\r
49 import org.simantics.layer0.utils.IEntity;\r
50 import org.simantics.proconf.g3d.Activator;\r
51 import org.simantics.proconf.g3d.actions.CameraAction;\r
52 import org.simantics.proconf.g3d.actions.ContextAction;\r
53 import org.simantics.proconf.g3d.actions.InteractiveAction;\r
54 import org.simantics.proconf.g3d.base.SelectionAdapter.SelectionType;\r
55 import org.simantics.proconf.g3d.common.JmeComposite;\r
56 import org.simantics.proconf.g3d.common.JmeSinglePassRenderingComponent;\r
57 import org.simantics.proconf.g3d.common.OrbitalCamera;\r
58 import org.simantics.proconf.g3d.dialogs.JMEDialog;\r
59 import org.simantics.proconf.g3d.dnd.ShapeDropTarget;\r
60 import org.simantics.proconf.g3d.gizmo.Gizmo;\r
61 import org.simantics.proconf.g3d.input.InputProvider;\r
62 import org.simantics.proconf.g3d.input.SWTInputProvider;\r
63 import org.simantics.proconf.g3d.scenegraph.IGeometryNode;\r
64 import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
65 import org.simantics.proconf.g3d.tools.ScenegraphLockTraverser;\r
66 import org.simantics.utils.ErrorLogger;\r
67 import org.simantics.utils.ui.jface.MenuTools;\r
68 \r
69 import com.jme.math.Ray;\r
70 import com.jme.math.Vector2f;\r
71 import com.jme.math.Vector3f;\r
72 import com.jme.renderer.ColorRGBA;\r
73 \r
74 \r
75 public abstract class ThreeDimensionalEditorBase implements  Runnable {\r
76 \r
77         private Resource inputResource;\r
78         \r
79         private List<EditorContribution> editorContributions = new ArrayList<EditorContribution>();\r
80         \r
81         private EditorContribution currentEditorContribution;\r
82         \r
83     protected List<ContextAction> actions = new ArrayList<ContextAction>();\r
84     \r
85     private List<Action> contributionSelectionActions = new ArrayList<Action>();\r
86       \r
87     protected Composite parent;\r
88     \r
89     protected ISessionContext sessionContext;\r
90     \r
91     protected Session session;\r
92     \r
93     protected ScenegraphAdapter adapter;\r
94     \r
95     protected SelectionAdapter selectionAdapter;\r
96     \r
97     protected Action refreshAction;\r
98     \r
99     protected Action configureJMEAction;\r
100     \r
101     private Action lockScenegraphAction;\r
102 \r
103     protected Menu contextMenu;\r
104 \r
105     private JmeComposite renderingComposite = null;  \r
106 \r
107     protected OrbitalCamera camera = new OrbitalCamera();\r
108 \r
109     protected boolean viewChanged = true;\r
110 \r
111     private InteractiveAction currentAction = null;\r
112     \r
113     private Gizmo currentGizmo = null;\r
114     \r
115     private InteractiveAction cameraAction = null;\r
116     \r
117     private JmeRenderingComponent component = null;\r
118     \r
119     protected InputProvider input = null;\r
120     \r
121     protected ShapeDropTarget dropTarget;\r
122 \r
123 //    protected IEditorActionBarContributor actionBarContributor;\r
124     protected IActionBars actionBars;\r
125     protected IToolBarManager toolBarManager;\r
126     protected IMenuManager menuManager;\r
127     \r
128     public ThreeDimensionalEditorBase(ISessionContext session) {\r
129         this.sessionContext = session;\r
130         this.session = session.getSession();\r
131         component = new JmeSinglePassRenderingComponent();\r
132     }\r
133 \r
134     public ThreeDimensionalEditorBase(ISessionContext session, JmeRenderingComponent component) {\r
135         this.sessionContext = session;\r
136         this.session = session.getSession();\r
137         this.component = component;\r
138     }\r
139     \r
140 //    public void setActionBarContributor(IEditorActionBarContributor contributor) {\r
141 //      actionBarContributor = contributor;\r
142 //    }\r
143     \r
144     public void setActionBars(IActionBars actionBars) {\r
145         this.actionBars = actionBars;\r
146         this.menuManager = actionBars.getMenuManager();\r
147         this.toolBarManager = actionBars.getToolBarManager();\r
148     }\r
149     \r
150    \r
151     \r
152     \r
153     public ISessionContext getSessionContext() {\r
154         return sessionContext;\r
155     }\r
156     \r
157     public Session getSession() {\r
158         return session;\r
159     }\r
160     \r
161     /**\r
162      * Creates basic UI for ThreeDimenionalEditors.\r
163      * Note : inputResource has not been set at this point.\r
164      * \r
165      * @param graph\r
166      * @param parent\r
167      */\r
168     public void createControl(Graph graph, Composite parent) {\r
169         this.parent = parent;\r
170         renderingComposite = new JmeComposite(parent,component);\r
171         // add listeners to force repaint on size changes\r
172         renderingComposite.getCanvas().addPaintListener(new PaintListener() {\r
173                 public void paintControl(PaintEvent e) {\r
174                         viewChanged = true;     \r
175                 }\r
176         });\r
177 \r
178         \r
179         input = new SWTInputProvider();\r
180         \r
181         renderingComposite.initGL();\r
182         camera.setCamera(component.getCamera());\r
183         camera.updateCamera();  \r
184         makeActions(graph);\r
185         hookContextMenu();\r
186 \r
187         // provide selection events for properies view\r
188         this.adapter = createScenegraphAdapter();\r
189         this.selectionAdapter = createSelectionAdapter();\r
190         \r
191         this.selectionAdapter.addSelectionChangedListener(new ISelectionChangedListener() {\r
192                 public void selectionChanged(SelectionChangedEvent event) {\r
193                         setCurrentAction(getDefaultAction());   \r
194                 }\r
195         });\r
196         hookDragAndDrop();      \r
197         hookInput();\r
198         VisualizationScheduler.getInstance().addVisualization(this);\r
199         \r
200         if (editorContributions.size() > 0) {\r
201             //  setActiveEditorContribution(editorContributions.get(0));\r
202            // } else if (editorContributions.size() > 1) {\r
203                 // create actions for selecting contribution\r
204                 for (EditorContribution ec : editorContributions) {\r
205                         final EditorContribution e = ec;\r
206                         Action a = new Action(e.getName(),Action.AS_RADIO_BUTTON) {\r
207                                 @Override\r
208                                 public void run() {\r
209                                         \r
210                                         setActiveEditorContribution(e);\r
211                                 }\r
212                         };\r
213                         contributionSelectionActions.add(a);\r
214                         \r
215                 }\r
216          }\r
217        \r
218     }\r
219     \r
220     public void addEditorContribution(EditorContribution e) {\r
221         if (parent != null)\r
222                 throw new RuntimeException("Editor contributions must be added before editor is created.");\r
223         editorContributions.add(e);\r
224     }\r
225     \r
226     private void initializeEditorContributions(Graph graph) {\r
227          for (EditorContribution e : editorContributions) {\r
228                 e.initialize(graph);\r
229          }\r
230          if (editorContributions.size() > 0)\r
231                  parent.getDisplay().asyncExec(new Runnable() {\r
232                          @Override\r
233                         public void run() {\r
234                                  setActiveEditorContribution(editorContributions.get(0));\r
235                         }\r
236                  });     \r
237     }\r
238     \r
239     \r
240     private void hookInput() {\r
241         renderingComposite.getCanvas().addKeyListener((SWTInputProvider) input);\r
242         renderingComposite.getCanvas().addMouseListener((SWTInputProvider) input);\r
243         renderingComposite.getCanvas().addMouseMoveListener((SWTInputProvider) input);\r
244         renderingComposite.getCanvas().addMouseTrackListener((SWTInputProvider) input);\r
245         renderingComposite.getCanvas().addFocusListener((SWTInputProvider) input);\r
246     }\r
247     \r
248     protected abstract ScenegraphAdapter createScenegraphAdapter();\r
249     protected abstract SelectionAdapter createSelectionAdapter();\r
250 \r
251     \r
252     public JmeComposite getRenderingComposite() {\r
253         return renderingComposite;\r
254    }\r
255     \r
256     public JmeRenderingComponent getRenderingComponent() {\r
257       return component;\r
258     }\r
259 \r
260     public ScenegraphAdapter getScenegraphAdapter() {\r
261         return adapter;\r
262     }\r
263     \r
264     public SelectionAdapter getSelectionAdapter() {\r
265         return selectionAdapter;\r
266     }\r
267 \r
268     public OrbitalCamera getCamera() {\r
269         return camera;\r
270     }\r
271     \r
272     public void setViewChanged(boolean b) {\r
273         viewChanged = b;\r
274     }\r
275 \r
276     protected void hookContextMenu() {\r
277         MenuManager menuMgr = new MenuManager("#PopupMenu");\r
278         menuMgr.setRemoveAllWhenShown(true);\r
279         menuMgr.addMenuListener(new IMenuListener() {\r
280             public void menuAboutToShow(IMenuManager manager) {\r
281                 final IMenuManager m = manager;\r
282                 GraphRequestAdapter r = new GraphRequestAdapter() {\r
283                         @Override\r
284                         public GraphRequestStatus perform(Graph g) throws Exception {\r
285                                 ThreeDimensionalEditorBase.this.fillContextMenu(g,m);\r
286                                 return GraphRequestStatus.transactionComplete();\r
287                         }\r
288                 };\r
289                 \r
290                 session.syncRead(r);\r
291                 \r
292             }\r
293         });\r
294 \r
295         contextMenu = menuMgr.createContextMenu(renderingComposite);\r
296     }\r
297 \r
298     \r
299 \r
300     protected void fillContextMenu(Graph graph,IMenuManager manager) {\r
301         manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));\r
302         \r
303         List<Resource> selected = selectionAdapter.getSelectedResources();\r
304         for (ContextAction action : actions) {\r
305             if(action.usable(graph,selected)) {\r
306                 manager.add(action);\r
307             }\r
308         }\r
309         if (currentEditorContribution != null) {\r
310                 currentEditorContribution.fillContextMenu(graph, manager, selectionAdapter.getCurrentSelection());\r
311                 for (ContextAction action : currentEditorContribution.getActions()) {\r
312                         if(action.usable(graph,selected)) {\r
313                                 manager.add(action);\r
314                 }\r
315             }\r
316         }\r
317 \r
318     }\r
319 \r
320     protected void fillLocalToolBar() {\r
321 \r
322         if (currentEditorContribution != null)\r
323                 currentEditorContribution.fillLocalToolBar(toolBarManager);\r
324     }\r
325     \r
326     protected void fillLocalPullDown() {\r
327         for (Action a : contributionSelectionActions) {\r
328                 IMenuManager menu = MenuTools.getOrCreate(getMenuID(),"View", menuManager);\r
329                 menu.add(a);\r
330         }\r
331         MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(refreshAction);\r
332         if (configureJMEAction != null) {\r
333                 MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(configureJMEAction);\r
334         }\r
335 \r
336         MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(lockScenegraphAction);\r
337         if (currentEditorContribution != null)\r
338                 currentEditorContribution.fillLocalPullDown(menuManager);\r
339     }\r
340     \r
341     public String getMenuID() {\r
342         return Long.toString(getInputResource().getResourceId());\r
343     }\r
344 \r
345     protected void makeActions(Graph graph) {\r
346         \r
347         refreshAction = new Action() {\r
348 \r
349             public void run() {\r
350                 GraphRequestAdapter r = new GraphRequestAdapter() {\r
351                         public GraphRequestStatus perform(Graph g) throws Exception {\r
352 //                               Stack<IGraphicsNode> stack = new Stack<IGraphicsNode>();\r
353 //                         stack.push(adapter.getNode(adapter.getRootResource()));\r
354 //                         while(!stack.isEmpty()) {\r
355 //                             IGraphicsNode node = stack.pop();\r
356 //                             stack.addAll(node.getChildren());\r
357 //                             if (node instanceof IGeometryNode) {\r
358 //                                 ((IGeometryNode)node).updateGeometry(g);\r
359 //                             }\r
360 //                         }\r
361                                  for (IGraphicsNode node : adapter.getNodes())\r
362                                          if (node instanceof IGeometryNode)\r
363                                                  ((IGeometryNode)node).updateGeometry(g);\r
364                          viewChanged = true;\r
365                          return GraphRequestStatus.transactionComplete();\r
366                         };\r
367                 };\r
368                 session.asyncRead(r);\r
369                \r
370             }\r
371         };\r
372         refreshAction.setText("Refresh");\r
373         refreshAction.setToolTipText("Refreshes the visualization");\r
374         refreshAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(\r
375                 ISharedImages.IMG_TOOL_UP));\r
376         if (getRenderingComponent() instanceof JmeSinglePassRenderingComponent) {\r
377                 configureJMEAction = new Action() {\r
378                         public void run() {\r
379                                 JmeSinglePassRenderingComponent c = (JmeSinglePassRenderingComponent)getRenderingComponent();\r
380                                 JMEDialog dialog = new JMEDialog(ThreeDimensionalEditorBase.this.parent.getShell());\r
381                                 c.getDisplaySystem().setCurrent();\r
382                                 dialog.setBounds(c.isShowBounds());\r
383                                 dialog.setNormals(c.isShowNormals());\r
384                                 dialog.setWireframe(c.isShowWireframe());\r
385                                 ColorRGBA col = c.getDisplaySystem().getRenderer().getBackgroundColor();\r
386                                 dialog.setFloatColor(new float[]{col.r,col.g,col.b});\r
387                                 if (dialog.open() == JMEDialog.CANCEL)\r
388                                         return;\r
389                                 c.setShowBounds(dialog.isBounds());\r
390                                 c.setShowNormals(dialog.isNormals());\r
391                                 c.setShowWireframe(dialog.isWireframe());\r
392                                 if (dialog.getFloatColor() != null) {\r
393                                         c.getDisplaySystem().setCurrent();\r
394                                         c.getDisplaySystem().getRenderer().setBackgroundColor(new ColorRGBA(dialog.getFloatColor()[0],dialog.getFloatColor()[1],dialog.getFloatColor()[2],0.f));\r
395                                 }\r
396                         }\r
397                 };\r
398                 configureJMEAction.setText("Configure JME");\r
399                 configureJMEAction.setImageDescriptor(Activator.imageDescriptorFromPlugin("fi.vtt.proconf.ode", "icons/silk/wrench.png"));\r
400         }\r
401         \r
402         lockScenegraphAction = new Action("Lock scenegraph",Action.AS_CHECK_BOX) {\r
403                 public void run() {\r
404                         new ScenegraphLockTraverser(adapter.getRoot(),this.isChecked());\r
405                 }\r
406         };\r
407         \r
408         cameraAction = new CameraAction(this); \r
409         currentAction = cameraAction;\r
410         \r
411         \r
412     }\r
413     \r
414     public InteractiveAction getDefaultAction() {\r
415         return cameraAction;\r
416     }\r
417     \r
418     public void createPickRay(Vector3d o, Vector3d d) {\r
419         Ray r = createPickRay();\r
420         o.x = r.origin.x;\r
421         o.y = r.origin.y;\r
422         o.z = r.origin.z;\r
423         d.x = r.direction.x;\r
424         d.y = r.direction.y;\r
425         d.z = r.direction.z;\r
426         d.normalize();\r
427     }\r
428     \r
429     public Ray createPickRay() {\r
430         Vector2f screenPos = new Vector2f();\r
431                 screenPos.set(input.mouseX(),renderingComposite.getBounds().height - input.mouseY());\r
432                 \r
433                 \r
434                 Ray mouseRay;\r
435                 if (component.getCamera().isParallelProjection()) {\r
436                         Vector3f worldCoords = renderingComposite.getDisplaySystem().getWorldCoordinates(screenPos, 0.0f);\r
437                         mouseRay = new Ray(worldCoords,\r
438                                 component.getCamera().getDirection());\r
439                 } else {\r
440                         Vector3f worldCoords = renderingComposite.getDisplaySystem().getWorldCoordinates(screenPos, 1.0f);\r
441                         mouseRay = new Ray(component.getCamera().getLocation(), worldCoords\r
442                                         .subtractLocal(component.getCamera().getLocation()));\r
443                 }\r
444                 return mouseRay;\r
445     }\r
446     \r
447     public Vector2f getScreenCoord(Tuple3d worldCoord) {\r
448         Vector3f v = renderingComposite.getDisplaySystem().getScreenCoordinates(VecmathJmeTools.get(worldCoord));\r
449         return new Vector2f(v.x,v.y);\r
450     }\r
451     \r
452     \r
453     public InputProvider getInputProvider() {\r
454         return input;\r
455     }\r
456 \r
457     /**\r
458      * Changes current action \r
459      * \r
460      * @param type\r
461      */\r
462     public void setCurrentAction(InteractiveAction action) {\r
463         if (currentAction == action)\r
464                 return;\r
465         if (toolBarManager != null) {\r
466                 toolBarManager.removeAll();\r
467                 fillLocalToolBar();\r
468         }\r
469         if (currentAction != null)\r
470             currentAction.deactivate();\r
471         currentAction = action;\r
472         if (currentAction != null) {\r
473             currentAction.activate();\r
474             if (toolBarManager != null) {\r
475                 currentAction.fillToolBar(toolBarManager);\r
476             }\r
477         }\r
478         \r
479         updateBars();\r
480     }\r
481     \r
482     public InteractiveAction getCurrentAction() {\r
483         return currentAction;\r
484     }\r
485     \r
486     public void setActiveEditorContribution(EditorContribution contribution) {\r
487         if (currentEditorContribution == contribution)\r
488                 return;\r
489         if (currentAction != getDefaultAction())\r
490                 return;\r
491         if (currentEditorContribution != null)\r
492                 currentEditorContribution.disposeControl();\r
493         currentEditorContribution = contribution;\r
494         int index = editorContributions.indexOf(contribution);\r
495         for (int i = 0; i < contributionSelectionActions.size(); i++) {\r
496                 if (i != index)\r
497                         contributionSelectionActions.get(i).setChecked(false);\r
498                 else\r
499                         contributionSelectionActions.get(i).setChecked(true);\r
500         }\r
501         if (currentEditorContribution != null)\r
502                 currentEditorContribution.createControl(parent);\r
503         \r
504         actionBars.clearGlobalActionHandlers();\r
505         \r
506         parent.layout(true, true);\r
507         if (toolBarManager != null) {\r
508                 toolBarManager.removeAll();\r
509                 fillLocalToolBar();\r
510         }\r
511         if (menuManager != null) {              \r
512                 menuManager.removeAll();\r
513                 fillLocalPullDown();\r
514         }\r
515         \r
516         updateBars();\r
517     }\r
518     \r
519     protected void updateBars() {\r
520         // TODO : actionBars.updateActionBars does not update toolbar, updating toolBar directly layouts code \r
521         //        generated widgets top of contributed (extension) widgets. Only way to achieve proper update\r
522         //        is to use WorkbenchWindow.getCoolBarManager.update(true)\r
523         actionBars.updateActionBars();\r
524 //      if (toolBarManager != null) {\r
525 //              toolBarManager.update(true);\r
526 //      }\r
527         WorkbenchWindow w = (WorkbenchWindow)PlatformUI.getWorkbench().getActiveWorkbenchWindow();\r
528         w.getCoolBarManager().update(true);\r
529     }\r
530     \r
531     public void setGizmo(Gizmo gizmo) {\r
532         if (currentGizmo != null) {\r
533                 currentGizmo.getNode().removeFromParent();\r
534         }\r
535         currentGizmo = gizmo;\r
536         selectionAdapter.setCurrentGizmo(gizmo);\r
537         viewChanged = true;\r
538     }\r
539     \r
540 //    public void setInfoText(String text) {\r
541 //        if (useInfoComposite) {\r
542 //            infoText.setText(text);\r
543 //        }\r
544 //    }\r
545 \r
546     public void showMessage(String message) {\r
547         MessageDialog.openInformation(parent.getShell(), "Shape Editor", //$NON-NLS-1$\r
548                 message);\r
549     }\r
550 \r
551 \r
552     /**\r
553      * Passing the focus request to the viewer's control.\r
554      */\r
555     public void setFocus() {\r
556         renderingComposite.getCanvas().setFocus();\r
557     }\r
558 \r
559     public void dispose() {\r
560         //System.out.println("ThreeDimensionalEditorBase.dispose()");\r
561         VisualizationScheduler.getInstance().removeVisualization(this);\r
562 \r
563         if (currentAction != null)\r
564             currentAction.deactivate();\r
565 \r
566         for (EditorContribution e : editorContributions)\r
567                 e.dispose();\r
568         \r
569         renderingComposite.dispose();\r
570 \r
571         // copy of the set is needed to avoid ConcurrentModificationException\r
572         adapter.dispose();\r
573         component.dispose();\r
574     }\r
575 \r
576     public final void reload(Graph g, Resource res) {\r
577         inputResource = res;\r
578         reloadFrom(EntityFactory.create(g, res));\r
579         // at this point we can initialize editor contributions, which may require inputResource\r
580         initializeEditorContributions(g);\r
581     }\r
582 \r
583     public Resource getInputResource() {\r
584         return inputResource;\r
585     }\r
586     \r
587     public void update(GraphChangeEvent event) {\r
588 //        System.out.println("Transaction " + this + " : " + event.getTransactionId() + " Arg1: " + event.getArg1()\r
589 //                + " arg2: " + event.getArg2() + " sender: " + event.getSender() + " source: " + event.getSource());\r
590         \r
591 //        if (event.added.size() > 0) {\r
592 //            System.out.println("Added:");\r
593 //            for (Triplet t : event.added)\r
594 //                System.out.println(t);\r
595 //        }\r
596 //        if (event.changed.size() > 0) {\r
597 //            System.out.println("Changed:");\r
598 //            for (Triplet t : event.changed)\r
599 //                System.out.println(t);\r
600 //        }\r
601 //        if (event.removed.size() > 0) {\r
602 //            System.out.println("Removed:");\r
603 //            for (Triplet t : event.removed)\r
604 //                System.out.println(t);\r
605 //        }\r
606 \r
607     }\r
608 \r
609     \r
610 \r
611     /**\r
612      * Loads the initial scene: all further updates to the view are done by\r
613      * listening changes in the shapes and int the shape group\r
614      * \r
615      * @param resource\r
616      */\r
617     protected abstract void reloadFrom(IEntity thing);\r
618 \r
619 \r
620         protected void viewUpdated() {\r
621 \r
622         }\r
623 \r
624     /*\r
625      * (non-Javadoc)\r
626      * \r
627      * @see java.lang.Runnable#run()\r
628      */\r
629     public void run() {\r
630         if (currentEditorContribution != null)\r
631                 currentEditorContribution.run();\r
632         if (parent.isDisposed() || !parent.isVisible())\r
633                         return;\r
634         //renderingComposite.getDisplaySystem().setCurrent();\r
635                 input.update();\r
636                 if (input.mouseClicked()) {\r
637                         int downMask = MouseEvent.CTRL_DOWN_MASK;\r
638 \r
639                         if ((input.clickModifiers() & downMask) > 0) {\r
640                                 selectionAdapter.setSelectionType(SelectionType.MODIFY);\r
641                         } else {\r
642                                 selectionAdapter.setSelectionType(SelectionType.SET);\r
643                         }\r
644                 }\r
645                 if (input.mouseMoved()) {\r
646                         Ray mouseRay = createPickRay();\r
647                         selectionAdapter.updateHighlights(mouseRay);\r
648                 }\r
649                 if (currentAction == cameraAction && input.mouseClicked()) {\r
650                         selectionAdapter.pickHighlighted();\r
651                 }\r
652                 if (currentAction == cameraAction && input.mousePressed()\r
653                                 && (input.pressModifiers() & MouseEvent.BUTTON3_MASK) > 0) {\r
654                         Point p = renderingComposite.toDisplay(input.mouseX(), input\r
655                                         .mouseY());\r
656                         contextMenu.setLocation(p.x, p.y);\r
657                         contextMenu.setVisible(true);\r
658                 }\r
659 \r
660                 if (currentAction != null)\r
661                         try {\r
662                                 currentAction.update();\r
663                         } catch (Exception e) {\r
664                                 ErrorLogger.defaultLogError("Action error!", e);\r
665                                 setCurrentAction(getDefaultAction());\r
666                         }\r
667 \r
668                 if (component.update())\r
669                         viewChanged = true;\r
670                     \r
671                 if (!geometryUpdateRequestAdapter.isRunning() && adapter.needsUpdateGeometry()) {\r
672                         session.asyncRead(geometryUpdateRequestAdapter);        \r
673                 }\r
674                 \r
675                 viewChanged |= adapter.isChanged();\r
676                  if (viewChanged) {\r
677                         viewChanged = false;\r
678                         adapter.setChanged(false);\r
679                         camera.updateCamera();\r
680                         viewUpdated();\r
681                         component.render();\r
682                 }\r
683         }\r
684     // TODO : there is some sort of synchronization bug in rendering:\r
685     //        part of the rendered objects are rendered with different camera transformation than others.\r
686     //        re-rendering the scene hides the worst problems.\r
687     //        Using shadows is the reason: shadowed objects are rendered with different transformation than non-shadowed.\r
688     //private boolean lastChanged = false;\r
689     \r
690     private GeometryUpdateRequestAdapter geometryUpdateRequestAdapter = new GeometryUpdateRequestAdapter();\r
691         \r
692     private class GeometryUpdateRequestAdapter extends GraphRequestAdapter {\r
693         private boolean running;\r
694         @Override\r
695                 public GraphRequestStatus perform(Graph g) throws Exception {\r
696                 running = true;\r
697                         adapter.updateGeometry(g);\r
698                         return GraphRequestStatus.transactionComplete();\r
699                 }\r
700                 @Override\r
701                 public void requestCompleted(GraphRequestStatus status) {\r
702                         running = false;\r
703                         adapter.setChanged(true);\r
704                 }\r
705                 \r
706                 public boolean isRunning() {\r
707                         return running;\r
708                 }\r
709     }\r
710 \r
711    \r
712     \r
713     protected void hookDragAndDrop() {\r
714         dropTarget = new ShapeDropTarget(this);\r
715     }\r
716 \r
717     /**\r
718      * Receives selection changes\r
719      * \r
720      * @param part\r
721      * @param selection\r
722      */\r
723     protected abstract void pageSelectionChanged(IWorkbenchPart part, ISelection selection);\r
724 \r
725     /**\r
726      * EditorPart or ViewPart uses this method to forward getAdapter(Class)\r
727      * @see org.eclipse.ui.part.WorkbenchPart.getAdapter(Class adapter)\r
728      * @param adapter\r
729      * @return\r
730      */\r
731     public Object getAdapter(Class adapter) {\r
732         return null;\r
733     }\r
734 \r
735 }