]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/AbstractDiagramParticipant.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / diagram / participant / AbstractDiagramParticipant.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.diagram.participant;
13
14 import java.lang.reflect.Field;
15
16 import org.simantics.g2d.canvas.ICanvasContext;
17 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
18 import org.simantics.g2d.canvas.impl.DependencyReflection;
19 import org.simantics.g2d.canvas.impl.DependencyReflection.ReferenceDefinition;
20 import org.simantics.g2d.canvas.impl.DependencyReflection.ReferenceType;
21 import org.simantics.g2d.canvas.impl.HintReflection.HintListener;
22 import org.simantics.g2d.diagram.DiagramClass;
23 import org.simantics.g2d.diagram.DiagramHints;
24 import org.simantics.g2d.diagram.IDiagram;
25 import org.simantics.g2d.diagram.handler.DiagramHandler;
26 import org.simantics.utils.datastructures.hints.IHintObservable;
27 import org.simantics.utils.datastructures.hints.IHintContext.Key;
28
29 /**
30  * This is a base implementation for all participants that handle
31  * diagram.  
32  * 
33  * Features:
34  *  - Overrideable onDiagramSet() method
35  *  - diagram -field points to current diagram
36  *  - DiagramHandlers accessible with @Dependency and @Reference annotations
37  * 
38  * TODO add Diagram class handler annotations
39  * @author Toni Kalajainen
40  */
41 public class AbstractDiagramParticipant extends AbstractCanvasParticipant {
42         
43         public IDiagram diagram;
44         public DiagramClass clazz;
45         protected ReferenceDefinition[] handlerDefs;
46         boolean handlerDepsSatisfied = true; 
47                 
48         public AbstractDiagramParticipant() {
49                 super();
50                 
51                 handlerDefs = DependencyReflection.getDependencies(this, ReferenceType.DiagramHandler);         
52         }
53         
54         @HintListener(Class=DiagramHints.class, Field="KEY_DIAGRAM")
55         public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
56                 if (oldValue==newValue) return;
57                 _setDiagram( (IDiagram) newValue );             
58         }
59         @HintListener(Class=DiagramHints.class, Field="KEY_DIAGRAM")
60         public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
61                 _setDiagram(null);              
62         }
63
64         @Override
65         public void addedToContext(ICanvasContext ctx) {
66                 super.addedToContext(ctx);
67                 _setDiagram( (IDiagram) ctx.getHintStack().getHint(DiagramHints.KEY_DIAGRAM) );
68         }
69         
70         @Override
71         public void removedFromContext(ICanvasContext ctx) {
72                 _setDiagram(null);
73                 super.removedFromContext(ctx);
74         }
75         
76         @Override
77         public void assertDependencies() {
78                 super.assertDependencies();
79                 assert(diagram!=null);
80         }
81
82         private void _setDiagram(IDiagram d)
83         {
84                 IDiagram oldDiagram = this.diagram;
85                 this.diagram = d;
86                 if (d!=null) clazz = d.getDiagramClass();
87                 else clazz=null;
88                 
89                 if (clazz!=null) {
90
91                         try {
92                                 for (DiagramHandler h : clazz.getAll()) {
93                                         Class<?> c = h.getClass();
94                                         for (ReferenceDefinition def : handlerDefs)
95                                         {
96                                                 Class<?>        defClass = def.requirement;
97                                                 if (!defClass.isAssignableFrom(c)) continue;
98                                                 Field           f = def.field;
99                                                 //Object                value = f.get(this);
100                                                 //assert(value==null);
101                                                 f.set(this, h);
102                                         }
103                                 }
104                         } catch (Exception e) {
105                                 throw new RuntimeException(e);
106                         }               
107                         handlerDepsSatisfied = checkHandlerDependencies();                      
108                 } else {
109
110                         try {
111                                 for (ReferenceDefinition def : handlerDefs)
112                                 {
113                                         Field           f = def.field;
114                                         f.set(this, null);
115                                 }
116                         } catch (Exception e) {
117                                 throw new RuntimeException(e);
118                         }               
119                         handlerDepsSatisfied = true;
120                 }
121                 onDiagramSet(this.diagram, oldDiagram);
122         }
123         
124         /**
125          * OVERRIDE THIS to hook diagram modifications 
126          * @param newDiagram new diagram or null
127          * @param oldDiagram ..
128          */
129         protected void onDiagramSet(IDiagram newDiagram, IDiagram oldDiagram)
130         {
131         }
132         
133         private boolean checkHandlerDependencies() {
134                 try {
135                         for (ReferenceDefinition rd : handlerDefs) {
136                                 if (!rd.dependency)
137                                         continue;
138                                 Field f = rd.field;
139                                 Object o = f.get(this);
140                                 if (o == null)
141                                         return false;
142                         }
143                 } catch (Exception e) {
144                         throw new RuntimeException(e);
145                 }
146                 return true;
147         }       
148
149         
150         
151 }