Added support library for TreeViewList. Previously this code was subsumed in the...
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 27 May 2012 12:48:32 +0000 (12:48 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Sun, 27 May 2012 12:48:32 +0000 (12:48 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@729 180e2498-e6e9-4542-8430-84ac67f01cd8

75 files changed:
android-libraries/TreeViewList/.classpath [new file with mode: 0644]
android-libraries/TreeViewList/.project [new file with mode: 0644]
android-libraries/TreeViewList/AndroidManifest.xml [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter$1.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/BuildConfig.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeNode.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeStateManager.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeAlreadyInTreeException.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeNotInTreeException.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$attr.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$drawable.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$id.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$layout.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$style.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$styleable.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeBuilder.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeConfigurationException.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeNodeInfo.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeStateManager.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList$1.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/overview.html [new file with mode: 0644]
android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/package-info.class [new file with mode: 0644]
android-libraries/TreeViewList/bin/jarlist.cache [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-hdpi/collapsed.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-hdpi/expanded.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-ldpi/collapsed.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-ldpi/expanded.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-ldpi/ic_launcher.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-mdpi/collapsed.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-mdpi/expanded.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable/list_selector_background_disabled.9.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable/list_selector_background_focus.9.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable/list_selector_background_longpress.9.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/res/drawable/list_selector_background_pressed.9.png [new file with mode: 0644]
android-libraries/TreeViewList/bin/treeviewlist.jar [new file with mode: 0644]
android-libraries/TreeViewList/gen/pl/polidea/treeview/BuildConfig.java [new file with mode: 0644]
android-libraries/TreeViewList/gen/pl/polidea/treeview/R.java [new file with mode: 0644]
android-libraries/TreeViewList/proguard.cfg [new file with mode: 0644]
android-libraries/TreeViewList/project.properties [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-hdpi/collapsed.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-hdpi/expanded.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-ldpi/collapsed.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-ldpi/expanded.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-ldpi/ic_launcher.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-mdpi/collapsed.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-mdpi/expanded.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable/divider.xml [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable/list_selector_background.xml [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable/list_selector_background_disabled.9.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable/list_selector_background_focus.9.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable/list_selector_background_longpress.9.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable/list_selector_background_pressed.9.png [new file with mode: 0644]
android-libraries/TreeViewList/res/drawable/list_selector_background_transition.xml [new file with mode: 0644]
android-libraries/TreeViewList/res/layout/tree_list_item_wrapper.xml [new file with mode: 0644]
android-libraries/TreeViewList/res/values/attrs.xml [new file with mode: 0644]
android-libraries/TreeViewList/res/values/styles.xml [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/AbstractTreeViewAdapter.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeNode.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeStateManager.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/NodeAlreadyInTreeException.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/NodeNotInTreeException.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/TreeBuilder.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/TreeConfigurationException.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/TreeNodeInfo.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/TreeStateManager.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/TreeViewList.java [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/overview.html [new file with mode: 0644]
android-libraries/TreeViewList/src/pl/polidea/treeview/package-info.java [new file with mode: 0644]

diff --git a/android-libraries/TreeViewList/.classpath b/android-libraries/TreeViewList/.classpath
new file mode 100644 (file)
index 0000000..a4f1e40
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="src" path="gen"/>\r
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>\r
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>\r
+       <classpathentry kind="output" path="bin/classes"/>\r
+</classpath>\r
diff --git a/android-libraries/TreeViewList/.project b/android-libraries/TreeViewList/.project
new file mode 100644 (file)
index 0000000..c9d4fda
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>TreeViewList</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/android-libraries/TreeViewList/AndroidManifest.xml b/android-libraries/TreeViewList/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..28a7fe0
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"\r
+    package="pl.polidea.treeview"\r
+    android:versionCode="1"\r
+    android:versionName="1.0" >\r
+\r
+    <uses-sdk android:minSdkVersion="7" />\r
+\r
+    <application/>\r
+\r
+</manifest>
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter$1.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter$1.class
new file mode 100644 (file)
index 0000000..2b84661
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter$1.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter.class
new file mode 100644 (file)
index 0000000..40535ba
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/AbstractTreeViewAdapter.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/BuildConfig.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/BuildConfig.class
new file mode 100644 (file)
index 0000000..77562f4
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/BuildConfig.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeNode.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeNode.class
new file mode 100644 (file)
index 0000000..c2a6124
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeNode.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeStateManager.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeStateManager.class
new file mode 100644 (file)
index 0000000..791ae79
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/InMemoryTreeStateManager.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeAlreadyInTreeException.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeAlreadyInTreeException.class
new file mode 100644 (file)
index 0000000..35af40c
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeAlreadyInTreeException.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeNotInTreeException.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeNotInTreeException.class
new file mode 100644 (file)
index 0000000..a981398
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/NodeNotInTreeException.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$attr.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$attr.class
new file mode 100644 (file)
index 0000000..1a7b40c
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$attr.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$drawable.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$drawable.class
new file mode 100644 (file)
index 0000000..f266770
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$drawable.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$id.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$id.class
new file mode 100644 (file)
index 0000000..7f11957
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$id.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$layout.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$layout.class
new file mode 100644 (file)
index 0000000..a13978f
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$layout.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$style.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$style.class
new file mode 100644 (file)
index 0000000..4a475b2
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$style.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$styleable.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$styleable.class
new file mode 100644 (file)
index 0000000..a992b85
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R$styleable.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R.class
new file mode 100644 (file)
index 0000000..ef23d5e
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/R.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeBuilder.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeBuilder.class
new file mode 100644 (file)
index 0000000..4ddc77c
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeBuilder.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeConfigurationException.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeConfigurationException.class
new file mode 100644 (file)
index 0000000..d2e7193
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeConfigurationException.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeNodeInfo.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeNodeInfo.class
new file mode 100644 (file)
index 0000000..683896c
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeNodeInfo.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeStateManager.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeStateManager.class
new file mode 100644 (file)
index 0000000..f3beab5
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeStateManager.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList$1.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList$1.class
new file mode 100644 (file)
index 0000000..2b9baac
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList$1.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList.class
new file mode 100644 (file)
index 0000000..5303999
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/TreeViewList.class differ
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/overview.html b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/overview.html
new file mode 100644 (file)
index 0000000..bdd09ce
--- /dev/null
@@ -0,0 +1,24 @@
+<html>
+<body>
+This is a small utility that provides quite configurable tree view list.
+It is based on standard android list view. It separates out different
+aspects of the tree: there is a separate list view, tree adapter, tree
+state manager and tree state builder.
+<p>
+<ul>
+       <li>Tree view provides the frame to display the view.</li>
+       <li>Adapter allows to create visual representation of each tree
+       node.</li>
+       <li>State manager provides storage for tree state (connections
+       between parents and children, collapsed/expanded state). It provides
+       all the low-level tree manipulation methods.</li>
+       <li>Tree builder allows to build tree easily providing higher
+       level methods. The tree can be build either from prepared sequentially
+       prepared list of nodes (node id, level) or using (parent/child
+       relationships).</li>
+       <p>For now only in-memory state manager is provided, but Tree State
+       Manger interface is done in the way that database tree manager even for
+       large trees is potentially supported.
+</ul>
+</body>
+</html>
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/package-info.class b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/package-info.class
new file mode 100644 (file)
index 0000000..d0a1275
Binary files /dev/null and b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/package-info.class differ
diff --git a/android-libraries/TreeViewList/bin/jarlist.cache b/android-libraries/TreeViewList/bin/jarlist.cache
new file mode 100644 (file)
index 0000000..1b5ec3f
--- /dev/null
@@ -0,0 +1,3 @@
+# cache for current jar dependecy. DO NOT EDIT.
+# format is <lastModified> <length> <SHA-1> <path>
+# Encoding is UTF-8
diff --git a/android-libraries/TreeViewList/bin/res/drawable-hdpi/collapsed.png b/android-libraries/TreeViewList/bin/res/drawable-hdpi/collapsed.png
new file mode 100644 (file)
index 0000000..84ca818
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-hdpi/collapsed.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-hdpi/expanded.png b/android-libraries/TreeViewList/bin/res/drawable-hdpi/expanded.png
new file mode 100644 (file)
index 0000000..2761231
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-hdpi/expanded.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-hdpi/ic_launcher.png b/android-libraries/TreeViewList/bin/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..882eb14
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-hdpi/ic_launcher.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-ldpi/collapsed.png b/android-libraries/TreeViewList/bin/res/drawable-ldpi/collapsed.png
new file mode 100644 (file)
index 0000000..f9c06f4
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-ldpi/collapsed.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-ldpi/expanded.png b/android-libraries/TreeViewList/bin/res/drawable-ldpi/expanded.png
new file mode 100644 (file)
index 0000000..7ce5074
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-ldpi/expanded.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-ldpi/ic_launcher.png b/android-libraries/TreeViewList/bin/res/drawable-ldpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..18689f6
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-ldpi/ic_launcher.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-mdpi/collapsed.png b/android-libraries/TreeViewList/bin/res/drawable-mdpi/collapsed.png
new file mode 100644 (file)
index 0000000..d2e8774
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-mdpi/collapsed.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-mdpi/expanded.png b/android-libraries/TreeViewList/bin/res/drawable-mdpi/expanded.png
new file mode 100644 (file)
index 0000000..4c5ad0f
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-mdpi/expanded.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable-mdpi/ic_launcher.png b/android-libraries/TreeViewList/bin/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..02e96b9
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable-mdpi/ic_launcher.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_disabled.9.png b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_disabled.9.png
new file mode 100644 (file)
index 0000000..6bc40f6
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_disabled.9.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_focus.9.png b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_focus.9.png
new file mode 100644 (file)
index 0000000..38c6754
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_focus.9.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_longpress.9.png b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_longpress.9.png
new file mode 100644 (file)
index 0000000..8d2894e
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_longpress.9.png differ
diff --git a/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_pressed.9.png b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_pressed.9.png
new file mode 100644 (file)
index 0000000..900623e
Binary files /dev/null and b/android-libraries/TreeViewList/bin/res/drawable/list_selector_background_pressed.9.png differ
diff --git a/android-libraries/TreeViewList/bin/treeviewlist.jar b/android-libraries/TreeViewList/bin/treeviewlist.jar
new file mode 100644 (file)
index 0000000..3445f56
Binary files /dev/null and b/android-libraries/TreeViewList/bin/treeviewlist.jar differ
diff --git a/android-libraries/TreeViewList/gen/pl/polidea/treeview/BuildConfig.java b/android-libraries/TreeViewList/gen/pl/polidea/treeview/BuildConfig.java
new file mode 100644 (file)
index 0000000..18bc91b
--- /dev/null
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package pl.polidea.treeview;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/gen/pl/polidea/treeview/R.java b/android-libraries/TreeViewList/gen/pl/polidea/treeview/R.java
new file mode 100644 (file)
index 0000000..3ef9b35
--- /dev/null
@@ -0,0 +1,276 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.\r
+ *\r
+ * This class was automatically generated by the\r
+ * aapt tool from the resource data it found.  It\r
+ * should not be modified by hand.\r
+ */\r
+\r
+package pl.polidea.treeview;\r
+\r
+public final class R {\r
+    public static final class attr {\r
+        /** <p>Must be a boolean value, either "<code>true</code>" or "<code>false</code>".\r
+<p>This may also be a reference to a resource (in the form\r
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or\r
+theme attribute (in the form\r
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")\r
+containing a value of this type.\r
+         */\r
+        public static int collapsible=0x7f010000;\r
+        /** <p>Must be a boolean value, either "<code>true</code>" or "<code>false</code>".\r
+<p>This may also be a reference to a resource (in the form\r
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or\r
+theme attribute (in the form\r
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")\r
+containing a value of this type.\r
+         */\r
+        public static int handle_trackball_press=0x7f010004;\r
+        /** <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".\r
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\r
+in (inches), mm (millimeters).\r
+<p>This may also be a reference to a resource (in the form\r
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or\r
+theme attribute (in the form\r
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")\r
+containing a value of this type.\r
+         */\r
+        public static int indent_width=0x7f010003;\r
+        /** <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+         */\r
+        public static int indicator_background=0x7f010006;\r
+        /** <p>Must be one or more (separated by '|') of the following constant values.</p>\r
+<table>\r
+<colgroup align="left" />\r
+<colgroup align="left" />\r
+<colgroup align="left" />\r
+<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\r
+<tr><td><code>top</code></td><td>0x30</td><td> Push object to the top of its container, not changing its size. </td></tr>\r
+<tr><td><code>bottom</code></td><td>0x50</td><td> Push object to the bottom of its container, not changing its size. </td></tr>\r
+<tr><td><code>left</code></td><td>0x03</td><td> Push object to the left of its container, not changing its size. </td></tr>\r
+<tr><td><code>right</code></td><td>0x05</td><td> Push object to the right of its container, not changing its size. </td></tr>\r
+<tr><td><code>center_vertical</code></td><td>0x10</td><td> Place object in the vertical center of its container, not changing its size. </td></tr>\r
+<tr><td><code>fill_vertical</code></td><td>0x70</td><td> Grow the vertical size of the object if needed so it completely fills its container. </td></tr>\r
+<tr><td><code>center_horizontal</code></td><td>0x01</td><td> Place object in the horizontal center of its container, not changing its size. </td></tr>\r
+<tr><td><code>fill_horizontal</code></td><td>0x07</td><td> Grow the horizontal size of the object if needed so it completely fills its container. </td></tr>\r
+<tr><td><code>center</code></td><td>0x11</td><td> Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. </td></tr>\r
+<tr><td><code>fill</code></td><td>0x77</td><td> Grow the horizontal and vertical size of the object if needed so it completely fills its container. </td></tr>\r
+<tr><td><code>clip_vertical</code></td><td>0x80</td><td> Additional option that can be set to have the top and/or bottom edges of the child clipped to its container's bounds.\r
+                               The clip will be based on the vertical gravity: a top gravity will clip the bottom edge, a bottom gravity will clip the top\r
+                               edge, and neither will clip both edges. </td></tr>\r
+<tr><td><code>clip_horizontal</code></td><td>0x08</td><td> Additional option that can be set to have the left and/or right edges of the child clipped to its container's bounds.\r
+                               The clip will be based on the horizontal gravity: a left gravity will clip the right edge, a right gravity will clip the\r
+                               left edge, and neither will clip both edges. </td></tr>\r
+</table>\r
+         */\r
+        public static int indicator_gravity=0x7f010005;\r
+        /** <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+         */\r
+        public static int row_background=0x7f010007;\r
+        /** <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+         */\r
+        public static int src_collapsed=0x7f010002;\r
+        /** <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+         */\r
+        public static int src_expanded=0x7f010001;\r
+    }\r
+    public static final class drawable {\r
+        public static int collapsed=0x7f020000;\r
+        public static int divider=0x7f020001;\r
+        public static int expanded=0x7f020002;\r
+        public static int ic_launcher=0x7f020003;\r
+        public static int list_selector_background=0x7f020004;\r
+        public static int list_selector_background_disabled=0x7f020005;\r
+        public static int list_selector_background_focus=0x7f020006;\r
+        public static int list_selector_background_longpress=0x7f020007;\r
+        public static int list_selector_background_pressed=0x7f020008;\r
+        public static int list_selector_background_transition=0x7f020009;\r
+    }\r
+    public static final class id {\r
+        public static int bottom=0x7f040001;\r
+        public static int center=0x7f040008;\r
+        public static int center_horizontal=0x7f040006;\r
+        public static int center_vertical=0x7f040004;\r
+        public static int clip_horizontal=0x7f04000b;\r
+        public static int clip_vertical=0x7f04000a;\r
+        public static int fill=0x7f040009;\r
+        public static int fill_horizontal=0x7f040007;\r
+        public static int fill_vertical=0x7f040005;\r
+        public static int left=0x7f040002;\r
+        public static int right=0x7f040003;\r
+        public static int top=0x7f040000;\r
+        public static int treeview_list_item_frame=0x7f04000e;\r
+        public static int treeview_list_item_image=0x7f04000d;\r
+        public static int treeview_list_item_image_layout=0x7f04000c;\r
+    }\r
+    public static final class layout {\r
+        public static int tree_list_item_wrapper=0x7f030000;\r
+    }\r
+    public static final class style {\r
+        public static int treeViewListStyle=0x7f050000;\r
+    }\r
+    public static final class styleable {\r
+        /** Attributes that can be used with a TreeViewList.\r
+           <p>Includes the following attributes:</p>\r
+           <table>\r
+           <colgroup align="left" />\r
+           <colgroup align="left" />\r
+           <tr><th>Attribute</th><th>Description</th></tr>\r
+           <tr><td><code>{@link #TreeViewList_collapsible pl.polidea.treeview:collapsible}</code></td><td></td></tr>\r
+           <tr><td><code>{@link #TreeViewList_handle_trackball_press pl.polidea.treeview:handle_trackball_press}</code></td><td></td></tr>\r
+           <tr><td><code>{@link #TreeViewList_indent_width pl.polidea.treeview:indent_width}</code></td><td></td></tr>\r
+           <tr><td><code>{@link #TreeViewList_indicator_background pl.polidea.treeview:indicator_background}</code></td><td></td></tr>\r
+           <tr><td><code>{@link #TreeViewList_indicator_gravity pl.polidea.treeview:indicator_gravity}</code></td><td></td></tr>\r
+           <tr><td><code>{@link #TreeViewList_row_background pl.polidea.treeview:row_background}</code></td><td></td></tr>\r
+           <tr><td><code>{@link #TreeViewList_src_collapsed pl.polidea.treeview:src_collapsed}</code></td><td></td></tr>\r
+           <tr><td><code>{@link #TreeViewList_src_expanded pl.polidea.treeview:src_expanded}</code></td><td></td></tr>\r
+           </table>\r
+           @see #TreeViewList_collapsible\r
+           @see #TreeViewList_handle_trackball_press\r
+           @see #TreeViewList_indent_width\r
+           @see #TreeViewList_indicator_background\r
+           @see #TreeViewList_indicator_gravity\r
+           @see #TreeViewList_row_background\r
+           @see #TreeViewList_src_collapsed\r
+           @see #TreeViewList_src_expanded\r
+         */\r
+        public static final int[] TreeViewList = {\r
+            0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003,\r
+            0x7f010004, 0x7f010005, 0x7f010006, 0x7f010007\r
+        };\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#collapsible}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>Must be a boolean value, either "<code>true</code>" or "<code>false</code>".\r
+<p>This may also be a reference to a resource (in the form\r
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or\r
+theme attribute (in the form\r
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")\r
+containing a value of this type.\r
+          @attr name android:collapsible\r
+        */\r
+        public static final int TreeViewList_collapsible = 0;\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#handle_trackball_press}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>Must be a boolean value, either "<code>true</code>" or "<code>false</code>".\r
+<p>This may also be a reference to a resource (in the form\r
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or\r
+theme attribute (in the form\r
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")\r
+containing a value of this type.\r
+          @attr name android:handle_trackball_press\r
+        */\r
+        public static final int TreeViewList_handle_trackball_press = 4;\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#indent_width}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".\r
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\r
+in (inches), mm (millimeters).\r
+<p>This may also be a reference to a resource (in the form\r
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or\r
+theme attribute (in the form\r
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")\r
+containing a value of this type.\r
+          @attr name android:indent_width\r
+        */\r
+        public static final int TreeViewList_indent_width = 3;\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#indicator_background}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+          @attr name android:indicator_background\r
+        */\r
+        public static final int TreeViewList_indicator_background = 6;\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#indicator_gravity}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>Must be one or more (separated by '|') of the following constant values.</p>\r
+<table>\r
+<colgroup align="left" />\r
+<colgroup align="left" />\r
+<colgroup align="left" />\r
+<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\r
+<tr><td><code>top</code></td><td>0x30</td><td> Push object to the top of its container, not changing its size. </td></tr>\r
+<tr><td><code>bottom</code></td><td>0x50</td><td> Push object to the bottom of its container, not changing its size. </td></tr>\r
+<tr><td><code>left</code></td><td>0x03</td><td> Push object to the left of its container, not changing its size. </td></tr>\r
+<tr><td><code>right</code></td><td>0x05</td><td> Push object to the right of its container, not changing its size. </td></tr>\r
+<tr><td><code>center_vertical</code></td><td>0x10</td><td> Place object in the vertical center of its container, not changing its size. </td></tr>\r
+<tr><td><code>fill_vertical</code></td><td>0x70</td><td> Grow the vertical size of the object if needed so it completely fills its container. </td></tr>\r
+<tr><td><code>center_horizontal</code></td><td>0x01</td><td> Place object in the horizontal center of its container, not changing its size. </td></tr>\r
+<tr><td><code>fill_horizontal</code></td><td>0x07</td><td> Grow the horizontal size of the object if needed so it completely fills its container. </td></tr>\r
+<tr><td><code>center</code></td><td>0x11</td><td> Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. </td></tr>\r
+<tr><td><code>fill</code></td><td>0x77</td><td> Grow the horizontal and vertical size of the object if needed so it completely fills its container. </td></tr>\r
+<tr><td><code>clip_vertical</code></td><td>0x80</td><td> Additional option that can be set to have the top and/or bottom edges of the child clipped to its container's bounds.\r
+                               The clip will be based on the vertical gravity: a top gravity will clip the bottom edge, a bottom gravity will clip the top\r
+                               edge, and neither will clip both edges. </td></tr>\r
+<tr><td><code>clip_horizontal</code></td><td>0x08</td><td> Additional option that can be set to have the left and/or right edges of the child clipped to its container's bounds.\r
+                               The clip will be based on the horizontal gravity: a left gravity will clip the right edge, a right gravity will clip the\r
+                               left edge, and neither will clip both edges. </td></tr>\r
+</table>\r
+          @attr name android:indicator_gravity\r
+        */\r
+        public static final int TreeViewList_indicator_gravity = 5;\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#row_background}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+          @attr name android:row_background\r
+        */\r
+        public static final int TreeViewList_row_background = 7;\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#src_collapsed}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+          @attr name android:src_collapsed\r
+        */\r
+        public static final int TreeViewList_src_collapsed = 2;\r
+        /**\r
+          <p>This symbol is the offset where the {@link pl.polidea.treeview.R.attr#src_expanded}\r
+          attribute's value can be found in the {@link #TreeViewList} array.\r
+\r
+\r
+          <p>May be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"\r
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".\r
+<p>May be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",\r
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".\r
+          @attr name android:src_expanded\r
+        */\r
+        public static final int TreeViewList_src_expanded = 1;\r
+    };\r
+}\r
diff --git a/android-libraries/TreeViewList/proguard.cfg b/android-libraries/TreeViewList/proguard.cfg
new file mode 100644 (file)
index 0000000..b1cdf17
--- /dev/null
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+   public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+  public static final android.os.Parcelable$Creator *;
+}
diff --git a/android-libraries/TreeViewList/project.properties b/android-libraries/TreeViewList/project.properties
new file mode 100644 (file)
index 0000000..337e8f3
--- /dev/null
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-7
+android.library=true
diff --git a/android-libraries/TreeViewList/res/drawable-hdpi/collapsed.png b/android-libraries/TreeViewList/res/drawable-hdpi/collapsed.png
new file mode 100644 (file)
index 0000000..c1e1f3d
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-hdpi/collapsed.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-hdpi/expanded.png b/android-libraries/TreeViewList/res/drawable-hdpi/expanded.png
new file mode 100644 (file)
index 0000000..cec254a
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-hdpi/expanded.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-hdpi/ic_launcher.png b/android-libraries/TreeViewList/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..8074c4c
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-hdpi/ic_launcher.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-ldpi/collapsed.png b/android-libraries/TreeViewList/res/drawable-ldpi/collapsed.png
new file mode 100644 (file)
index 0000000..a52e846
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-ldpi/collapsed.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-ldpi/expanded.png b/android-libraries/TreeViewList/res/drawable-ldpi/expanded.png
new file mode 100644 (file)
index 0000000..d8b7ab8
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-ldpi/expanded.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-ldpi/ic_launcher.png b/android-libraries/TreeViewList/res/drawable-ldpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..1095584
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-ldpi/ic_launcher.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-mdpi/collapsed.png b/android-libraries/TreeViewList/res/drawable-mdpi/collapsed.png
new file mode 100644 (file)
index 0000000..b235551
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-mdpi/collapsed.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-mdpi/expanded.png b/android-libraries/TreeViewList/res/drawable-mdpi/expanded.png
new file mode 100644 (file)
index 0000000..f7377cb
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-mdpi/expanded.png differ
diff --git a/android-libraries/TreeViewList/res/drawable-mdpi/ic_launcher.png b/android-libraries/TreeViewList/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..a07c69f
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable-mdpi/ic_launcher.png differ
diff --git a/android-libraries/TreeViewList/res/drawable/divider.xml b/android-libraries/TreeViewList/res/drawable/divider.xml
new file mode 100644 (file)
index 0000000..5f37949
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+  android:src="@android:drawable/divider_horizontal_dark"
+  android:layout_width="fill_parent" android:layout_height="wrap_content"
+  android:scaleType="fitXY" android:paddingLeft="5sp"
+  android:paddingRight="5sp" android:paddingBottom="2sp" />
diff --git a/android-libraries/TreeViewList/res/drawable/list_selector_background.xml b/android-libraries/TreeViewList/res/drawable/list_selector_background.xml
new file mode 100644 (file)
index 0000000..2b21b0c
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project Licensed under the 
+       Apache License, Version 2.0 (the "License"); you may not use this file except 
+       in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
+       Unless required by applicable law or agreed to in writing, software distributed 
+       under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 
+       OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
+       the specific language governing permissions and limitations under the License. -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+       <item android:state_window_focused="false" android:drawable="@android:color/transparent" />
+
+       <!-- Even though these two point to the same resource, have two states so 
+               the drawable will invalidate itself when coming out of pressed state. -->
+       <item android:state_focused="true" android:state_enabled="false"
+               android:state_pressed="true" android:drawable="@drawable/list_selector_background_disabled" />
+       <item android:state_focused="true" android:state_enabled="false"
+               android:drawable="@drawable/list_selector_background_disabled" />
+
+       <item android:state_focused="true" android:state_pressed="true"
+               android:drawable="@drawable/list_selector_background_transition" />
+       <item android:state_focused="false" android:state_pressed="true"
+               android:drawable="@drawable/list_selector_background_transition" />
+
+       <item android:state_focused="true"
+               android:drawable="@drawable/list_selector_background_focus" />
+
+       <!-- !!hack!! to fill StateListDrawable.mStateListState with exactly 10 
+               items otherwise it will throw NPE on Android 1.6 -->
+
+       <item android:animationCache="true"
+               android:drawable="@android:color/transparent" />
+
+       <item android:animationCache="false"
+               android:drawable="@android:color/transparent" />
+
+       <item android:alwaysDrawnWithCache="false"
+               android:drawable="@android:color/transparent" />
+
+       <item android:alwaysDrawnWithCache="true"
+               android:drawable="@android:color/transparent" />
+       
+       
+</selector>
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/res/drawable/list_selector_background_disabled.9.png b/android-libraries/TreeViewList/res/drawable/list_selector_background_disabled.9.png
new file mode 100644 (file)
index 0000000..bf970b0
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable/list_selector_background_disabled.9.png differ
diff --git a/android-libraries/TreeViewList/res/drawable/list_selector_background_focus.9.png b/android-libraries/TreeViewList/res/drawable/list_selector_background_focus.9.png
new file mode 100644 (file)
index 0000000..c3e2415
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable/list_selector_background_focus.9.png differ
diff --git a/android-libraries/TreeViewList/res/drawable/list_selector_background_longpress.9.png b/android-libraries/TreeViewList/res/drawable/list_selector_background_longpress.9.png
new file mode 100644 (file)
index 0000000..5cbb251
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable/list_selector_background_longpress.9.png differ
diff --git a/android-libraries/TreeViewList/res/drawable/list_selector_background_pressed.9.png b/android-libraries/TreeViewList/res/drawable/list_selector_background_pressed.9.png
new file mode 100644 (file)
index 0000000..02b4e9a
Binary files /dev/null and b/android-libraries/TreeViewList/res/drawable/list_selector_background_pressed.9.png differ
diff --git a/android-libraries/TreeViewList/res/drawable/list_selector_background_transition.xml b/android-libraries/TreeViewList/res/drawable/list_selector_background_transition.xml
new file mode 100644 (file)
index 0000000..0dec133
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/list_selector_background_pressed"  />
+    <item android:drawable="@drawable/list_selector_background_longpress"  />
+</transition>
diff --git a/android-libraries/TreeViewList/res/layout/tree_list_item_wrapper.xml b/android-libraries/TreeViewList/res/layout/tree_list_item_wrapper.xml
new file mode 100644 (file)
index 0000000..9512a0c
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"
+       android:layout_height="fill_parent" >
+       <LinearLayout android:id="@+id/treeview_list_item_image_layout" android:layout_width="80dip"
+               android:layout_height="fill_parent" android:gravity="right|center_vertical">
+               <ImageView android:id="@+id/treeview_list_item_image" android:layout_width="wrap_content"
+                       android:layout_height="wrap_content" android:src="@drawable/collapsed" >
+               </ImageView>
+       </LinearLayout>
+       <FrameLayout android:id="@+id/treeview_list_item_frame" android:layout_width="fill_parent"
+               android:layout_height="fill_parent" android:layout_weight="1">
+       </FrameLayout>
+</LinearLayout>
diff --git a/android-libraries/TreeViewList/res/values/attrs.xml b/android-libraries/TreeViewList/res/values/attrs.xml
new file mode 100644 (file)
index 0000000..30060a4
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+       <declare-styleable name="TreeViewList">
+           <attr name="collapsible" format="boolean" />
+               <attr name="src_expanded" format="reference|color" />
+               <attr name="src_collapsed" format="reference|color" />
+        <attr name="indent_width" format="dimension" />
+        <attr name="handle_trackball_press" format="boolean" />
+               <attr name="indicator_gravity">
+                       <!-- Push object to the top of its container, not changing its size. -->
+                       <flag name="top" value="0x30" />
+                       <!-- Push object to the bottom of its container, not changing its size. -->
+                       <flag name="bottom" value="0x50" />
+                       <!-- Push object to the left of its container, not changing its size. -->
+                       <flag name="left" value="0x03" />
+                       <!-- Push object to the right of its container, not changing its size. -->
+                       <flag name="right" value="0x05" />
+                       <!-- Place object in the vertical center of its container, not changing its size. -->
+                       <flag name="center_vertical" value="0x10" />
+                       <!-- Grow the vertical size of the object if needed so it completely fills its container. -->
+                       <flag name="fill_vertical" value="0x70" />
+                       <!-- Place object in the horizontal center of its container, not changing its size. -->
+                       <flag name="center_horizontal" value="0x01" />
+                       <!-- Grow the horizontal size of the object if needed so it completely fills its container. -->
+                       <flag name="fill_horizontal" value="0x07" />
+                       <!-- Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. -->
+                       <flag name="center" value="0x11" />
+                       <!-- Grow the horizontal and vertical size of the object if needed so it completely fills its container. -->
+                       <flag name="fill" value="0x77" />
+                       <!-- Additional option that can be set to have the top and/or bottom edges of the child clipped to its container's bounds.
+                               The clip will be based on the vertical gravity: a top gravity will clip the bottom edge, a bottom gravity will clip the top
+                               edge, and neither will clip both edges. -->
+                       <flag name="clip_vertical" value="0x80" />
+                       <!-- Additional option that can be set to have the left and/or right edges of the child clipped to its container's bounds.
+                               The clip will be based on the horizontal gravity: a left gravity will clip the right edge, a right gravity will clip the
+                               left edge, and neither will clip both edges. -->
+                       <flag name="clip_horizontal" value="0x08" />
+               </attr>
+        <attr name="indicator_background" format="reference|color" />
+        <attr name="row_background" format="reference|color" />
+       </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/res/values/styles.xml b/android-libraries/TreeViewList/res/values/styles.xml
new file mode 100644 (file)
index 0000000..005c600
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style parent="@android:attr/listViewStyle" name="treeViewListStyle">
+        <item name="android:background">@android:color/white</item>
+        <item name="android:divider">@drawable/divider</item>
+    </style>
+</resources>
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/AbstractTreeViewAdapter.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/AbstractTreeViewAdapter.java
new file mode 100644 (file)
index 0000000..7f2b366
--- /dev/null
@@ -0,0 +1,315 @@
+package pl.polidea.treeview;
+
+import android.app.Activity;
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
+import android.widget.FrameLayout.LayoutParams;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+
+/**
+ * Adapter used to feed the table view.
+ * 
+ * @param <T>
+ *            class for ID of the tree
+ */
+public abstract class AbstractTreeViewAdapter<T> extends BaseAdapter implements
+        ListAdapter {
+    private final TreeStateManager<T> treeStateManager;
+    private final int numberOfLevels;
+    private final LayoutInflater layoutInflater;
+
+    private int indentWidth = 0;
+    private int indicatorGravity = 0;
+    private Drawable collapsedDrawable;
+    private Drawable expandedDrawable;
+    private Drawable indicatorBackgroundDrawable;
+    private Drawable rowBackgroundDrawable;
+
+    private final OnClickListener indicatorClickListener = new OnClickListener() {
+        @Override
+        public void onClick(final View v) {
+            @SuppressWarnings("unchecked")
+            final T id = (T) v.getTag();
+            expandCollapse(id);
+        }
+    };
+
+    private boolean collapsible;
+    private final Activity activity;
+
+    public Activity getActivity() {
+        return activity;
+    }
+
+    protected TreeStateManager<T> getManager() {
+        return treeStateManager;
+    }
+
+    protected void expandCollapse(final T id) {
+        final TreeNodeInfo<T> info = treeStateManager.getNodeInfo(id);
+        if (!info.isWithChildren()) {
+            // ignore - no default action
+            return;
+        }
+        if (info.isExpanded()) {
+            treeStateManager.collapseChildren(id);
+        } else {
+            treeStateManager.expandDirectChildren(id);
+        }
+    }
+
+    private void calculateIndentWidth() {
+        if (expandedDrawable != null) {
+            indentWidth = Math.max(getIndentWidth(),
+                    expandedDrawable.getIntrinsicWidth());
+        }
+        if (collapsedDrawable != null) {
+            indentWidth = Math.max(getIndentWidth(),
+                    collapsedDrawable.getIntrinsicWidth());
+        }
+    }
+
+    public AbstractTreeViewAdapter(final Activity activity,
+            final TreeStateManager<T> treeStateManager, final int numberOfLevels) {
+        this.activity = activity;
+        this.treeStateManager = treeStateManager;
+        this.layoutInflater = (LayoutInflater) activity
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        this.numberOfLevels = numberOfLevels;
+        this.collapsedDrawable = null;
+        this.expandedDrawable = null;
+        this.rowBackgroundDrawable = null;
+        this.indicatorBackgroundDrawable = null;
+    }
+
+    @Override
+    public void registerDataSetObserver(final DataSetObserver observer) {
+        treeStateManager.registerDataSetObserver(observer);
+    }
+
+    @Override
+    public void unregisterDataSetObserver(final DataSetObserver observer) {
+        treeStateManager.unregisterDataSetObserver(observer);
+    }
+
+    @Override
+    public int getCount() {
+        return treeStateManager.getVisibleCount();
+    }
+
+    @Override
+    public Object getItem(final int position) {
+        return getItemId(position);
+    }
+
+    public T getTreeId(final int position) {
+        return treeStateManager.getVisibleList().get(position);
+    }
+
+    public TreeNodeInfo<T> getTreeNodeInfo(final int position) {
+        return treeStateManager.getNodeInfo(getTreeId(position));
+    }
+
+    @Override
+    public boolean hasStableIds() { // NOPMD
+        return true;
+    }
+
+    @Override
+    public int getItemViewType(final int position) {
+        return getTreeNodeInfo(position).getLevel();
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return numberOfLevels;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return getCount() == 0;
+    }
+
+    @Override
+    public boolean areAllItemsEnabled() { // NOPMD
+        return true;
+    }
+
+    @Override
+    public boolean isEnabled(final int position) { // NOPMD
+        return true;
+    }
+
+    protected int getTreeListItemWrapperId() {
+        return R.layout.tree_list_item_wrapper;
+    }
+
+    @Override
+    public final View getView(final int position, final View convertView,
+            final ViewGroup parent) {
+        final TreeNodeInfo<T> nodeInfo = getTreeNodeInfo(position);
+        if (convertView == null) {
+            final LinearLayout layout = (LinearLayout) layoutInflater.inflate(
+                    getTreeListItemWrapperId(), null);
+            return populateTreeItem(layout, getNewChildView(nodeInfo),
+                    nodeInfo, true);
+        } else {
+            final LinearLayout linear = (LinearLayout) convertView;
+            final FrameLayout frameLayout = (FrameLayout) linear
+                    .findViewById(R.id.treeview_list_item_frame);
+            final View childView = frameLayout.getChildAt(0);
+            updateView(childView, nodeInfo);
+            return populateTreeItem(linear, childView, nodeInfo, false);
+        }
+    }
+
+    /**
+     * Called when new view is to be created.
+     * 
+     * @param treeNodeInfo
+     *            node info
+     * @return view that should be displayed as tree content
+     */
+    public abstract View getNewChildView(TreeNodeInfo<T> treeNodeInfo);
+
+    /**
+     * Called when new view is going to be reused. You should update the view
+     * and fill it in with the data required to display the new information. You
+     * can also create a new view, which will mean that the old view will not be
+     * reused.
+     * 
+     * @param view
+     *            view that should be updated with the new values
+     * @param treeNodeInfo
+     *            node info used to populate the view
+     * @return view to used as row indented content
+     */
+    public abstract View updateView(View view, TreeNodeInfo<T> treeNodeInfo);
+
+    /**
+     * Retrieves background drawable for the node.
+     * 
+     * @param treeNodeInfo
+     *            node info
+     * @return drawable returned as background for the whole row. Might be null,
+     *         then default background is used
+     */
+    public Drawable getBackgroundDrawable(final TreeNodeInfo<T> treeNodeInfo) { // NOPMD
+        return null;
+    }
+
+    private Drawable getDrawableOrDefaultBackground(final Drawable r) {
+        if (r == null) {
+            return activity.getResources()
+                    .getDrawable(R.drawable.list_selector_background).mutate();
+        } else {
+            return r;
+        }
+    }
+
+    public final LinearLayout populateTreeItem(final LinearLayout layout,
+            final View childView, final TreeNodeInfo<T> nodeInfo,
+            final boolean newChildView) {
+        final Drawable individualRowDrawable = getBackgroundDrawable(nodeInfo);
+        layout.setBackgroundDrawable(individualRowDrawable == null ? getDrawableOrDefaultBackground(rowBackgroundDrawable)
+                : individualRowDrawable);
+        final LinearLayout.LayoutParams indicatorLayoutParams = new LinearLayout.LayoutParams(
+                calculateIndentation(nodeInfo), LayoutParams.FILL_PARENT);
+        final LinearLayout indicatorLayout = (LinearLayout) layout
+                .findViewById(R.id.treeview_list_item_image_layout);
+        indicatorLayout.setGravity(indicatorGravity);
+        indicatorLayout.setLayoutParams(indicatorLayoutParams);
+        final ImageView image = (ImageView) layout
+                .findViewById(R.id.treeview_list_item_image);
+        image.setImageDrawable(getDrawable(nodeInfo));
+        image.setBackgroundDrawable(getDrawableOrDefaultBackground(indicatorBackgroundDrawable));
+        image.setScaleType(ScaleType.CENTER);
+        image.setTag(nodeInfo.getId());
+        if (nodeInfo.isWithChildren() && collapsible) {
+            image.setOnClickListener(indicatorClickListener);
+        } else {
+            image.setOnClickListener(null);
+        }
+        layout.setTag(nodeInfo.getId());
+        final FrameLayout frameLayout = (FrameLayout) layout
+                .findViewById(R.id.treeview_list_item_frame);
+        final FrameLayout.LayoutParams childParams = new FrameLayout.LayoutParams(
+                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+        if (newChildView) {
+            frameLayout.addView(childView, childParams);
+        }
+        frameLayout.setTag(nodeInfo.getId());
+        return layout;
+    }
+
+    protected int calculateIndentation(final TreeNodeInfo<T> nodeInfo) {
+        return getIndentWidth() * (nodeInfo.getLevel() + (collapsible ? 1 : 0));
+    }
+
+    private Drawable getDrawable(final TreeNodeInfo<T> nodeInfo) {
+        if (!nodeInfo.isWithChildren() || !collapsible) {
+            return getDrawableOrDefaultBackground(indicatorBackgroundDrawable);
+        }
+        if (nodeInfo.isExpanded()) {
+            return expandedDrawable;
+        } else {
+            return collapsedDrawable;
+        }
+    }
+
+    public void setIndicatorGravity(final int indicatorGravity) {
+        this.indicatorGravity = indicatorGravity;
+    }
+
+    public void setCollapsedDrawable(final Drawable collapsedDrawable) {
+        this.collapsedDrawable = collapsedDrawable;
+        calculateIndentWidth();
+    }
+
+    public void setExpandedDrawable(final Drawable expandedDrawable) {
+        this.expandedDrawable = expandedDrawable;
+        calculateIndentWidth();
+    }
+
+    public void setIndentWidth(final int indentWidth) {
+        this.indentWidth = indentWidth;
+        calculateIndentWidth();
+    }
+
+    public void setRowBackgroundDrawable(final Drawable rowBackgroundDrawable) {
+        this.rowBackgroundDrawable = rowBackgroundDrawable;
+    }
+
+    public void setIndicatorBackgroundDrawable(
+            final Drawable indicatorBackgroundDrawable) {
+        this.indicatorBackgroundDrawable = indicatorBackgroundDrawable;
+    }
+
+    public void setCollapsible(final boolean collapsible) {
+        this.collapsible = collapsible;
+    }
+
+    public void refresh() {
+        treeStateManager.refresh();
+    }
+
+    private int getIndentWidth() {
+        return indentWidth;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void handleItemClick(final View view, final Object id) {
+        expandCollapse((T) id);
+    }
+
+}
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeNode.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeNode.java
new file mode 100644 (file)
index 0000000..6035369
--- /dev/null
@@ -0,0 +1,116 @@
+package pl.polidea.treeview;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Node. It is package protected so that it cannot be used outside.
+ * 
+ * @param <T>
+ *            type of the identifier used by the tree
+ */
+class InMemoryTreeNode<T> implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private final T id;
+    private final T parent;
+    private final int level;
+    private boolean visible = true;
+    private final List<InMemoryTreeNode<T>> children = new LinkedList<InMemoryTreeNode<T>>();
+    private List<T> childIdListCache = null;
+
+    public InMemoryTreeNode(final T id, final T parent, final int level,
+            final boolean visible) {
+        super();
+        this.id = id;
+        this.parent = parent;
+        this.level = level;
+        this.visible = visible;
+    }
+
+    public int indexOf(final T id) {
+        return getChildIdList().indexOf(id);
+    }
+
+    /**
+     * Cache is built lasily only if needed. The cache is cleaned on any
+     * structure change for that node!).
+     * 
+     * @return list of ids of children
+     */
+    public synchronized List<T> getChildIdList() {
+        if (childIdListCache == null) {
+            childIdListCache = new LinkedList<T>();
+            for (final InMemoryTreeNode<T> n : children) {
+                childIdListCache.add(n.getId());
+            }
+        }
+        return childIdListCache;
+    }
+
+    public boolean isVisible() {
+        return visible;
+    }
+
+    public void setVisible(final boolean visible) {
+        this.visible = visible;
+    }
+
+    public int getChildrenListSize() {
+        return children.size();
+    }
+
+    public synchronized InMemoryTreeNode<T> add(final int index, final T child,
+            final boolean visible) {
+        childIdListCache = null;
+        // Note! top levell children are always visible (!)
+        final InMemoryTreeNode<T> newNode = new InMemoryTreeNode<T>(child,
+                getId(), getLevel() + 1, getId() == null ? true : visible);
+        children.add(index, newNode);
+        return newNode;
+    }
+
+    /**
+     * Note. This method should technically return unmodifiable collection, but
+     * for performance reason on small devices we do not do it.
+     * 
+     * @return children list
+     */
+    public List<InMemoryTreeNode<T>> getChildren() {
+        return children;
+    }
+
+    public synchronized void clearChildren() {
+        children.clear();
+        childIdListCache = null;
+    }
+
+    public synchronized void removeChild(final T child) {
+        final int childIndex = indexOf(child);
+        if (childIndex != -1) {
+            children.remove(childIndex);
+            childIdListCache = null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "InMemoryTreeNode [id=" + getId() + ", parent=" + getParent()
+                + ", level=" + getLevel() + ", visible=" + visible
+                + ", children=" + children + ", childIdListCache="
+                + childIdListCache + "]";
+    }
+
+    T getId() {
+        return id;
+    }
+
+    T getParent() {
+        return parent;
+    }
+
+    int getLevel() {
+        return level;
+    }
+
+}
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeStateManager.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeStateManager.java
new file mode 100644 (file)
index 0000000..bae675b
--- /dev/null
@@ -0,0 +1,374 @@
+package pl.polidea.treeview;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import android.database.DataSetObserver;
+
+/**
+ * In-memory manager of tree state.
+ * 
+ * @param <T>
+ *            type of identifier
+ */
+public class InMemoryTreeStateManager<T> implements TreeStateManager<T> {
+    private static final long serialVersionUID = 1L;
+    private final Map<T, InMemoryTreeNode<T>> allNodes = new HashMap<T, InMemoryTreeNode<T>>();
+    private final InMemoryTreeNode<T> topSentinel = new InMemoryTreeNode<T>(
+            null, null, -1, true);
+    private transient List<T> visibleListCache = null; // lasy initialised
+    private transient List<T> unmodifiableVisibleList = null;
+    private boolean visibleByDefault = true;
+    private final transient Set<DataSetObserver> observers = new HashSet<DataSetObserver>();
+
+    private synchronized void internalDataSetChanged() {
+        visibleListCache = null;
+        unmodifiableVisibleList = null;
+        for (final DataSetObserver observer : observers) {
+            observer.onChanged();
+        }
+    }
+
+    /**
+     * If true new nodes are visible by default.
+     * 
+     * @param visibleByDefault
+     *            if true, then newly added nodes are expanded by default
+     */
+    public void setVisibleByDefault(final boolean visibleByDefault) {
+        this.visibleByDefault = visibleByDefault;
+    }
+
+    private InMemoryTreeNode<T> getNodeFromTreeOrThrow(final T id) {
+        if (id == null) {
+            throw new NodeNotInTreeException("(null)");
+        }
+        final InMemoryTreeNode<T> node = allNodes.get(id);
+        if (node == null) {
+            throw new NodeNotInTreeException(id.toString());
+        }
+        return node;
+    }
+
+    private InMemoryTreeNode<T> getNodeFromTreeOrThrowAllowRoot(final T id) {
+        if (id == null) {
+            return topSentinel;
+        }
+        return getNodeFromTreeOrThrow(id);
+    }
+
+    private void expectNodeNotInTreeYet(final T id) {
+        final InMemoryTreeNode<T> node = allNodes.get(id);
+        if (node != null) {
+            throw new NodeAlreadyInTreeException(id.toString(), node.toString());
+        }
+    }
+
+    @Override
+    public synchronized TreeNodeInfo<T> getNodeInfo(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrow(id);
+        final List<InMemoryTreeNode<T>> children = node.getChildren();
+        boolean expanded = false;
+        if (!children.isEmpty() && children.get(0).isVisible()) {
+            expanded = true;
+        }
+        return new TreeNodeInfo<T>(id, node.getLevel(), !children.isEmpty(),
+                node.isVisible(), expanded);
+    }
+
+    @Override
+    public synchronized List<T> getChildren(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(id);
+        return node.getChildIdList();
+    }
+
+    @Override
+    public synchronized T getParent(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(id);
+        return node.getParent();
+    }
+
+    private boolean getChildrenVisibility(final InMemoryTreeNode<T> node) {
+        boolean visibility;
+        final List<InMemoryTreeNode<T>> children = node.getChildren();
+        if (children.isEmpty()) {
+            visibility = visibleByDefault;
+        } else {
+            visibility = children.get(0).isVisible();
+        }
+        return visibility;
+    }
+
+    @Override
+    public synchronized void addBeforeChild(final T parent, final T newChild,
+            final T beforeChild) {
+        expectNodeNotInTreeYet(newChild);
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(parent);
+        final boolean visibility = getChildrenVisibility(node);
+        // top nodes are always expanded.
+        if (beforeChild == null) {
+            final InMemoryTreeNode<T> added = node.add(0, newChild, visibility);
+            allNodes.put(newChild, added);
+        } else {
+            final int index = node.indexOf(beforeChild);
+            final InMemoryTreeNode<T> added = node.add(index == -1 ? 0 : index,
+                    newChild, visibility);
+            allNodes.put(newChild, added);
+        }
+        if (visibility) {
+            internalDataSetChanged();
+        }
+    }
+
+    @Override
+    public synchronized void addAfterChild(final T parent, final T newChild,
+            final T afterChild) {
+        expectNodeNotInTreeYet(newChild);
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(parent);
+        final boolean visibility = getChildrenVisibility(node);
+        if (afterChild == null) {
+            final InMemoryTreeNode<T> added = node.add(
+                    node.getChildrenListSize(), newChild, visibility);
+            allNodes.put(newChild, added);
+        } else {
+            final int index = node.indexOf(afterChild);
+            final InMemoryTreeNode<T> added = node.add(
+                    index == -1 ? node.getChildrenListSize() : index, newChild,
+                    visibility);
+            allNodes.put(newChild, added);
+        }
+        if (visibility) {
+            internalDataSetChanged();
+        }
+    }
+
+    @Override
+    public synchronized void removeNodeRecursively(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(id);
+        final boolean visibleNodeChanged = removeNodeRecursively(node);
+        final T parent = node.getParent();
+        final InMemoryTreeNode<T> parentNode = getNodeFromTreeOrThrowAllowRoot(parent);
+        parentNode.removeChild(id);
+        if (visibleNodeChanged) {
+            internalDataSetChanged();
+        }
+    }
+
+    private boolean removeNodeRecursively(final InMemoryTreeNode<T> node) {
+        boolean visibleNodeChanged = false;
+        for (final InMemoryTreeNode<T> child : node.getChildren()) {
+            if (removeNodeRecursively(child)) {
+                visibleNodeChanged = true;
+            }
+        }
+        node.clearChildren();
+        if (node.getId() != null) {
+            allNodes.remove(node.getId());
+            if (node.isVisible()) {
+                visibleNodeChanged = true;
+            }
+        }
+        return visibleNodeChanged;
+    }
+
+    private void setChildrenVisibility(final InMemoryTreeNode<T> node,
+            final boolean visible, final boolean recursive) {
+        for (final InMemoryTreeNode<T> child : node.getChildren()) {
+            child.setVisible(visible);
+            if (recursive) {
+                setChildrenVisibility(child, visible, true);
+            }
+        }
+    }
+
+    @Override
+    public synchronized void expandDirectChildren(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(id);
+        setChildrenVisibility(node, true, false);
+        internalDataSetChanged();
+    }
+
+    @Override
+    public synchronized void expandEverythingBelow(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(id);
+        setChildrenVisibility(node, true, true);
+        internalDataSetChanged();
+    }
+
+    @Override
+    public synchronized void collapseChildren(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(id);
+        if (node == topSentinel) {
+            for (final InMemoryTreeNode<T> n : topSentinel.getChildren()) {
+                setChildrenVisibility(n, false, true);
+            }
+        } else {
+            setChildrenVisibility(node, false, true);
+        }
+        internalDataSetChanged();
+    }
+
+    @Override
+    public synchronized T getNextSibling(final T id) {
+        final T parent = getParent(id);
+        final InMemoryTreeNode<T> parentNode = getNodeFromTreeOrThrowAllowRoot(parent);
+        boolean returnNext = false;
+        for (final InMemoryTreeNode<T> child : parentNode.getChildren()) {
+            if (returnNext) {
+                return child.getId();
+            }
+            if (child.getId().equals(id)) {
+                returnNext = true;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public synchronized T getPreviousSibling(final T id) {
+        final T parent = getParent(id);
+        final InMemoryTreeNode<T> parentNode = getNodeFromTreeOrThrowAllowRoot(parent);
+        final T previousSibling = null;
+        for (final InMemoryTreeNode<T> child : parentNode.getChildren()) {
+            if (child.getId().equals(id)) {
+                return previousSibling;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public synchronized boolean isInTree(final T id) {
+        return allNodes.containsKey(id);
+    }
+
+    @Override
+    public synchronized int getVisibleCount() {
+        return getVisibleList().size();
+    }
+
+    @Override
+    public synchronized List<T> getVisibleList() {
+        T currentId = null;
+        if (visibleListCache == null) {
+            visibleListCache = new ArrayList<T>(allNodes.size());
+            do {
+                currentId = getNextVisible(currentId);
+                if (currentId == null) {
+                    break;
+                } else {
+                    visibleListCache.add(currentId);
+                }
+            } while (true);
+        }
+        if (unmodifiableVisibleList == null) {
+            unmodifiableVisibleList = Collections
+                    .unmodifiableList(visibleListCache);
+        }
+        return unmodifiableVisibleList;
+    }
+
+    public synchronized T getNextVisible(final T id) {
+        final InMemoryTreeNode<T> node = getNodeFromTreeOrThrowAllowRoot(id);
+        if (!node.isVisible()) {
+            return null;
+        }
+        final List<InMemoryTreeNode<T>> children = node.getChildren();
+        if (!children.isEmpty()) {
+            final InMemoryTreeNode<T> firstChild = children.get(0);
+            if (firstChild.isVisible()) {
+                return firstChild.getId();
+            }
+        }
+        final T sibl = getNextSibling(id);
+        if (sibl != null) {
+            return sibl;
+        }
+        T parent = node.getParent();
+        do {
+            if (parent == null) {
+                return null;
+            }
+            final T parentSibling = getNextSibling(parent);
+            if (parentSibling != null) {
+                return parentSibling;
+            }
+            parent = getNodeFromTreeOrThrow(parent).getParent();
+        } while (true);
+    }
+
+    @Override
+    public synchronized void registerDataSetObserver(
+            final DataSetObserver observer) {
+        observers.add(observer);
+    }
+
+    @Override
+    public synchronized void unregisterDataSetObserver(
+            final DataSetObserver observer) {
+        observers.remove(observer);
+    }
+
+    @Override
+    public int getLevel(final T id) {
+        return getNodeFromTreeOrThrow(id).getLevel();
+    }
+
+    @Override
+    public Integer[] getHierarchyDescription(final T id) {
+        final int level = getLevel(id);
+        final Integer[] hierarchy = new Integer[level + 1];
+        int currentLevel = level;
+        T currentId = id;
+        T parent = getParent(currentId);
+        while (currentLevel >= 0) {
+            hierarchy[currentLevel--] = getChildren(parent).indexOf(currentId);
+            currentId = parent;
+            parent = getParent(parent);
+        }
+        return hierarchy;
+    }
+
+    private void appendToSb(final StringBuilder sb, final T id) {
+        if (id != null) {
+            final TreeNodeInfo<T> node = getNodeInfo(id);
+            final int indent = node.getLevel() * 4;
+            final char[] indentString = new char[indent];
+            Arrays.fill(indentString, ' ');
+            sb.append(indentString);
+            sb.append(node.toString());
+            sb.append(Arrays.asList(getHierarchyDescription(id)).toString());
+            sb.append("\n");
+        }
+        final List<T> children = getChildren(id);
+        for (final T child : children) {
+            appendToSb(sb, child);
+        }
+    }
+
+    @Override
+    public synchronized String toString() {
+        final StringBuilder sb = new StringBuilder();
+        appendToSb(sb, null);
+        return sb.toString();
+    }
+
+    @Override
+    public synchronized void clear() {
+        allNodes.clear();
+        topSentinel.clearChildren();
+        internalDataSetChanged();
+    }
+
+    @Override
+    public void refresh() {
+        internalDataSetChanged();
+    }
+
+}
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/NodeAlreadyInTreeException.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/NodeAlreadyInTreeException.java
new file mode 100644 (file)
index 0000000..680d026
--- /dev/null
@@ -0,0 +1,14 @@
+package pl.polidea.treeview;
+
+/**
+ * The node being added is already in the tree.
+ * 
+ */
+public class NodeAlreadyInTreeException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    public NodeAlreadyInTreeException(final String id, final String oldNode) {
+        super("The node has already been added to the tree: " + id + ". Old node is:" + oldNode);
+    }
+
+}
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/NodeNotInTreeException.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/NodeNotInTreeException.java
new file mode 100644 (file)
index 0000000..f20450e
--- /dev/null
@@ -0,0 +1,15 @@
+package pl.polidea.treeview;
+
+/**
+ * This exception is thrown when the tree does not contain node requested.
+ * 
+ */
+public class NodeNotInTreeException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public NodeNotInTreeException(final String id) {
+        super("The tree does not contain the node specified: " + id);
+    }
+
+}
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;
+    }
+
+}
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeConfigurationException.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeConfigurationException.java
new file mode 100644 (file)
index 0000000..1fa72e0
--- /dev/null
@@ -0,0 +1,15 @@
+package pl.polidea.treeview;
+
+/**
+ * Exception thrown when there is a problem with configuring tree.
+ * 
+ */
+public class TreeConfigurationException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public TreeConfigurationException(final String detailMessage) {
+        super(detailMessage);
+    }
+
+}
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeNodeInfo.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeNodeInfo.java
new file mode 100644 (file)
index 0000000..32d18dd
--- /dev/null
@@ -0,0 +1,69 @@
+package pl.polidea.treeview;
+
+/**
+ * Information about the node.
+ * 
+ * @param <T>
+ *            type of the id for the tree
+ */
+public class TreeNodeInfo<T> {
+    private final T id;
+    private final int level;
+    private final boolean withChildren;
+    private final boolean visible;
+    private final boolean expanded;
+
+    /**
+     * Creates the node information.
+     * 
+     * @param id
+     *            id of the node
+     * @param level
+     *            level of the node
+     * @param withChildren
+     *            whether the node has children.
+     * @param visible
+     *            whether the tree node is visible.
+     * @param expanded
+     *            whether the tree node is expanded
+     * 
+     */
+    public TreeNodeInfo(final T id, final int level,
+            final boolean withChildren, final boolean visible,
+            final boolean expanded) {
+        super();
+        this.id = id;
+        this.level = level;
+        this.withChildren = withChildren;
+        this.visible = visible;
+        this.expanded = expanded;
+    }
+
+    public T getId() {
+        return id;
+    }
+
+    public boolean isWithChildren() {
+        return withChildren;
+    }
+
+    public boolean isVisible() {
+        return visible;
+    }
+
+    public boolean isExpanded() {
+        return expanded;
+    }
+
+    public int getLevel() {
+        return level;
+    }
+
+    @Override
+    public String toString() {
+        return "TreeNodeInfo [id=" + id + ", level=" + level
+                + ", withChildren=" + withChildren + ", visible=" + visible
+                + ", expanded=" + expanded + "]";
+    }
+
+}
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeStateManager.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeStateManager.java
new file mode 100644 (file)
index 0000000..781b70e
--- /dev/null
@@ -0,0 +1,193 @@
+package pl.polidea.treeview;
+
+import java.io.Serializable;
+import java.util.List;
+
+import android.database.DataSetObserver;
+
+/**
+ * Manages information about state of the tree. It only keeps information about
+ * tree elements, not the elements themselves.
+ * 
+ * @param <T>
+ *            type of the identifier for nodes in the tree
+ */
+public interface TreeStateManager<T> extends Serializable {
+
+    /**
+     * Returns array of integers showing the location of the node in hierarchy.
+     * It corresponds to heading numbering. {0,0,0} in 3 level node is the first
+     * node {0,0,1} is second leaf (assuming that there are two leaves in first
+     * subnode of the first node).
+     * 
+     * @param id
+     *            id of the node
+     * @return textual description of the hierarchy in tree for the node.
+     */
+    Integer[] getHierarchyDescription(T id);
+
+    /**
+     * Returns level of the node.
+     * 
+     * @param id
+     *            id of the node
+     * @return level in the tree
+     */
+    int getLevel(T id);
+
+    /**
+     * Returns information about the node.
+     * 
+     * @param id
+     *            node id
+     * @return node info
+     */
+    TreeNodeInfo<T> getNodeInfo(T id);
+
+    /**
+     * Returns children of the node.
+     * 
+     * @param id
+     *            id of the node or null if asking for top nodes
+     * @return children of the node
+     */
+    List<T> getChildren(T id);
+
+    /**
+     * Returns parent of the node.
+     * 
+     * @param id
+     *            id of the node
+     * @return parent id or null if no parent
+     */
+    T getParent(T id);
+
+    /**
+     * Adds the node before child or at the beginning.
+     * 
+     * @param parent
+     *            id of the parent node. If null - adds at the top level
+     * @param newChild
+     *            new child to add if null - adds at the beginning.
+     * @param beforeChild
+     *            child before which to add the new child
+     */
+    void addBeforeChild(T parent, T newChild, T beforeChild);
+
+    /**
+     * Adds the node after child or at the end.
+     * 
+     * @param parent
+     *            id of the parent node. If null - adds at the top level.
+     * @param newChild
+     *            new child to add. If null - adds at the end.
+     * @param afterChild
+     *            child after which to add the new child
+     */
+    void addAfterChild(T parent, T newChild, T afterChild);
+
+    /**
+     * Removes the node and all children from the tree.
+     * 
+     * @param id
+     *            id of the node to remove or null if all nodes are to be
+     *            removed.
+     */
+    void removeNodeRecursively(T id);
+
+    /**
+     * Expands all children of the node.
+     * 
+     * @param id
+     *            node which children should be expanded. cannot be null (top
+     *            nodes are always expanded!).
+     */
+    void expandDirectChildren(T id);
+
+    /**
+     * Expands everything below the node specified. Might be null - then expands
+     * all.
+     * 
+     * @param id
+     *            node which children should be expanded or null if all nodes
+     *            are to be expanded.
+     */
+    void expandEverythingBelow(T id);
+
+    /**
+     * Collapse children.
+     * 
+     * @param id
+     *            id collapses everything below node specified. If null,
+     *            collapses everything but top-level nodes.
+     */
+    void collapseChildren(T id);
+
+    /**
+     * Returns next sibling of the node (or null if no further sibling).
+     * 
+     * @param id
+     *            node id
+     * @return the sibling (or null if no next)
+     */
+    T getNextSibling(T id);
+
+    /**
+     * Returns previous sibling of the node (or null if no previous sibling).
+     * 
+     * @param id
+     *            node id
+     * @return the sibling (or null if no previous)
+     */
+    T getPreviousSibling(T id);
+
+    /**
+     * Checks if given node is already in tree.
+     * 
+     * @param id
+     *            id of the node
+     * @return true if node is already in tree.
+     */
+    boolean isInTree(T id);
+
+    /**
+     * Count visible elements.
+     * 
+     * @return number of currently visible elements.
+     */
+    int getVisibleCount();
+
+    /**
+     * Returns visible node list.
+     * 
+     * @return return the list of all visible nodes in the right sequence
+     */
+    List<T> getVisibleList();
+
+    /**
+     * Registers observers with the manager.
+     * 
+     * @param observer
+     *            observer
+     */
+    void registerDataSetObserver(final DataSetObserver observer);
+
+    /**
+     * Unregisters observers with the manager.
+     * 
+     * @param observer
+     *            observer
+     */
+    void unregisterDataSetObserver(final DataSetObserver observer);
+
+    /**
+     * Cleans tree stored in manager. After this operation the tree is empty.
+     * 
+     */
+    void clear();
+
+    /**
+     * Refreshes views connected to the manager.
+     */
+    void refresh();
+}
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeViewList.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeViewList.java
new file mode 100644 (file)
index 0000000..fb48ab5
--- /dev/null
@@ -0,0 +1,198 @@
+package pl.polidea.treeview;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+/**
+ * Tree view, expandable multi-level.
+ * 
+ * <pre>
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_collapsible
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_src_expanded
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_src_collapsed
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_indent_width
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_handle_trackball_press
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_indicator_gravity
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_indicator_background
+ * attr ref pl.polidea.treeview.R.styleable#TreeViewList_row_background
+ * </pre>
+ */
+public class TreeViewList extends ListView {
+    private static final int DEFAULT_COLLAPSED_RESOURCE = R.drawable.collapsed;
+    private static final int DEFAULT_EXPANDED_RESOURCE = R.drawable.expanded;
+    private static final int DEFAULT_INDENT = 0;
+    private static final int DEFAULT_GRAVITY = Gravity.LEFT
+            | Gravity.CENTER_VERTICAL;
+    private Drawable expandedDrawable;
+    private Drawable collapsedDrawable;
+    private Drawable rowBackgroundDrawable;
+    private Drawable indicatorBackgroundDrawable;
+    private int indentWidth = 0;
+    private int indicatorGravity = 0;
+    private AbstractTreeViewAdapter< ? > treeAdapter;
+    private boolean collapsible;
+    private boolean handleTrackballPress;
+
+    public TreeViewList(final Context context, final AttributeSet attrs) {
+        this(context, attrs, R.style.treeViewListStyle);
+    }
+
+    public TreeViewList(final Context context) {
+        this(context, null);
+    }
+
+    public TreeViewList(final Context context, final AttributeSet attrs,
+            final int defStyle) {
+        super(context, attrs, defStyle);
+        parseAttributes(context, attrs);
+    }
+
+    private void parseAttributes(final Context context, final AttributeSet attrs) {
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.TreeViewList);
+        expandedDrawable = a.getDrawable(R.styleable.TreeViewList_src_expanded);
+        if (expandedDrawable == null) {
+            expandedDrawable = context.getResources().getDrawable(
+                    DEFAULT_EXPANDED_RESOURCE);
+        }
+        collapsedDrawable = a
+                .getDrawable(R.styleable.TreeViewList_src_collapsed);
+        if (collapsedDrawable == null) {
+            collapsedDrawable = context.getResources().getDrawable(
+                    DEFAULT_COLLAPSED_RESOURCE);
+        }
+        indentWidth = a.getDimensionPixelSize(
+                R.styleable.TreeViewList_indent_width, DEFAULT_INDENT);
+        indicatorGravity = a.getInteger(
+                R.styleable.TreeViewList_indicator_gravity, DEFAULT_GRAVITY);
+        indicatorBackgroundDrawable = a
+                .getDrawable(R.styleable.TreeViewList_indicator_background);
+        rowBackgroundDrawable = a
+                .getDrawable(R.styleable.TreeViewList_row_background);
+        collapsible = a.getBoolean(R.styleable.TreeViewList_collapsible, true);
+        handleTrackballPress = a.getBoolean(
+                R.styleable.TreeViewList_handle_trackball_press, true);
+    }
+
+    @Override
+    public void setAdapter(final ListAdapter adapter) {
+        if (!(adapter instanceof AbstractTreeViewAdapter)) {
+            throw new TreeConfigurationException(
+                    "The adapter is not of TreeViewAdapter type");
+        }
+        treeAdapter = (AbstractTreeViewAdapter< ? >) adapter;
+        syncAdapter();
+        super.setAdapter(treeAdapter);
+    }
+
+    private void syncAdapter() {
+        treeAdapter.setCollapsedDrawable(collapsedDrawable);
+        treeAdapter.setExpandedDrawable(expandedDrawable);
+        treeAdapter.setIndicatorGravity(indicatorGravity);
+        treeAdapter.setIndentWidth(indentWidth);
+        treeAdapter.setIndicatorBackgroundDrawable(indicatorBackgroundDrawable);
+        treeAdapter.setRowBackgroundDrawable(rowBackgroundDrawable);
+        treeAdapter.setCollapsible(collapsible);
+        if (handleTrackballPress) {
+            setOnItemClickListener(new OnItemClickListener() {
+                @Override
+                public void onItemClick(final AdapterView< ? > parent,
+                        final View view, final int position, final long id) {
+                    treeAdapter.handleItemClick(view, view.getTag());
+                }
+            });
+        } else {
+            setOnClickListener(null);
+        }
+
+    }
+
+    public void setExpandedDrawable(final Drawable expandedDrawable) {
+        this.expandedDrawable = expandedDrawable;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public void setCollapsedDrawable(final Drawable collapsedDrawable) {
+        this.collapsedDrawable = collapsedDrawable;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public void setRowBackgroundDrawable(final Drawable rowBackgroundDrawable) {
+        this.rowBackgroundDrawable = rowBackgroundDrawable;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public void setIndicatorBackgroundDrawable(
+            final Drawable indicatorBackgroundDrawable) {
+        this.indicatorBackgroundDrawable = indicatorBackgroundDrawable;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public void setIndentWidth(final int indentWidth) {
+        this.indentWidth = indentWidth;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public void setIndicatorGravity(final int indicatorGravity) {
+        this.indicatorGravity = indicatorGravity;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public void setCollapsible(final boolean collapsible) {
+        this.collapsible = collapsible;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public void setHandleTrackballPress(final boolean handleTrackballPress) {
+        this.handleTrackballPress = handleTrackballPress;
+        syncAdapter();
+        treeAdapter.refresh();
+    }
+
+    public Drawable getExpandedDrawable() {
+        return expandedDrawable;
+    }
+
+    public Drawable getCollapsedDrawable() {
+        return collapsedDrawable;
+    }
+
+    public Drawable getRowBackgroundDrawable() {
+        return rowBackgroundDrawable;
+    }
+
+    public Drawable getIndicatorBackgroundDrawable() {
+        return indicatorBackgroundDrawable;
+    }
+
+    public int getIndentWidth() {
+        return indentWidth;
+    }
+
+    public int getIndicatorGravity() {
+        return indicatorGravity;
+    }
+
+    public boolean isCollapsible() {
+        return collapsible;
+    }
+
+    public boolean isHandleTrackballPress() {
+        return handleTrackballPress;
+    }
+
+}
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/overview.html b/android-libraries/TreeViewList/src/pl/polidea/treeview/overview.html
new file mode 100644 (file)
index 0000000..bdd09ce
--- /dev/null
@@ -0,0 +1,24 @@
+<html>
+<body>
+This is a small utility that provides quite configurable tree view list.
+It is based on standard android list view. It separates out different
+aspects of the tree: there is a separate list view, tree adapter, tree
+state manager and tree state builder.
+<p>
+<ul>
+       <li>Tree view provides the frame to display the view.</li>
+       <li>Adapter allows to create visual representation of each tree
+       node.</li>
+       <li>State manager provides storage for tree state (connections
+       between parents and children, collapsed/expanded state). It provides
+       all the low-level tree manipulation methods.</li>
+       <li>Tree builder allows to build tree easily providing higher
+       level methods. The tree can be build either from prepared sequentially
+       prepared list of nodes (node id, level) or using (parent/child
+       relationships).</li>
+       <p>For now only in-memory state manager is provided, but Tree State
+       Manger interface is done in the way that database tree manager even for
+       large trees is potentially supported.
+</ul>
+</body>
+</html>
\ No newline at end of file
diff --git a/android-libraries/TreeViewList/src/pl/polidea/treeview/package-info.java b/android-libraries/TreeViewList/src/pl/polidea/treeview/package-info.java
new file mode 100644 (file)
index 0000000..a622e09
--- /dev/null
@@ -0,0 +1,4 @@
+/**
+ * Provides expandable Tree View implementation.
+ */
+package pl.polidea.treeview;
\ No newline at end of file