From: kruland2607 Date: Sun, 27 May 2012 12:48:32 +0000 (+0000) Subject: Added support library for TreeViewList. Previously this code was subsumed in the... X-Git-Tag: upstream/12.09^2~223 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=bf3408aa65d45d99482d00baf5784dfde72d286d;p=debian%2Fopenrocket Added support library for TreeViewList. Previously this code was subsumed in the android app. git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@729 180e2498-e6e9-4542-8430-84ac67f01cd8 --- diff --git a/android-libraries/TreeViewList/.classpath b/android-libraries/TreeViewList/.classpath new file mode 100644 index 00000000..a4f1e405 --- /dev/null +++ b/android-libraries/TreeViewList/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/android-libraries/TreeViewList/.project b/android-libraries/TreeViewList/.project new file mode 100644 index 00000000..c9d4fdac --- /dev/null +++ b/android-libraries/TreeViewList/.project @@ -0,0 +1,33 @@ + + + TreeViewList + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/android-libraries/TreeViewList/AndroidManifest.xml b/android-libraries/TreeViewList/AndroidManifest.xml new file mode 100644 index 00000000..28a7fe08 --- /dev/null +++ b/android-libraries/TreeViewList/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + + \ 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 index 00000000..2b846618 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 index 00000000..40535baa 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 index 00000000..77562f42 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 index 00000000..c2a6124d 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 index 00000000..791ae79a 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 index 00000000..35af40c6 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 index 00000000..a9813987 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 index 00000000..1a7b40c1 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 index 00000000..f266770c 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 index 00000000..7f119578 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 index 00000000..a13978fa 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 index 00000000..4a475b27 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 index 00000000..a992b85f 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 index 00000000..ef23d5e4 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 index 00000000..4ddc77cc 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 index 00000000..d2e71937 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 index 00000000..683896ce 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 index 00000000..f3beab57 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 index 00000000..2b9baacc 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 index 00000000..53039993 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 index 00000000..bdd09ce9 --- /dev/null +++ b/android-libraries/TreeViewList/bin/classes/pl/polidea/treeview/overview.html @@ -0,0 +1,24 @@ + + +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. +

+

+ + \ 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 index 00000000..d0a12754 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 index 00000000..1b5ec3f9 --- /dev/null +++ b/android-libraries/TreeViewList/bin/jarlist.cache @@ -0,0 +1,3 @@ +# cache for current jar dependecy. DO NOT EDIT. +# format is +# 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 index 00000000..84ca818c 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 index 00000000..27612315 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 index 00000000..882eb148 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 index 00000000..f9c06f4f 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 index 00000000..7ce50746 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 index 00000000..18689f65 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 index 00000000..d2e87746 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 index 00000000..4c5ad0f9 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 index 00000000..02e96b96 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 index 00000000..6bc40f6d 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 index 00000000..38c67542 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 index 00000000..8d2894e1 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 index 00000000..900623e1 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 index 00000000..3445f56d 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 index 00000000..18bc91b3 --- /dev/null +++ b/android-libraries/TreeViewList/gen/pl/polidea/treeview/BuildConfig.java @@ -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 index 00000000..3ef9b354 --- /dev/null +++ b/android-libraries/TreeViewList/gen/pl/polidea/treeview/R.java @@ -0,0 +1,276 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package pl.polidea.treeview; + +public final class R { + public static final class attr { + /**

Must be a boolean value, either "true" or "false". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int collapsible=0x7f010000; + /**

Must be a boolean value, either "true" or "false". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int handle_trackball_press=0x7f010004; + /**

Must be a dimension value, which is a floating point number appended with a unit such as "14.5sp". +Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size), +in (inches), mm (millimeters). +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + */ + public static int indent_width=0x7f010003; + /**

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + */ + public static int indicator_background=0x7f010006; + /**

Must be one or more (separated by '|') of the following constant values.

+ ++++ + + + + + + + + + + + + +
ConstantValueDescription
top0x30 Push object to the top of its container, not changing its size.
bottom0x50 Push object to the bottom of its container, not changing its size.
left0x03 Push object to the left of its container, not changing its size.
right0x05 Push object to the right of its container, not changing its size.
center_vertical0x10 Place object in the vertical center of its container, not changing its size.
fill_vertical0x70 Grow the vertical size of the object if needed so it completely fills its container.
center_horizontal0x01 Place object in the horizontal center of its container, not changing its size.
fill_horizontal0x07 Grow the horizontal size of the object if needed so it completely fills its container.
center0x11 Place the object in the center of its container in both the vertical and horizontal axis, not changing its size.
fill0x77 Grow the horizontal and vertical size of the object if needed so it completely fills its container.
clip_vertical0x80 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.
clip_horizontal0x08 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.
+ */ + public static int indicator_gravity=0x7f010005; + /**

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + */ + public static int row_background=0x7f010007; + /**

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + */ + public static int src_collapsed=0x7f010002; + /**

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + */ + public static int src_expanded=0x7f010001; + } + public static final class drawable { + public static int collapsed=0x7f020000; + public static int divider=0x7f020001; + public static int expanded=0x7f020002; + public static int ic_launcher=0x7f020003; + public static int list_selector_background=0x7f020004; + public static int list_selector_background_disabled=0x7f020005; + public static int list_selector_background_focus=0x7f020006; + public static int list_selector_background_longpress=0x7f020007; + public static int list_selector_background_pressed=0x7f020008; + public static int list_selector_background_transition=0x7f020009; + } + public static final class id { + public static int bottom=0x7f040001; + public static int center=0x7f040008; + public static int center_horizontal=0x7f040006; + public static int center_vertical=0x7f040004; + public static int clip_horizontal=0x7f04000b; + public static int clip_vertical=0x7f04000a; + public static int fill=0x7f040009; + public static int fill_horizontal=0x7f040007; + public static int fill_vertical=0x7f040005; + public static int left=0x7f040002; + public static int right=0x7f040003; + public static int top=0x7f040000; + public static int treeview_list_item_frame=0x7f04000e; + public static int treeview_list_item_image=0x7f04000d; + public static int treeview_list_item_image_layout=0x7f04000c; + } + public static final class layout { + public static int tree_list_item_wrapper=0x7f030000; + } + public static final class style { + public static int treeViewListStyle=0x7f050000; + } + public static final class styleable { + /** Attributes that can be used with a TreeViewList. +

Includes the following attributes:

+ + + + + + + + + + + + +
AttributeDescription
{@link #TreeViewList_collapsible pl.polidea.treeview:collapsible}
{@link #TreeViewList_handle_trackball_press pl.polidea.treeview:handle_trackball_press}
{@link #TreeViewList_indent_width pl.polidea.treeview:indent_width}
{@link #TreeViewList_indicator_background pl.polidea.treeview:indicator_background}
{@link #TreeViewList_indicator_gravity pl.polidea.treeview:indicator_gravity}
{@link #TreeViewList_row_background pl.polidea.treeview:row_background}
{@link #TreeViewList_src_collapsed pl.polidea.treeview:src_collapsed}
{@link #TreeViewList_src_expanded pl.polidea.treeview:src_expanded}
+ @see #TreeViewList_collapsible + @see #TreeViewList_handle_trackball_press + @see #TreeViewList_indent_width + @see #TreeViewList_indicator_background + @see #TreeViewList_indicator_gravity + @see #TreeViewList_row_background + @see #TreeViewList_src_collapsed + @see #TreeViewList_src_expanded + */ + public static final int[] TreeViewList = { + 0x7f010000, 0x7f010001, 0x7f010002, 0x7f010003, + 0x7f010004, 0x7f010005, 0x7f010006, 0x7f010007 + }; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#collapsible} + attribute's value can be found in the {@link #TreeViewList} array. + + +

Must be a boolean value, either "true" or "false". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:collapsible + */ + public static final int TreeViewList_collapsible = 0; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#handle_trackball_press} + attribute's value can be found in the {@link #TreeViewList} array. + + +

Must be a boolean value, either "true" or "false". +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:handle_trackball_press + */ + public static final int TreeViewList_handle_trackball_press = 4; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#indent_width} + attribute's value can be found in the {@link #TreeViewList} array. + + +

Must be a dimension value, which is a floating point number appended with a unit such as "14.5sp". +Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size), +in (inches), mm (millimeters). +

This may also be a reference to a resource (in the form +"@[package:]type:name") or +theme attribute (in the form +"?[package:][type:]name") +containing a value of this type. + @attr name android:indent_width + */ + public static final int TreeViewList_indent_width = 3; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#indicator_background} + attribute's value can be found in the {@link #TreeViewList} array. + + +

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + @attr name android:indicator_background + */ + public static final int TreeViewList_indicator_background = 6; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#indicator_gravity} + attribute's value can be found in the {@link #TreeViewList} array. + + +

Must be one or more (separated by '|') of the following constant values.

+ ++++ + + + + + + + + + + + + +
ConstantValueDescription
top0x30 Push object to the top of its container, not changing its size.
bottom0x50 Push object to the bottom of its container, not changing its size.
left0x03 Push object to the left of its container, not changing its size.
right0x05 Push object to the right of its container, not changing its size.
center_vertical0x10 Place object in the vertical center of its container, not changing its size.
fill_vertical0x70 Grow the vertical size of the object if needed so it completely fills its container.
center_horizontal0x01 Place object in the horizontal center of its container, not changing its size.
fill_horizontal0x07 Grow the horizontal size of the object if needed so it completely fills its container.
center0x11 Place the object in the center of its container in both the vertical and horizontal axis, not changing its size.
fill0x77 Grow the horizontal and vertical size of the object if needed so it completely fills its container.
clip_vertical0x80 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.
clip_horizontal0x08 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.
+ @attr name android:indicator_gravity + */ + public static final int TreeViewList_indicator_gravity = 5; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#row_background} + attribute's value can be found in the {@link #TreeViewList} array. + + +

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + @attr name android:row_background + */ + public static final int TreeViewList_row_background = 7; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#src_collapsed} + attribute's value can be found in the {@link #TreeViewList} array. + + +

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + @attr name android:src_collapsed + */ + public static final int TreeViewList_src_collapsed = 2; + /** +

This symbol is the offset where the {@link pl.polidea.treeview.R.attr#src_expanded} + attribute's value can be found in the {@link #TreeViewList} array. + + +

May be a reference to another resource, in the form "@[+][package:]type:name" +or to a theme attribute in the form "?[package:][type:]name". +

May be a color value, in the form of "#rgb", "#argb", +"#rrggbb", or "#aarrggbb". + @attr name android:src_expanded + */ + public static final int TreeViewList_src_expanded = 1; + }; +} diff --git a/android-libraries/TreeViewList/proguard.cfg b/android-libraries/TreeViewList/proguard.cfg new file mode 100644 index 00000000..b1cdf17b --- /dev/null +++ b/android-libraries/TreeViewList/proguard.cfg @@ -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 ; +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembers class * { + public (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 index 00000000..337e8f37 --- /dev/null +++ b/android-libraries/TreeViewList/project.properties @@ -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 index 00000000..c1e1f3d5 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 index 00000000..cec254aa 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 index 00000000..8074c4c5 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 index 00000000..a52e846a 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 index 00000000..d8b7ab89 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 index 00000000..1095584e 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 index 00000000..b2355514 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 index 00000000..f7377cb3 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 index 00000000..a07c69fa 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 index 00000000..5f379499 --- /dev/null +++ b/android-libraries/TreeViewList/res/drawable/divider.xml @@ -0,0 +1,6 @@ + + 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 index 00000000..2b21b0c1 --- /dev/null +++ b/android-libraries/TreeViewList/res/drawable/list_selector_background.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 index 00000000..bf970b05 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 index 00000000..c3e24158 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 index 00000000..5cbb251a 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 index 00000000..02b4e9a5 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 index 00000000..0dec1335 --- /dev/null +++ b/android-libraries/TreeViewList/res/drawable/list_selector_background_transition.xml @@ -0,0 +1,20 @@ + + + + + + + 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 index 00000000..9512a0c8 --- /dev/null +++ b/android-libraries/TreeViewList/res/layout/tree_list_item_wrapper.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/android-libraries/TreeViewList/res/values/attrs.xml b/android-libraries/TreeViewList/res/values/attrs.xml new file mode 100644 index 00000000..30060a4c --- /dev/null +++ b/android-libraries/TreeViewList/res/values/attrs.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 index 00000000..005c6007 --- /dev/null +++ b/android-libraries/TreeViewList/res/values/styles.xml @@ -0,0 +1,7 @@ + + + + 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 index 00000000..7f2b366a --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/AbstractTreeViewAdapter.java @@ -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 + * class for ID of the tree + */ +public abstract class AbstractTreeViewAdapter extends BaseAdapter implements + ListAdapter { + private final TreeStateManager 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 getManager() { + return treeStateManager; + } + + protected void expandCollapse(final T id) { + final TreeNodeInfo 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 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 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 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 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 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 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 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 nodeInfo) { + return getIndentWidth() * (nodeInfo.getLevel() + (collapsible ? 1 : 0)); + } + + private Drawable getDrawable(final TreeNodeInfo 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 index 00000000..6035369f --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeNode.java @@ -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 + * type of the identifier used by the tree + */ +class InMemoryTreeNode 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> children = new LinkedList>(); + private List 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 getChildIdList() { + if (childIdListCache == null) { + childIdListCache = new LinkedList(); + for (final InMemoryTreeNode 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 add(final int index, final T child, + final boolean visible) { + childIdListCache = null; + // Note! top levell children are always visible (!) + final InMemoryTreeNode newNode = new InMemoryTreeNode(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> 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 index 00000000..bae675bf --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/InMemoryTreeStateManager.java @@ -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 + * type of identifier + */ +public class InMemoryTreeStateManager implements TreeStateManager { + private static final long serialVersionUID = 1L; + private final Map> allNodes = new HashMap>(); + private final InMemoryTreeNode topSentinel = new InMemoryTreeNode( + null, null, -1, true); + private transient List visibleListCache = null; // lasy initialised + private transient List unmodifiableVisibleList = null; + private boolean visibleByDefault = true; + private final transient Set observers = new HashSet(); + + 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 getNodeFromTreeOrThrow(final T id) { + if (id == null) { + throw new NodeNotInTreeException("(null)"); + } + final InMemoryTreeNode node = allNodes.get(id); + if (node == null) { + throw new NodeNotInTreeException(id.toString()); + } + return node; + } + + private InMemoryTreeNode getNodeFromTreeOrThrowAllowRoot(final T id) { + if (id == null) { + return topSentinel; + } + return getNodeFromTreeOrThrow(id); + } + + private void expectNodeNotInTreeYet(final T id) { + final InMemoryTreeNode node = allNodes.get(id); + if (node != null) { + throw new NodeAlreadyInTreeException(id.toString(), node.toString()); + } + } + + @Override + public synchronized TreeNodeInfo getNodeInfo(final T id) { + final InMemoryTreeNode node = getNodeFromTreeOrThrow(id); + final List> children = node.getChildren(); + boolean expanded = false; + if (!children.isEmpty() && children.get(0).isVisible()) { + expanded = true; + } + return new TreeNodeInfo(id, node.getLevel(), !children.isEmpty(), + node.isVisible(), expanded); + } + + @Override + public synchronized List getChildren(final T id) { + final InMemoryTreeNode node = getNodeFromTreeOrThrowAllowRoot(id); + return node.getChildIdList(); + } + + @Override + public synchronized T getParent(final T id) { + final InMemoryTreeNode node = getNodeFromTreeOrThrowAllowRoot(id); + return node.getParent(); + } + + private boolean getChildrenVisibility(final InMemoryTreeNode node) { + boolean visibility; + final List> 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 node = getNodeFromTreeOrThrowAllowRoot(parent); + final boolean visibility = getChildrenVisibility(node); + // top nodes are always expanded. + if (beforeChild == null) { + final InMemoryTreeNode added = node.add(0, newChild, visibility); + allNodes.put(newChild, added); + } else { + final int index = node.indexOf(beforeChild); + final InMemoryTreeNode 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 node = getNodeFromTreeOrThrowAllowRoot(parent); + final boolean visibility = getChildrenVisibility(node); + if (afterChild == null) { + final InMemoryTreeNode added = node.add( + node.getChildrenListSize(), newChild, visibility); + allNodes.put(newChild, added); + } else { + final int index = node.indexOf(afterChild); + final InMemoryTreeNode 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 node = getNodeFromTreeOrThrowAllowRoot(id); + final boolean visibleNodeChanged = removeNodeRecursively(node); + final T parent = node.getParent(); + final InMemoryTreeNode parentNode = getNodeFromTreeOrThrowAllowRoot(parent); + parentNode.removeChild(id); + if (visibleNodeChanged) { + internalDataSetChanged(); + } + } + + private boolean removeNodeRecursively(final InMemoryTreeNode node) { + boolean visibleNodeChanged = false; + for (final InMemoryTreeNode 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 node, + final boolean visible, final boolean recursive) { + for (final InMemoryTreeNode child : node.getChildren()) { + child.setVisible(visible); + if (recursive) { + setChildrenVisibility(child, visible, true); + } + } + } + + @Override + public synchronized void expandDirectChildren(final T id) { + final InMemoryTreeNode node = getNodeFromTreeOrThrowAllowRoot(id); + setChildrenVisibility(node, true, false); + internalDataSetChanged(); + } + + @Override + public synchronized void expandEverythingBelow(final T id) { + final InMemoryTreeNode node = getNodeFromTreeOrThrowAllowRoot(id); + setChildrenVisibility(node, true, true); + internalDataSetChanged(); + } + + @Override + public synchronized void collapseChildren(final T id) { + final InMemoryTreeNode node = getNodeFromTreeOrThrowAllowRoot(id); + if (node == topSentinel) { + for (final InMemoryTreeNode 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 parentNode = getNodeFromTreeOrThrowAllowRoot(parent); + boolean returnNext = false; + for (final InMemoryTreeNode 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 parentNode = getNodeFromTreeOrThrowAllowRoot(parent); + final T previousSibling = null; + for (final InMemoryTreeNode 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 getVisibleList() { + T currentId = null; + if (visibleListCache == null) { + visibleListCache = new ArrayList(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 node = getNodeFromTreeOrThrowAllowRoot(id); + if (!node.isVisible()) { + return null; + } + final List> children = node.getChildren(); + if (!children.isEmpty()) { + final InMemoryTreeNode 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 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 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 index 00000000..680d0266 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/NodeAlreadyInTreeException.java @@ -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 index 00000000..f20450e1 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/NodeNotInTreeException.java @@ -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 index 00000000..13b499c4 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeBuilder.java @@ -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 + */ +public class TreeBuilder { + private static final String TAG = TreeBuilder.class.getSimpleName(); + + private final TreeStateManager manager; + + private T lastAddedId = null; + private int lastLevel = -1; + + public TreeBuilder(final TreeStateManager 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 index 00000000..1fa72e04 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeConfigurationException.java @@ -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 index 00000000..32d18dd4 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeNodeInfo.java @@ -0,0 +1,69 @@ +package pl.polidea.treeview; + +/** + * Information about the node. + * + * @param + * type of the id for the tree + */ +public class TreeNodeInfo { + 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 index 00000000..781b70e5 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeStateManager.java @@ -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 + * type of the identifier for nodes in the tree + */ +public interface TreeStateManager 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 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 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 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 index 00000000..fb48ab5c --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/TreeViewList.java @@ -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. + * + *

+ * 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
+ * 
+ */ +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 index 00000000..bdd09ce9 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/overview.html @@ -0,0 +1,24 @@ + + +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. +

+

    +
  • Tree view provides the frame to display the view.
  • +
  • Adapter allows to create visual representation of each tree + node.
  • +
  • State manager provides storage for tree state (connections + between parents and children, collapsed/expanded state). It provides + all the low-level tree manipulation methods.
  • +
  • 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).
  • +

    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. +

+ + \ 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 index 00000000..a622e091 --- /dev/null +++ b/android-libraries/TreeViewList/src/pl/polidea/treeview/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides expandable Tree View implementation. + */ +package pl.polidea.treeview; \ No newline at end of file