]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/Node.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / Node.java
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/Node.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/Node.java
new file mode 100644 (file)
index 0000000..fe66f2b
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.scenegraph;
+
+import java.beans.PropertyChangeListener;\r
+\r
+import org.simantics.scenegraph.utils.NodeUtil;\r
+\r
+/**
+ * @author J-P
+ */
+public abstract class Node implements INode {
+\r
+    private static final long                  serialVersionUID       = -5540999051056414851L;\r
+\r
+    public transient static long               IDCOUNTER              = 1;\r
+
+    protected transient ParentNode<?>          parent                 = null;\r
+    protected transient Location               location               = Location.LOCAL;\r
+\r
+    // This is for internal server communications. Do not touch.
+    // Support for only one listener should be enough, thus we don't need PropertyChangeSupport\r
+    protected transient PropertyChangeListener propertyChangeListener = null;
+
+    protected Long                             id                     = IDCOUNTER++;\r
+\r
+    /**\r
+     * @see org.simantics.scenegraph.INode#getId()\r
+     */\r
+    public Long getId() {
+        return id;
+    }
+
+    /**\r
+     * @see org.simantics.scenegraph.INode#getParent()\r
+     */\r
+    public ParentNode<?> getParent() {
+        return parent;
+    }
+
+    /**\r
+     * @see org.simantics.scenegraph.INode#setParent(org.simantics.scenegraph.ParentNode)\r
+     */\r
+    public void setParent(ParentNode<?> parent) {
+        this.parent = parent;
+    }
+
+    /**\r
+     * The default implementation of {@link #getRootNode()} always asks for the\r
+     * root node from the parent. Scene graph leaf nodes are never considered to\r
+     * be real scene graph root nodes, although they are can be thought of as\r
+     * such when they are not attached to any scene graph. This implementation\r
+     * prevents the need to have a separate rootNodeCache field in all nodes.\r
+     * \r
+     * @see org.simantics.scenegraph.INode#getRootNode()\r
+     */\r
+    public ParentNode<?> getRootNode() {\r
+        return parent != null ? parent.getRootNode() : null;\r
+    }\r
+\r
+    public void remove() {
+        if (parent != null) {\r
+            parent.asyncRemoveNode(this);
+        }
+    }
+
+    /**\r
+     * @see org.simantics.scenegraph.INode#init()\r
+     */\r
+    public void init() {
+    }\r
+    \r
+    public void attach() {\r
+    }\r
+    
+
+    /**\r
+     * @see org.simantics.scenegraph.INode#cleanup()\r
+     */\r
+    public void cleanup() {
+        retractMapping();\r
+    }\r
+\r
+    /**\r
+     * @see org.simantics.scenegraph.INode#delete()\r
+     */\r
+    public void delete() {\r
+        // 1. Remove this node from parent\r
+        parent.asyncRemoveNode(this);\r
+    }\r
+\r
+    /**\r
+     * Remove any ID<->Node mapping this node might have in the scene graph's\r
+     * {@link LookupService}.\r
+     */\r
+    protected void retractMapping() {\r
+        NodeUtil.tryUnmap(this);\r
+    }\r
+\r
+    public <TC> TC appendParent(String id, Class<TC> nc) {\r
+        assert(parent != null);\r
+\r
+        // 0. Find identifier from parent\r
+        String identifier = null;\r
+        for(String s : parent.children.keySet()) { // FIXME: should not be this complicated\r
+            if(parent.children.get(s) == this) { // Find this from parent child list\r
+                identifier = s;\r
+                break;\r
+            }\r
+        }\r
+        if (identifier == null)\r
+            identifier = "" + this.id;\r
+\r
+        // 1. Remove this node from original parent\r
+        parent.unlinkChild(this);\r
+\r
+        // 2. Add new node under parent\r
+        TC instance = parent.addNode(id, nc);\r
+\r
+        // 3. Add this node under new parent\r
+        ((ParentNode<?>)instance).appendChild(identifier, this);\r
+\r
+        return instance;\r
+    }\r
+
+    @Override
+    public String toString() {
+        return getSimpleClassName() + " (" + id + ")";
+    }
+
+    public String getSimpleClassName() {
+        return getSimpleClassName(getClass());
+    }
+
+    public static String getSimpleClassName(Class<?> clazz) {
+        String name = clazz.getSimpleName();
+        int pos = name.indexOf("$$");
+        if (pos >= 0)
+            name = name.substring(0, pos);
+        return name;
+    }\r
+\r
+    /**\r
+     * Associates this node with the specified ID in the {@link ILookupService}\r
+     * that must be offered by the scene graph root node. After this\r
+     * association, one can use {@link NodeUtil#lookup(INode, String)} to lookup\r
+     * this node from the scene graph by its ID.\r
+     * \r
+     * @param id\r
+     * @throws UnsupportedOperationException if no ILookupService is available\r
+     *         for this node\r
+     */\r
+    @ClientSide\r
+    public void setLookupId(String id) {\r
+        NodeUtil.getLookupService(this).map(id, this);\r
+    }\r
+\r
+    /**\r
+     * A shorthand utility for {@link NodeUtil#lookup(INode, String, Class)}.\r
+     * \r
+     * @param id\r
+     * @param clazz\r
+     * @return\r
+     */\r
+    protected <T extends INode> T lookupNode(String id, Class<T> clazz) {\r
+        return NodeUtil.lookup(this, id, clazz);\r
+    }\r
+\r
+    /**\r
+     * A shorthand utility for {@link NodeUtil#lookupId(INode)}).\r
+     * \r
+     * @param node\r
+     * @return\r
+     */\r
+    protected String lookupId(INode node) {\r
+        return NodeUtil.lookupId(node);\r
+    }\r
+\r
+}