Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / android-libraries / TreeViewList / src / pl / polidea / treeview / TreeBuilder.java
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeBuilder.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeBuilder.java
new file mode 100644 (file)
index 0000000..13b499c
--- /dev/null
@@ -0,0 +1,126 @@
+package pl.polidea.treeview;
+
+import android.util.Log;
+
+/**
+ * Allows to build tree easily in sequential mode (you have to know levels of
+ * all the tree elements upfront). You should rather use this class rather than
+ * manager if you build initial tree from some external data source.
+ * 
+ * @param <T>
+ */
+public class TreeBuilder<T> {
+    private static final String TAG = TreeBuilder.class.getSimpleName();
+
+    private final TreeStateManager<T> manager;
+
+    private T lastAddedId = null;
+    private int lastLevel = -1;
+
+    public TreeBuilder(final TreeStateManager<T> manager) {
+        this.manager = manager;
+    }
+
+    public void clear() {
+        manager.clear();
+    }
+
+    /**
+     * Adds new relation to existing tree. Child is set as the last child of the
+     * parent node. Parent has to already exist in the tree, child cannot yet
+     * exist. This method is mostly useful in case you add entries layer by
+     * layer - i.e. first top level entries, then children for all parents, then
+     * grand-children and so on.
+     * 
+     * @param parent
+     *            parent id
+     * @param child
+     *            child id
+     */
+    public synchronized void addRelation(final T parent, final T child) {
+        Log.d(TAG, "Adding relation parent:" + parent + " -> child: " + child);
+        manager.addAfterChild(parent, child, null);
+        lastAddedId = child;
+        lastLevel = manager.getLevel(child);
+    }
+
+    /**
+     * Adds sequentially new node. Using this method is the simplest way of
+     * building tree - if you have all the elements in the sequence as they
+     * should be displayed in fully-expanded tree. You can combine it with add
+     * relation - for example you can add information about few levels using
+     * {@link addRelation} and then after the right level is added as parent,
+     * you can continue adding them using sequential operation.
+     * 
+     * @param id
+     *            id of the node
+     * @param level
+     *            its level
+     */
+    public synchronized void sequentiallyAddNextNode(final T id, final int level) {
+        Log.d(TAG, "Adding sequentiall node " + id + " at level " + level);
+        if (lastAddedId == null) {
+            addNodeToParentOneLevelDown(null, id, level);
+        } else {
+            if (level <= lastLevel) {
+                final T parent = findParentAtLevel(lastAddedId, level - 1);
+                addNodeToParentOneLevelDown(parent, id, level);
+            } else {
+                addNodeToParentOneLevelDown(lastAddedId, id, level);
+            }
+        }
+    }
+
+    /**
+     * Find parent of the node at the level specified.
+     * 
+     * @param node
+     *            node from which we start
+     * @param levelToFind
+     *            level which we are looking for
+     * @return the node found (null if it is topmost node).
+     */
+    private T findParentAtLevel(final T node, final int levelToFind) {
+        T parent = manager.getParent(node);
+        while (parent != null) {
+            if (manager.getLevel(parent) == levelToFind) {
+                break;
+            }
+            parent = manager.getParent(parent);
+        }
+        return parent;
+    }
+
+    /**
+     * Adds note to parent at the level specified. But it verifies that the
+     * level is one level down than the parent!
+     * 
+     * @param parent
+     *            parent parent
+     * @param id
+     *            new node id
+     * @param level
+     *            should always be parent's level + 1
+     */
+    private void addNodeToParentOneLevelDown(final T parent, final T id,
+            final int level) {
+        if (parent == null && level != 0) {
+            throw new TreeConfigurationException("Trying to add new id " + id
+                    + " to top level with level != 0 (" + level + ")");
+        }
+        if (parent != null && manager.getLevel(parent) != level - 1) {
+            throw new TreeConfigurationException("Trying to add new id " + id
+                    + " <" + level + "> to " + parent + " <"
+                    + manager.getLevel(parent)
+                    + ">. The difference in levels up is bigger than 1.");
+        }
+        manager.addAfterChild(parent, id, null);
+        setLastAdded(id, level);
+    }
+
+    private void setLastAdded(final T id, final int level) {
+        lastAddedId = id;
+        lastLevel = level;
+    }
+
+}