--- /dev/null
+package org.simantics.g2d.element.impl;\r
+\r
+import java.util.Map;\r
+\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.ElementAdapter;\r
+import org.simantics.g2d.element.handler.LifeCycle;\r
+import org.simantics.utils.datastructures.hints.HintContext;\r
+import org.simantics.utils.datastructures.hints.HintStack;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class MutatedElement extends HintStack implements IElement {\r
+\r
+ IDiagram diagram;\r
+ IElement orig;\r
+ ElementClass origClass;\r
+ HintContext mutations;\r
+\r
+ public MutatedElement(IElement orig) {\r
+ if (orig == null)\r
+ throw new IllegalArgumentException("null arg");\r
+ this.orig = orig;\r
+ this.origClass = orig.getElementClass();\r
+ this.addHintContext(orig, 0);\r
+ }\r
+\r
+ @Override\r
+ public void addedToDiagram(IDiagram ctx) {\r
+ this.diagram = ctx;\r
+ }\r
+\r
+ @Override\r
+ public IDiagram getDiagram() {\r
+ assert diagram != null;\r
+ return diagram;\r
+ }\r
+\r
+ @Override\r
+ public IDiagram peekDiagram() {\r
+ return diagram;\r
+ }\r
+\r
+ @Override\r
+ public ElementClass getElementClass() {\r
+ return origClass;\r
+ }\r
+\r
+ @Override\r
+ public synchronized void clearWithoutNotification() {\r
+ if (mutations != null)\r
+ mutations.clearWithoutNotification();\r
+ }\r
+\r
+ @Override\r
+ public synchronized <E> E removeHint(Key key) {\r
+ if (key == null)\r
+ throw new IllegalArgumentException("key is null");\r
+ if (mutations == null)\r
+ return null;\r
+ E result = mutations.removeHint(key);\r
+ if (mutations.size() == 0) {\r
+ removeHintContext(mutations);\r
+ mutations = null;\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public synchronized void setHint(Key key, Object value) {\r
+ if (key == null)\r
+ throw new IllegalArgumentException("key is null");\r
+ if (value == null)\r
+ throw new IllegalArgumentException("value is null");\r
+ if (!key.isValueAccepted(value))\r
+ throw new RuntimeException("Value \"" + value + "\" is not accepted with key " + key.getClass().getName());\r
+ if (mutations == null) {\r
+ mutations = new HintContext();\r
+ addHintContext(mutations, 10);\r
+ }\r
+ mutations.setHint(key, value);\r
+ }\r
+\r
+ @Override\r
+ public synchronized void setHints(Map<Key, Object> hints) {\r
+ if (mutations == null) {\r
+ mutations = new HintContext();\r
+ addHintContext(mutations, 10);\r
+ }\r
+ mutations.setHints(hints);\r
+ }\r
+\r
+ @Override\r
+ public void destroy() {\r
+ for (LifeCycle lc : getElementClass().getItemsByClass(LifeCycle.class))\r
+ lc.onElementDestroyed(this);\r
+ dispose();\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ if (mutations != null)\r
+ this.removeHintContext(mutations);\r
+ this.removeHintContext(orig);\r
+ orig = null;\r
+ origClass = null;\r
+ mutations = null;\r
+ }\r
+\r
+ @SuppressWarnings({ "rawtypes", "unchecked" })\r
+ public Object getAdapter(Class adapter) {\r
+ for (ElementAdapter ea : getElementClass().getItemsByClass(ElementAdapter.class)) {\r
+ Object result = ea.adapt(this, adapter);\r
+ if (result != null)\r
+ return result;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return orig != null ? orig.hashCode() : 0;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ return orig == null ? false : orig.equals(obj);\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "MutatedElement[" + orig + " " + origClass + "]";\r
+ }\r
+\r
+}\r