diff --git a/greendroid/.gitignore b/greendroid/.gitignore
new file mode 100644
index 000000000..3c8e6349e
--- /dev/null
+++ b/greendroid/.gitignore
@@ -0,0 +1,9 @@
+*/bin/*
+*/gen/*
+*.DS_Store
+*.pyc
+
+# Prevent Git from versioning the GreenDroid library in the samples project.
+
+GDCatalog/src/greendroid/*
+GDCatalog/res/*/gd_*
\ No newline at end of file
diff --git a/greendroid/.project b/greendroid/.project
new file mode 100644
index 000000000..fcb384fde
--- /dev/null
+++ b/greendroid/.project
@@ -0,0 +1,33 @@
+
+
+ GreenDroid
+
+
+
+
+
+ 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/greendroid/GDCatalog/.classpath b/greendroid/GDCatalog/.classpath
new file mode 100644
index 000000000..28d6a6ece
--- /dev/null
+++ b/greendroid/GDCatalog/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/greendroid/GDCatalog/.project b/greendroid/GDCatalog/.project
new file mode 100644
index 000000000..2da883a8f
--- /dev/null
+++ b/greendroid/GDCatalog/.project
@@ -0,0 +1,40 @@
+
+
+ GDCatalog
+
+
+
+
+
+ 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
+
+
+
+ GreenDroid_src
+ 2
+ _android_GreenDroid_612cb559/src
+
+
+
diff --git a/greendroid/GDCatalog/AndroidManifest.xml b/greendroid/GDCatalog/AndroidManifest.xml
new file mode 100644
index 000000000..2e0161ed2
--- /dev/null
+++ b/greendroid/GDCatalog/AndroidManifest.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GDCatalog/default.properties b/greendroid/GDCatalog/default.properties
new file mode 100644
index 000000000..1bb292689
--- /dev/null
+++ b/greendroid/GDCatalog/default.properties
@@ -0,0 +1,14 @@
+# 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,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-4
+android.library.reference.1=../GreenDroid/
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/action_bar_divider.png b/greendroid/GDCatalog/res/drawable-hdpi/action_bar_divider.png
new file mode 100755
index 000000000..249f7f357
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/action_bar_divider.png differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/class1.jpg b/greendroid/GDCatalog/res/drawable-hdpi/class1.jpg
new file mode 100644
index 000000000..9c36d9ca4
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/class1.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/class2.jpg b/greendroid/GDCatalog/res/drawable-hdpi/class2.jpg
new file mode 100644
index 000000000..b2930a386
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/class2.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/class3.jpg b/greendroid/GDCatalog/res/drawable-hdpi/class3.jpg
new file mode 100644
index 000000000..779b4835e
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/class3.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/class4.jpg b/greendroid/GDCatalog/res/drawable-hdpi/class4.jpg
new file mode 100644
index 000000000..7845de7c6
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/class4.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/class5.jpg b/greendroid/GDCatalog/res/drawable-hdpi/class5.jpg
new file mode 100644
index 000000000..08f0817bc
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/class5.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/greendroid_application_logo.png b/greendroid/GDCatalog/res/drawable-hdpi/greendroid_application_logo.png
new file mode 100644
index 000000000..944bb5fd1
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/greendroid_application_logo.png differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/greendroid_icon.png b/greendroid/GDCatalog/res/drawable-hdpi/greendroid_icon.png
new file mode 100644
index 000000000..1b21d0f5c
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/greendroid_icon.png differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/header_bg.9.png b/greendroid/GDCatalog/res/drawable-hdpi/header_bg.9.png
new file mode 100644
index 000000000..955a61c3a
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/header_bg.9.png differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/ic_title_export_alt.png b/greendroid/GDCatalog/res/drawable-hdpi/ic_title_export_alt.png
new file mode 100644
index 000000000..b55e41def
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/ic_title_export_alt.png differ
diff --git a/greendroid/GDCatalog/res/drawable-hdpi/ic_title_export_default.png b/greendroid/GDCatalog/res/drawable-hdpi/ic_title_export_default.png
new file mode 100644
index 000000000..b86014d5f
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-hdpi/ic_title_export_default.png differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/action_bar_divider.png b/greendroid/GDCatalog/res/drawable-mdpi/action_bar_divider.png
new file mode 100755
index 000000000..16b5accd2
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/action_bar_divider.png differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/class1.jpg b/greendroid/GDCatalog/res/drawable-mdpi/class1.jpg
new file mode 100644
index 000000000..de3daa04c
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/class1.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/class2.jpg b/greendroid/GDCatalog/res/drawable-mdpi/class2.jpg
new file mode 100644
index 000000000..0e0350a2c
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/class2.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/class3.jpg b/greendroid/GDCatalog/res/drawable-mdpi/class3.jpg
new file mode 100644
index 000000000..353785d83
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/class3.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/class4.jpg b/greendroid/GDCatalog/res/drawable-mdpi/class4.jpg
new file mode 100644
index 000000000..dc260f38c
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/class4.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/class5.jpg b/greendroid/GDCatalog/res/drawable-mdpi/class5.jpg
new file mode 100644
index 000000000..f0dcf2538
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/class5.jpg differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/greendroid_application_logo.png b/greendroid/GDCatalog/res/drawable-mdpi/greendroid_application_logo.png
new file mode 100755
index 000000000..f4ce26e7b
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/greendroid_application_logo.png differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/greendroid_icon.png b/greendroid/GDCatalog/res/drawable-mdpi/greendroid_icon.png
new file mode 100644
index 000000000..6538176a9
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/greendroid_icon.png differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/header_bg.9.png b/greendroid/GDCatalog/res/drawable-mdpi/header_bg.9.png
new file mode 100644
index 000000000..4b0ca5062
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/header_bg.9.png differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/ic_title_export_alt.png b/greendroid/GDCatalog/res/drawable-mdpi/ic_title_export_alt.png
new file mode 100644
index 000000000..af322aa18
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/ic_title_export_alt.png differ
diff --git a/greendroid/GDCatalog/res/drawable-mdpi/ic_title_export_default.png b/greendroid/GDCatalog/res/drawable-mdpi/ic_title_export_default.png
new file mode 100644
index 000000000..06797e08f
Binary files /dev/null and b/greendroid/GDCatalog/res/drawable-mdpi/ic_title_export_default.png differ
diff --git a/greendroid/GDCatalog/res/drawable/action_bar_background.xml b/greendroid/GDCatalog/res/drawable/action_bar_background.xml
new file mode 100644
index 000000000..d2f22e024
--- /dev/null
+++ b/greendroid/GDCatalog/res/drawable/action_bar_background.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
diff --git a/greendroid/GDCatalog/res/drawable/ic_title_export.xml b/greendroid/GDCatalog/res/drawable/ic_title_export.xml
new file mode 100644
index 000000000..c979f55eb
--- /dev/null
+++ b/greendroid/GDCatalog/res/drawable/ic_title_export.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GDCatalog/res/layout/headed_text_item_view.xml b/greendroid/GDCatalog/res/layout/headed_text_item_view.xml
new file mode 100644
index 000000000..3c7cb9a88
--- /dev/null
+++ b/greendroid/GDCatalog/res/layout/headed_text_item_view.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GDCatalog/res/layout/list.xml b/greendroid/GDCatalog/res/layout/list.xml
new file mode 100644
index 000000000..14f997e95
--- /dev/null
+++ b/greendroid/GDCatalog/res/layout/list.xml
@@ -0,0 +1,24 @@
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GDCatalog/res/layout/quick_action.xml b/greendroid/GDCatalog/res/layout/quick_action.xml
new file mode 100644
index 000000000..10d13c4c5
--- /dev/null
+++ b/greendroid/GDCatalog/res/layout/quick_action.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GDCatalog/res/layout/segmented_controls.xml b/greendroid/GDCatalog/res/layout/segmented_controls.xml
new file mode 100644
index 000000000..8345a78a7
--- /dev/null
+++ b/greendroid/GDCatalog/res/layout/segmented_controls.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GDCatalog/res/layout/text.xml b/greendroid/GDCatalog/res/layout/text.xml
new file mode 100644
index 000000000..4223feb49
--- /dev/null
+++ b/greendroid/GDCatalog/res/layout/text.xml
@@ -0,0 +1,27 @@
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GDCatalog/res/values-fr/strings.xml b/greendroid/GDCatalog/res/values-fr/strings.xml
new file mode 100644
index 000000000..e5b0f4b52
--- /dev/null
+++ b/greendroid/GDCatalog/res/values-fr/strings.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ GDCatalog
+
+
+ Items basiques
+ Items XML
+ Itemviews personnalisées
+ Démo SegmentedBar
+
+
+ Jeff
+ Romain
+ Adam
+ Dan
+
+
diff --git a/greendroid/GDCatalog/res/values/colors.xml b/greendroid/GDCatalog/res/values/colors.xml
new file mode 100644
index 000000000..c0e5d36e3
--- /dev/null
+++ b/greendroid/GDCatalog/res/values/colors.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ #cacaca
+
+
\ No newline at end of file
diff --git a/greendroid/GDCatalog/res/values/strings.xml b/greendroid/GDCatalog/res/values/strings.xml
new file mode 100644
index 000000000..fa9dd4b36
--- /dev/null
+++ b/greendroid/GDCatalog/res/values/strings.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+ GDCatalog
+
+
+ Basic items
+ XML items
+ Tweaked itemviews
+ SegmentedBar demo
+ QuickAction demo
+
+
+ Jeff
+ Romain
+ Adam
+ Dan
+
+
diff --git a/greendroid/GDCatalog/res/values/styles.xml b/greendroid/GDCatalog/res/values/styles.xml
new file mode 100644
index 000000000..42e1a0f90
--- /dev/null
+++ b/greendroid/GDCatalog/res/values/styles.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GDCatalog/res/values/themes.xml b/greendroid/GDCatalog/res/values/themes.xml
new file mode 100644
index 000000000..0d0f9cb96
--- /dev/null
+++ b/greendroid/GDCatalog/res/values/themes.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GDCatalog/res/xml/items.xml b/greendroid/GDCatalog/res/xml/items.xml
new file mode 100644
index 000000000..c2569497e
--- /dev/null
+++ b/greendroid/GDCatalog/res/xml/items.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/ActionBarActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/ActionBarActivity.java
new file mode 100644
index 000000000..feb84ccd6
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/ActionBarActivity.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDActivity;
+import greendroid.widget.ActionBarItem;
+import greendroid.widget.LoaderActionBarItem;
+import greendroid.widget.ActionBarItem.Type;
+import greendroid.widget.NormalActionBarItem;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class ActionBarActivity extends GDActivity {
+
+ private final Handler mHandler = new Handler();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setActionBarContentView(R.layout.text);
+ ((TextView) findViewById(R.id.text)).setText("Screen 1");
+
+ addActionBarItem(Type.Refresh);
+
+ ActionBarItem item = getActionBar().newActionBarItem(NormalActionBarItem.class);
+ item.setDrawable(R.drawable.ic_title_export).setContentDescription(R.string.gd_export);
+ addActionBarItem(item);
+
+ addActionBarItem(Type.Locate);
+ }
+
+ @Override
+ public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
+
+ switch (position) {
+ case 2:
+ Intent intent = new Intent(this, TabbedActionBarActivity.class);
+ startActivity(intent);
+ break;
+
+ case 0:
+ final LoaderActionBarItem loaderItem = (LoaderActionBarItem) item;
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ loaderItem.setLoading(false);
+ }
+ }, 2000);
+ Toast.makeText(this, "You've just pressed a ActionBarItem.Type.Refresh button", Toast.LENGTH_SHORT)
+ .show();
+ break;
+
+ case 1:
+ Toast.makeText(this, "Custom drawable. Click on another item instead", Toast.LENGTH_SHORT).show();
+ break;
+
+ default:
+ return super.onHandleActionBarItemClick(item, position);
+ }
+
+ return true;
+ }
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/BasicItemActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/BasicItemActivity.java
new file mode 100644
index 000000000..1827e16ff
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/BasicItemActivity.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDListActivity;
+import greendroid.widget.ItemAdapter;
+import greendroid.widget.item.DescriptionItem;
+import greendroid.widget.item.DrawableItem;
+import greendroid.widget.item.Item;
+import greendroid.widget.item.ProgressItem;
+import greendroid.widget.item.SeparatorItem;
+import greendroid.widget.item.TextItem;
+import greendroid.widget.item.ThumbnailItem;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.os.Bundle;
+import android.os.Handler;
+
+public class BasicItemActivity extends GDListActivity {
+
+ private final Handler mHandler = new Handler();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ List items = new ArrayList();
+
+ items.add(new SeparatorItem("Class 1"));
+ items.add(new ThumbnailItem("Powered paragliding", "aka paramotoring", R.drawable.class1));
+ items.add(new DescriptionItem("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));
+
+ items.add(new SeparatorItem("Class 2"));
+ items.add(new DrawableItem("Trikes", R.drawable.class2));
+ items.add(new DescriptionItem("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));
+
+ items.add(new SeparatorItem("Class 3"));
+ items.add(new ThumbnailItem("Multi-axis", "Looks like a tiny place", R.drawable.class3));
+ items.add(new DescriptionItem("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));
+
+ items.add(new SeparatorItem("Class 4"));
+ items.add(new ThumbnailItem("Auto-gyro", "A scary helicopter", R.drawable.class4));
+ items.add(new DescriptionItem("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));
+
+ items.add(new SeparatorItem("Class 5"));
+ items.add(new DrawableItem("Hot air baloon", R.drawable.class5));
+ items.add(new DescriptionItem("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in."));
+
+ final Item item1 = new SeparatorItem("Class 6");
+ final Item item2 = new TextItem("Airbus/Boeing planes");
+ final Item item3 = new DescriptionItem("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempus consequat leo, et tincidunt justo tristique in.");
+ items.add(item1);
+ items.add(item2);
+ items.add(item3);
+
+ final ProgressItem progressItem = new ProgressItem("Removing intruders", true);
+ items.add(progressItem);
+
+ final ItemAdapter adapter = new ItemAdapter(this, items);
+ setListAdapter(adapter);
+
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ adapter.remove(item1);
+ adapter.remove(item2);
+ adapter.remove(item3);
+ adapter.remove(progressItem);
+ adapter.insert(new ThumbnailItem("Ultralight aviation", "List of French 'ULM' classes", R.drawable.greendroid_icon), 0);
+ adapter.notifyDataSetChanged();
+ }
+ },8000);
+
+ }
+
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/CatalogActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/CatalogActivity.java
new file mode 100644
index 000000000..b4b9b618e
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/CatalogActivity.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDActivity;
+import greendroid.widget.ItemAdapter;
+import greendroid.widget.ActionBar.Type;
+import greendroid.widget.item.TextItem;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.AdapterView.OnItemClickListener;
+
+public class CatalogActivity extends GDActivity {
+
+ private ListView mListView;
+ private Class>[] mDemoClasses = {
+ BasicItemActivity.class, XmlItemActivity.class, TweakedItemViewActivity.class, SegmentedActivity.class,
+ ActionBarActivity.class, QuickActionActivity.class
+ };
+
+ public CatalogActivity() {
+ super(Type.Dashboard);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setActionBarContentView(R.layout.list);
+
+ ItemAdapter adapter = new ItemAdapter(this);
+ adapter.add(new TextItem("Basic items"));
+ adapter.add(new TextItem("XML items"));
+ adapter.add(new TextItem("Tweaked item cell"));
+ adapter.add(new TextItem("SegmentedBar"));
+ adapter.add(new TextItem("ActionBarActivity"));
+ adapter.add(new TextItem("QuickActionActivity"));
+
+ mListView = (ListView) findViewById(android.R.id.list);
+ mListView.setAdapter(adapter);
+ mListView.setOnItemClickListener(mItemClickHandler);
+ }
+
+ private OnItemClickListener mItemClickHandler = new OnItemClickListener() {
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ if (position >= 0 && position < mDemoClasses.length) {
+ Intent intent = new Intent(CatalogActivity.this, mDemoClasses[position]);
+
+ switch (position) {
+ case 4:
+ intent.putExtra(greendroid.app.ActionBarActivity.GD_ACTION_BAR_TITLE, "ActionBarActivity");
+ break;
+ }
+
+ startActivity(intent);
+ }
+ }
+ };
+
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/CatalogApplication.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/CatalogApplication.java
new file mode 100644
index 000000000..2fc1eadec
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/CatalogApplication.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDApplication;
+
+public class CatalogApplication extends GDApplication {
+
+ @Override
+ public Class> getHomeActivityClass() {
+ return CatalogActivity.class;
+ }
+
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/QuickActionActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/QuickActionActivity.java
new file mode 100644
index 000000000..459bb4b19
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/QuickActionActivity.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDActivity;
+import greendroid.widget.ActionBarItem;
+import greendroid.widget.ActionBarItem.Type;
+import greendroid.widget.QuickAction;
+import greendroid.widget.QuickActionBar;
+import greendroid.widget.QuickActionGrid;
+import greendroid.widget.QuickActionWidget;
+import greendroid.widget.QuickActionWidget.OnQuickActionClickListener;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+public class QuickActionActivity extends GDActivity {
+
+ private QuickActionWidget mBar;
+ private QuickActionWidget mGrid;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setActionBarContentView(R.layout.quick_action);
+
+ prepareQuickActionBar();
+ prepareQuickActionGrid();
+
+ addActionBarItem(Type.Edit);
+ }
+
+ public void onShowGrid(View v) {
+ mGrid.show(v);
+ }
+
+ public void onShowBar(View v) {
+ mBar.show(v);
+ }
+
+ @Override
+ public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
+
+ switch (position) {
+ case 0:
+ onShowGrid(item.getItemView());
+ break;
+
+ default:
+ return super.onHandleActionBarItemClick(item, position);
+ }
+
+ return true;
+ }
+
+ private void prepareQuickActionBar() {
+ mBar = new QuickActionBar(this);
+ mBar.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_compose_alt, R.string.gd_compose));
+ mBar.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_export_alt, R.string.gd_export));
+ mBar.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_share_alt, R.string.gd_share));
+
+ mBar.setOnQuickActionClickListener(mActionListener);
+ }
+
+ private void prepareQuickActionGrid() {
+ mGrid = new QuickActionGrid(this);
+ mGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_compose_alt, R.string.gd_compose));
+ mGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_export_alt, R.string.gd_export));
+ mGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_share_alt, R.string.gd_share));
+ mGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_search_alt, R.string.gd_search));
+ mGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_edit_alt, R.string.gd_edit));
+ mGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_locate_alt, R.string.gd_locate));
+
+ mGrid.setOnQuickActionClickListener(mActionListener);
+ }
+
+ private OnQuickActionClickListener mActionListener = new OnQuickActionClickListener() {
+ public void onQuickActionClicked(QuickActionWidget widget, int position) {
+ Toast.makeText(QuickActionActivity.this, "Item " + position + " clicked", Toast.LENGTH_SHORT).show();
+ }
+ };
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/SegmentedActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/SegmentedActivity.java
new file mode 100644
index 000000000..12adb7ba8
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/SegmentedActivity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDActivity;
+import greendroid.widget.SegmentedAdapter;
+import greendroid.widget.SegmentedHost;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class SegmentedActivity extends GDActivity {
+
+ private final Handler mHandler = new Handler();
+ private PeopleSegmentedAdapter mAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setActionBarContentView(R.layout.segmented_controls);
+
+ SegmentedHost segmentedHost = (SegmentedHost) findViewById(R.id.segmentedHost);
+
+ mAdapter = new PeopleSegmentedAdapter();
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ mAdapter.mReverse = true;
+ mAdapter.notifyDataSetChanged();
+ }
+ }, 4000);
+
+ segmentedHost.setAdapter(mAdapter);
+ }
+
+ private class PeopleSegmentedAdapter extends SegmentedAdapter {
+
+ public boolean mReverse = false;
+
+ @Override
+ public View getView(int position, ViewGroup parent) {
+ TextView textView = (TextView) getLayoutInflater().inflate(R.layout.text, parent, false);
+ textView.setText(getSegmentTitle(position));
+ return textView;
+ }
+
+ @Override
+ public int getCount() {
+ return 4;
+ }
+
+ @Override
+ public String getSegmentTitle(int position) {
+
+ switch (mReverse ? ((getCount() - 1) - position) : position) {
+ case 0:
+ return getString(R.string.segment_1);
+ case 1:
+ return getString(R.string.segment_2);
+ case 2:
+ return getString(R.string.segment_3);
+ case 3:
+ return getString(R.string.segment_4);
+ }
+
+ return null;
+ }
+ }
+
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/TabbedActionBarActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/TabbedActionBarActivity.java
new file mode 100644
index 000000000..f7ab76e62
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/TabbedActionBarActivity.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDTabActivity;
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class TabbedActionBarActivity extends GDTabActivity {
+
+ private static final String TAB1 = "tab_one";
+ private static final String TAB2 = "tab_two";
+ private static final String TAB3 = "tab_three";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setTitle("Screen 2");
+
+ Intent intent = new Intent(this, FakeActivity.class);
+ intent.putExtra(FakeActivity.EXTRA_COLOR, Color.BLACK);
+ intent.putExtra(FakeActivity.EXTRA_TEXT, "Content of tab #1");
+ addTab(TAB1, "Tab One", intent);
+
+ intent = new Intent(this, FakeActivity.class);
+ intent.putExtra(FakeActivity.EXTRA_COLOR, Color.rgb(20, 20, 20));
+ intent.putExtra(FakeActivity.EXTRA_TEXT, "Content of tab #2");
+ addTab(TAB2, "Tab Two", intent);
+
+ intent = new Intent(this, FakeActivity.class);
+ intent.putExtra(FakeActivity.EXTRA_COLOR, Color.rgb(40, 40, 40));
+ intent.putExtra(FakeActivity.EXTRA_TEXT, "Content of tab #3");
+ addTab(TAB3, "Tab Three", intent);
+ }
+
+ public static class FakeActivity extends Activity {
+
+ public static final String EXTRA_COLOR = "com.cyrilmottier.android.gdcatalog.TabbedActionBarActivity$FakeActivity.extraColor";
+ public static final String EXTRA_TEXT = "com.cyrilmottier.android.gdcatalog.TabbedActionBarActivity$FakeActivity.extraText";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Intent intent = getIntent();
+
+ if (intent != null) {
+ setContentView(R.layout.text);
+
+ TextView textView = (TextView) findViewById(R.id.text);
+ textView.setText(intent.getStringExtra(EXTRA_TEXT));
+ textView.setBackgroundColor(intent.getIntExtra(EXTRA_COLOR, Color.WHITE));
+ }
+ }
+
+ }
+
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/TweakedItemViewActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/TweakedItemViewActivity.java
new file mode 100644
index 000000000..1b55d45b8
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/TweakedItemViewActivity.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDListActivity;
+import greendroid.widget.ItemAdapter;
+import greendroid.widget.item.Item;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AlphabetIndexer;
+import android.widget.ListAdapter;
+import android.widget.SectionIndexer;
+
+import com.cyrilmottier.android.gdcatalog.widget.HeadedTextItem;
+
+public class TweakedItemViewActivity extends GDListActivity {
+
+ private static final String SECTIONS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ private static final HeadedTextItem CHEESES[] = {
+ new HeadedTextItem("Abbaye de Belloc"), new HeadedTextItem("Abbaye du Mont des Cats"),
+ new HeadedTextItem("Abertam"), new HeadedTextItem("Abondance"), new HeadedTextItem("Ackawi"),
+ new HeadedTextItem("Acorn"), new HeadedTextItem("Adelost"), new HeadedTextItem("Affidelice au Chablis"),
+ new HeadedTextItem("Afuega'l Pitu"), new HeadedTextItem("Airag"), new HeadedTextItem("Airedale"),
+ new HeadedTextItem("Aisy Cendre"), new HeadedTextItem("Allgauer Emmentaler"),
+ new HeadedTextItem("Alverca"), new HeadedTextItem("Ambert"), new HeadedTextItem("American Cheese"),
+ new HeadedTextItem("Ami du Chambertin"), new HeadedTextItem("Anejo Enchilado"),
+ new HeadedTextItem("Anneau du Vic-Bilh"), new HeadedTextItem("Anthoriro"), new HeadedTextItem("Appenzell"),
+ new HeadedTextItem("Aragon"), new HeadedTextItem("Ardi Gasna"), new HeadedTextItem("Ardrahan"),
+ new HeadedTextItem("Armenian String"), new HeadedTextItem("Aromes au Gene de Marc"),
+ new HeadedTextItem("Asadero"), new HeadedTextItem("Asiago"), new HeadedTextItem("Aubisque Pyrenees"),
+ new HeadedTextItem("Autun"), new HeadedTextItem("Avaxtskyr"), new HeadedTextItem("Baby Swiss"),
+ new HeadedTextItem("Babybel"), new HeadedTextItem("Baguette Laonnaise"), new HeadedTextItem("Bakers"),
+ new HeadedTextItem("Baladi"), new HeadedTextItem("Balaton"), new HeadedTextItem("Bandal"),
+ new HeadedTextItem("Banon"), new HeadedTextItem("Barry's Bay Cheddar"), new HeadedTextItem("Basing"),
+ new HeadedTextItem("Basket Cheese"), new HeadedTextItem("Bath Cheese"),
+ new HeadedTextItem("Bavarian Bergkase"), new HeadedTextItem("Baylough"), new HeadedTextItem("Beaufort"),
+ new HeadedTextItem("Beauvoorde"), new HeadedTextItem("Beenleigh Blue"), new HeadedTextItem("Beer Cheese"),
+ new HeadedTextItem("Bel Paese"), new HeadedTextItem("Bergader"), new HeadedTextItem("Bergere Bleue"),
+ new HeadedTextItem("Berkswell"), new HeadedTextItem("Beyaz Peynir"), new HeadedTextItem("Bierkase"),
+ new HeadedTextItem("Bishop Kennedy"), new HeadedTextItem("Blarney"), new HeadedTextItem("Bleu d'Auvergne"),
+ new HeadedTextItem("Bleu de Gex"), new HeadedTextItem("Bleu de Laqueuille"),
+ new HeadedTextItem("Bleu de Septmoncel"), new HeadedTextItem("Bleu Des Causses"),
+ new HeadedTextItem("Blue"), new HeadedTextItem("Blue Castello"), new HeadedTextItem("Blue Rathgore"),
+ new HeadedTextItem("Blue Vein (Australian)"), new HeadedTextItem("Blue Vein Cheeses"),
+ new HeadedTextItem("Bocconcini"), new HeadedTextItem("Bocconcini (Australian)"),
+ new HeadedTextItem("Boeren Leidenkaas"), new HeadedTextItem("Bonchester"), new HeadedTextItem("Bosworth"),
+ new HeadedTextItem("Bougon"), new HeadedTextItem("Boule Du Roves"),
+ new HeadedTextItem("Boulette d'Avesnes"), new HeadedTextItem("Boursault"), new HeadedTextItem("Boursin"),
+ new HeadedTextItem("Bouyssou"), new HeadedTextItem("Bra"), new HeadedTextItem("Braudostur"),
+ new HeadedTextItem("Breakfast Cheese"), new HeadedTextItem("Brebis du Lavort"),
+ new HeadedTextItem("Brebis du Lochois"), new HeadedTextItem("Brebis du Puyfaucon"),
+ new HeadedTextItem("Bresse Bleu"), new HeadedTextItem("Brick"), new HeadedTextItem("Brie"),
+ new HeadedTextItem("Brie de Meaux"), new HeadedTextItem("Brie de Melun"),
+ new HeadedTextItem("Brillat-Savarin"), new HeadedTextItem("Brin"), new HeadedTextItem("Brin d' Amour"),
+ new HeadedTextItem("Brin d'Amour"), new HeadedTextItem("Brinza (Burduf Brinza)"),
+ new HeadedTextItem("Briquette de Brebis"), new HeadedTextItem("Briquette du Forez"),
+ new HeadedTextItem("Broccio"), new HeadedTextItem("Broccio Demi-Affine"),
+ new HeadedTextItem("Brousse du Rove"), new HeadedTextItem("Bruder Basil"),
+ new HeadedTextItem("Brusselae Kaas (Fromage de Bruxelles)"), new HeadedTextItem("Bryndza"),
+ new HeadedTextItem("Buchette d'Anjou"), new HeadedTextItem("Buffalo"), new HeadedTextItem("Burgos"),
+ new HeadedTextItem("Butte"), new HeadedTextItem("Butterkase"), new HeadedTextItem("Button (Innes)"),
+ new HeadedTextItem("Buxton Blue"), new HeadedTextItem("Cabecou"), new HeadedTextItem("Caboc"),
+ new HeadedTextItem("Cabrales"), new HeadedTextItem("Cachaille"), new HeadedTextItem("Caciocavallo"),
+ new HeadedTextItem("Caciotta"), new HeadedTextItem("Caerphilly"), new HeadedTextItem("Cairnsmore"),
+ new HeadedTextItem("Calenzana"), new HeadedTextItem("Cambazola"),
+ new HeadedTextItem("Camembert de Normandie"), new HeadedTextItem("Canadian Cheddar"),
+ new HeadedTextItem("Canestrato"), new HeadedTextItem("Cantal"), new HeadedTextItem("Caprice des Dieux"),
+ new HeadedTextItem("Capricorn Goat"), new HeadedTextItem("Capriole Banon"),
+ new HeadedTextItem("Carre de l'Est"), new HeadedTextItem("Casciotta di Urbino"),
+ new HeadedTextItem("Cashel Blue"), new HeadedTextItem("Castellano"), new HeadedTextItem("Castelleno"),
+ new HeadedTextItem("Castelmagno"), new HeadedTextItem("Castelo Branco"), new HeadedTextItem("Castigliano"),
+ new HeadedTextItem("Cathelain"), new HeadedTextItem("Celtic Promise"),
+ new HeadedTextItem("Cendre d'Olivet"), new HeadedTextItem("Cerney"), new HeadedTextItem("Chabichou"),
+ new HeadedTextItem("Chabichou du Poitou"), new HeadedTextItem("Chabis de Gatine"),
+ new HeadedTextItem("Chaource"), new HeadedTextItem("Charolais"), new HeadedTextItem("Chaumes"),
+ new HeadedTextItem("Cheddar"), new HeadedTextItem("Cheddar Clothbound"), new HeadedTextItem("Cheshire"),
+ new HeadedTextItem("Chevres"), new HeadedTextItem("Chevrotin des Aravis"),
+ new HeadedTextItem("Chontaleno"), new HeadedTextItem("Civray"),
+ new HeadedTextItem("Coeur de Camembert au Calvados"), new HeadedTextItem("Coeur de Chevre"),
+ new HeadedTextItem("Colby"), new HeadedTextItem("Cold Pack"), new HeadedTextItem("Comte"),
+ new HeadedTextItem("Coolea"), new HeadedTextItem("Cooleney"), new HeadedTextItem("Coquetdale"),
+ new HeadedTextItem("Corleggy"), new HeadedTextItem("Cornish Pepper"), new HeadedTextItem("Cotherstone"),
+ new HeadedTextItem("Cotija"), new HeadedTextItem("Cottage Cheese"),
+ new HeadedTextItem("Cottage Cheese (Australian)"), new HeadedTextItem("Cougar Gold"),
+ new HeadedTextItem("Coulommiers"), new HeadedTextItem("Coverdale"), new HeadedTextItem("Crayeux de Roncq"),
+ new HeadedTextItem("Cream Cheese"), new HeadedTextItem("Cream Havarti"), new HeadedTextItem("Crema Agria"),
+ new HeadedTextItem("Crema Mexicana"), new HeadedTextItem("Creme Fraiche"), new HeadedTextItem("Crescenza"),
+ new HeadedTextItem("Croghan"), new HeadedTextItem("Crottin de Chavignol"),
+ new HeadedTextItem("Crottin du Chavignol"), new HeadedTextItem("Crowdie"), new HeadedTextItem("Crowley"),
+ new HeadedTextItem("Cuajada"), new HeadedTextItem("Curd"), new HeadedTextItem("Cure Nantais"),
+ new HeadedTextItem("Curworthy"), new HeadedTextItem("Cwmtawe Pecorino"),
+ new HeadedTextItem("Cypress Grove Chevre"), new HeadedTextItem("Danablu (Danish Blue)"),
+ new HeadedTextItem("Danbo"), new HeadedTextItem("Danish Fontina"), new HeadedTextItem("Daralagjazsky"),
+ new HeadedTextItem("Dauphin"), new HeadedTextItem("Delice des Fiouves"),
+ new HeadedTextItem("Denhany Dorset Drum"), new HeadedTextItem("Derby"),
+ new HeadedTextItem("Dessertnyj Belyj"), new HeadedTextItem("Devon Blue"),
+ new HeadedTextItem("Devon Garland"), new HeadedTextItem("Dolcelatte"), new HeadedTextItem("Doolin"),
+ new HeadedTextItem("Doppelrhamstufel"), new HeadedTextItem("Dorset Blue Vinney"),
+ new HeadedTextItem("Double Gloucester"), new HeadedTextItem("Double Worcester"),
+ new HeadedTextItem("Dreux a la Feuille"), new HeadedTextItem("Dry Jack"),
+ new HeadedTextItem("Duddleswell"), new HeadedTextItem("Dunbarra"), new HeadedTextItem("Dunlop"),
+ new HeadedTextItem("Dunsyre Blue"), new HeadedTextItem("Duroblando"), new HeadedTextItem("Durrus"),
+ new HeadedTextItem("Dutch Mimolette (Commissiekaas)"), new HeadedTextItem("Edam"),
+ new HeadedTextItem("Edelpilz"), new HeadedTextItem("Emental Grand Cru"), new HeadedTextItem("Emlett"),
+ new HeadedTextItem("Emmental"), new HeadedTextItem("Epoisses de Bourgogne"),
+ new HeadedTextItem("Esbareich"), new HeadedTextItem("Esrom"), new HeadedTextItem("Etorki"),
+ new HeadedTextItem("Evansdale Farmhouse Brie"), new HeadedTextItem("Evora De L'Alentejo"),
+ new HeadedTextItem("Exmoor Blue"), new HeadedTextItem("Explorateur"), new HeadedTextItem("Feta"),
+ new HeadedTextItem("Feta (Australian)"), new HeadedTextItem("Figue"), new HeadedTextItem("Filetta"),
+ new HeadedTextItem("Fin-de-Siecle"), new HeadedTextItem("Finlandia Swiss"), new HeadedTextItem("Finn"),
+ new HeadedTextItem("Fiore Sardo"), new HeadedTextItem("Fleur du Maquis"),
+ new HeadedTextItem("Flor de Guia"), new HeadedTextItem("Flower Marie"), new HeadedTextItem("Folded"),
+ new HeadedTextItem("Folded cheese with mint"), new HeadedTextItem("Fondant de Brebis"),
+ new HeadedTextItem("Fontainebleau"), new HeadedTextItem("Fontal"),
+ new HeadedTextItem("Fontina Val d'Aosta"), new HeadedTextItem("Formaggio di capra"),
+ new HeadedTextItem("Fougerus"), new HeadedTextItem("Four Herb Gouda"),
+ new HeadedTextItem("Fourme d' Ambert"), new HeadedTextItem("Fourme de Haute Loire"),
+ new HeadedTextItem("Fourme de Montbrison"), new HeadedTextItem("Fresh Jack"),
+ new HeadedTextItem("Fresh Mozzarella"), new HeadedTextItem("Fresh Ricotta"),
+ new HeadedTextItem("Fresh Truffles"), new HeadedTextItem("Fribourgeois"), new HeadedTextItem("Friesekaas"),
+ new HeadedTextItem("Friesian"), new HeadedTextItem("Friesla"), new HeadedTextItem("Frinault"),
+ new HeadedTextItem("Fromage a Raclette"), new HeadedTextItem("Fromage Corse"),
+ new HeadedTextItem("Fromage de Montagne de Savoie"), new HeadedTextItem("Fromage Frais"),
+ new HeadedTextItem("Fruit Cream Cheese"), new HeadedTextItem("Frying Cheese"), new HeadedTextItem("Fynbo"),
+ new HeadedTextItem("Gabriel"), new HeadedTextItem("Galette du Paludier"),
+ new HeadedTextItem("Galette Lyonnaise"), new HeadedTextItem("Galloway Goat's Milk Gems"),
+ new HeadedTextItem("Gammelost"), new HeadedTextItem("Gaperon a l'Ail"), new HeadedTextItem("Garrotxa"),
+ new HeadedTextItem("Gastanberra"), new HeadedTextItem("Geitost"), new HeadedTextItem("Gippsland Blue"),
+ new HeadedTextItem("Gjetost"), new HeadedTextItem("Gloucester"), new HeadedTextItem("Golden Cross"),
+ new HeadedTextItem("Gorgonzola"), new HeadedTextItem("Gornyaltajski"), new HeadedTextItem("Gospel Green"),
+ new HeadedTextItem("Gouda"), new HeadedTextItem("Goutu"), new HeadedTextItem("Gowrie"),
+ new HeadedTextItem("Grabetto"), new HeadedTextItem("Graddost"),
+ new HeadedTextItem("Grafton Village Cheddar"), new HeadedTextItem("Grana"),
+ new HeadedTextItem("Grana Padano"), new HeadedTextItem("Grand Vatel"),
+ new HeadedTextItem("Grataron d' Areches"), new HeadedTextItem("Gratte-Paille"),
+ new HeadedTextItem("Graviera"), new HeadedTextItem("Greuilh"), new HeadedTextItem("Greve"),
+ new HeadedTextItem("Gris de Lille"), new HeadedTextItem("Gruyere"), new HeadedTextItem("Gubbeen"),
+ new HeadedTextItem("Guerbigny"), new HeadedTextItem("Halloumi"),
+ new HeadedTextItem("Halloumy (Australian)"), new HeadedTextItem("Haloumi-Style Cheese"),
+ new HeadedTextItem("Harbourne Blue"), new HeadedTextItem("Havarti"), new HeadedTextItem("Heidi Gruyere"),
+ new HeadedTextItem("Hereford Hop"), new HeadedTextItem("Herrgardsost"),
+ new HeadedTextItem("Herriot Farmhouse"), new HeadedTextItem("Herve"), new HeadedTextItem("Hipi Iti"),
+ new HeadedTextItem("Hubbardston Blue Cow"), new HeadedTextItem("Hushallsost"),
+ new HeadedTextItem("Iberico"), new HeadedTextItem("Idaho Goatster"), new HeadedTextItem("Idiazabal"),
+ new HeadedTextItem("Il Boschetto al Tartufo"), new HeadedTextItem("Ile d'Yeu"),
+ new HeadedTextItem("Isle of Mull"), new HeadedTextItem("Jarlsberg"), new HeadedTextItem("Jermi Tortes"),
+ new HeadedTextItem("Jibneh Arabieh"), new HeadedTextItem("Jindi Brie"), new HeadedTextItem("Jubilee Blue"),
+ new HeadedTextItem("Juustoleipa"), new HeadedTextItem("Kadchgall"), new HeadedTextItem("Kaseri"),
+ new HeadedTextItem("Kashta"), new HeadedTextItem("Kefalotyri"), new HeadedTextItem("Kenafa"),
+ new HeadedTextItem("Kernhem"), new HeadedTextItem("Kervella Affine"), new HeadedTextItem("Kikorangi"),
+ new HeadedTextItem("King Island Cape Wickham Brie"), new HeadedTextItem("King River Gold"),
+ new HeadedTextItem("Klosterkaese"), new HeadedTextItem("Knockalara"), new HeadedTextItem("Kugelkase"),
+ new HeadedTextItem("L'Aveyronnais"), new HeadedTextItem("L'Ecir de l'Aubrac"),
+ new HeadedTextItem("La Taupiniere"), new HeadedTextItem("La Vache Qui Rit"),
+ new HeadedTextItem("Laguiole"), new HeadedTextItem("Lairobell"), new HeadedTextItem("Lajta"),
+ new HeadedTextItem("Lanark Blue"), new HeadedTextItem("Lancashire"), new HeadedTextItem("Langres"),
+ new HeadedTextItem("Lappi"), new HeadedTextItem("Laruns"), new HeadedTextItem("Lavistown"),
+ new HeadedTextItem("Le Brin"), new HeadedTextItem("Le Fium Orbo"), new HeadedTextItem("Le Lacandou"),
+ new HeadedTextItem("Le Roule"), new HeadedTextItem("Leafield"), new HeadedTextItem("Lebbene"),
+ new HeadedTextItem("Leerdammer"), new HeadedTextItem("Leicester"), new HeadedTextItem("Leyden"),
+ new HeadedTextItem("Limburger"), new HeadedTextItem("Lincolnshire Poacher"),
+ new HeadedTextItem("Lingot Saint Bousquet d'Orb"), new HeadedTextItem("Liptauer"),
+ new HeadedTextItem("Little Rydings"), new HeadedTextItem("Livarot"), new HeadedTextItem("Llanboidy"),
+ new HeadedTextItem("Llanglofan Farmhouse"), new HeadedTextItem("Loch Arthur Farmhouse"),
+ new HeadedTextItem("Loddiswell Avondale"), new HeadedTextItem("Longhorn"), new HeadedTextItem("Lou Palou"),
+ new HeadedTextItem("Lou Pevre"), new HeadedTextItem("Lyonnais"), new HeadedTextItem("Maasdam"),
+ new HeadedTextItem("Macconais"), new HeadedTextItem("Mahoe Aged Gouda"), new HeadedTextItem("Mahon"),
+ new HeadedTextItem("Malvern"), new HeadedTextItem("Mamirolle"), new HeadedTextItem("Manchego"),
+ new HeadedTextItem("Manouri"), new HeadedTextItem("Manur"), new HeadedTextItem("Marble Cheddar"),
+ new HeadedTextItem("Marbled Cheeses"), new HeadedTextItem("Maredsous"), new HeadedTextItem("Margotin"),
+ new HeadedTextItem("Maribo"), new HeadedTextItem("Maroilles"), new HeadedTextItem("Mascares"),
+ new HeadedTextItem("Mascarpone"), new HeadedTextItem("Mascarpone (Australian)"),
+ new HeadedTextItem("Mascarpone Torta"), new HeadedTextItem("Matocq"), new HeadedTextItem("Maytag Blue"),
+ new HeadedTextItem("Meira"), new HeadedTextItem("Menallack Farmhouse"), new HeadedTextItem("Menonita"),
+ new HeadedTextItem("Meredith Blue"), new HeadedTextItem("Mesost"),
+ new HeadedTextItem("Metton (Cancoillotte)"), new HeadedTextItem("Meyer Vintage Gouda"),
+ new HeadedTextItem("Mihalic Peynir"), new HeadedTextItem("Milleens"), new HeadedTextItem("Mimolette"),
+ new HeadedTextItem("Mine-Gabhar"), new HeadedTextItem("Mini Baby Bells"), new HeadedTextItem("Mixte"),
+ new HeadedTextItem("Molbo"), new HeadedTextItem("Monastery Cheeses"), new HeadedTextItem("Mondseer"),
+ new HeadedTextItem("Mont D'or Lyonnais"), new HeadedTextItem("Montasio"),
+ new HeadedTextItem("Monterey Jack"), new HeadedTextItem("Monterey Jack Dry"),
+ new HeadedTextItem("Morbier"), new HeadedTextItem("Morbier Cru de Montagne"),
+ new HeadedTextItem("Mothais a la Feuille"), new HeadedTextItem("Mozzarella"),
+ new HeadedTextItem("Mozzarella (Australian)"), new HeadedTextItem("Mozzarella di Bufala"),
+ new HeadedTextItem("Mozzarella Fresh, in water"), new HeadedTextItem("Mozzarella Rolls"),
+ new HeadedTextItem("Munster"), new HeadedTextItem("Murol"), new HeadedTextItem("Mycella"),
+ new HeadedTextItem("Myzithra"), new HeadedTextItem("Naboulsi"), new HeadedTextItem("Nantais"),
+ new HeadedTextItem("Neufchatel"), new HeadedTextItem("Neufchatel (Australian)"),
+ new HeadedTextItem("Niolo"), new HeadedTextItem("Nokkelost"), new HeadedTextItem("Northumberland"),
+ new HeadedTextItem("Oaxaca"), new HeadedTextItem("Olde York"), new HeadedTextItem("Olivet au Foin"),
+ new HeadedTextItem("Olivet Bleu"), new HeadedTextItem("Olivet Cendre"),
+ new HeadedTextItem("Orkney Extra Mature Cheddar"), new HeadedTextItem("Orla"),
+ new HeadedTextItem("Oschtjepka"), new HeadedTextItem("Ossau Fermier"), new HeadedTextItem("Ossau-Iraty"),
+ new HeadedTextItem("Oszczypek"), new HeadedTextItem("Oxford Blue"), new HeadedTextItem("P'tit Berrichon"),
+ new HeadedTextItem("Palet de Babligny"), new HeadedTextItem("Paneer"), new HeadedTextItem("Panela"),
+ new HeadedTextItem("Pannerone"), new HeadedTextItem("Pant ys Gawn"),
+ new HeadedTextItem("Parmesan (Parmigiano)"), new HeadedTextItem("Parmigiano Reggiano"),
+ new HeadedTextItem("Pas de l'Escalette"), new HeadedTextItem("Passendale"),
+ new HeadedTextItem("Pasteurized Processed"), new HeadedTextItem("Pate de Fromage"),
+ new HeadedTextItem("Patefine Fort"), new HeadedTextItem("Pave d'Affinois"),
+ new HeadedTextItem("Pave d'Auge"), new HeadedTextItem("Pave de Chirac"),
+ new HeadedTextItem("Pave du Berry"), new HeadedTextItem("Pecorino"),
+ new HeadedTextItem("Pecorino in Walnut Leaves"), new HeadedTextItem("Pecorino Romano"),
+ new HeadedTextItem("Peekskill Pyramid"), new HeadedTextItem("Pelardon des Cevennes"),
+ new HeadedTextItem("Pelardon des Corbieres"), new HeadedTextItem("Penamellera"),
+ new HeadedTextItem("Penbryn"), new HeadedTextItem("Pencarreg"), new HeadedTextItem("Perail de Brebis"),
+ new HeadedTextItem("Petit Morin"), new HeadedTextItem("Petit Pardou"), new HeadedTextItem("Petit-Suisse"),
+ new HeadedTextItem("Picodon de Chevre"), new HeadedTextItem("Picos de Europa"),
+ new HeadedTextItem("Piora"), new HeadedTextItem("Pithtviers au Foin"),
+ new HeadedTextItem("Plateau de Herve"), new HeadedTextItem("Plymouth Cheese"),
+ new HeadedTextItem("Podhalanski"), new HeadedTextItem("Poivre d'Ane"), new HeadedTextItem("Polkolbin"),
+ new HeadedTextItem("Pont l'Eveque"), new HeadedTextItem("Port Nicholson"),
+ new HeadedTextItem("Port-Salut"), new HeadedTextItem("Postel"),
+ new HeadedTextItem("Pouligny-Saint-Pierre"), new HeadedTextItem("Pourly"), new HeadedTextItem("Prastost"),
+ new HeadedTextItem("Pressato"), new HeadedTextItem("Prince-Jean"), new HeadedTextItem("Processed Cheddar"),
+ new HeadedTextItem("Provolone"), new HeadedTextItem("Provolone (Australian)"),
+ new HeadedTextItem("Pyengana Cheddar"), new HeadedTextItem("Pyramide"), new HeadedTextItem("Quark"),
+ new HeadedTextItem("Quark (Australian)"), new HeadedTextItem("Quartirolo Lombardo"),
+ new HeadedTextItem("Quatre-Vents"), new HeadedTextItem("Quercy Petit"), new HeadedTextItem("Queso Blanco"),
+ new HeadedTextItem("Queso Blanco con Frutas --Pina y Mango"), new HeadedTextItem("Queso de Murcia"),
+ new HeadedTextItem("Queso del Montsec"), new HeadedTextItem("Queso del Tietar"),
+ new HeadedTextItem("Queso Fresco"), new HeadedTextItem("Queso Fresco (Adobera)"),
+ new HeadedTextItem("Queso Iberico"), new HeadedTextItem("Queso Jalapeno"),
+ new HeadedTextItem("Queso Majorero"), new HeadedTextItem("Queso Media Luna"),
+ new HeadedTextItem("Queso Para Frier"), new HeadedTextItem("Queso Quesadilla"),
+ new HeadedTextItem("Rabacal"), new HeadedTextItem("Raclette"), new HeadedTextItem("Ragusano"),
+ new HeadedTextItem("Raschera"), new HeadedTextItem("Reblochon"), new HeadedTextItem("Red Leicester"),
+ new HeadedTextItem("Regal de la Dombes"), new HeadedTextItem("Reggianito"), new HeadedTextItem("Remedou"),
+ new HeadedTextItem("Requeson"), new HeadedTextItem("Richelieu"), new HeadedTextItem("Ricotta"),
+ new HeadedTextItem("Ricotta (Australian)"), new HeadedTextItem("Ricotta Salata"),
+ new HeadedTextItem("Ridder"), new HeadedTextItem("Rigotte"), new HeadedTextItem("Rocamadour"),
+ new HeadedTextItem("Rollot"), new HeadedTextItem("Romano"), new HeadedTextItem("Romans Part Dieu"),
+ new HeadedTextItem("Roncal"), new HeadedTextItem("Roquefort"), new HeadedTextItem("Roule"),
+ new HeadedTextItem("Rouleau De Beaulieu"), new HeadedTextItem("Royalp Tilsit"),
+ new HeadedTextItem("Rubens"), new HeadedTextItem("Rustinu"), new HeadedTextItem("Saaland Pfarr"),
+ new HeadedTextItem("Saanenkaese"), new HeadedTextItem("Saga"), new HeadedTextItem("Sage Derby"),
+ new HeadedTextItem("Sainte Maure"), new HeadedTextItem("Saint-Marcellin"),
+ new HeadedTextItem("Saint-Nectaire"), new HeadedTextItem("Saint-Paulin"), new HeadedTextItem("Salers"),
+ new HeadedTextItem("Samso"), new HeadedTextItem("San Simon"), new HeadedTextItem("Sancerre"),
+ new HeadedTextItem("Sap Sago"), new HeadedTextItem("Sardo"), new HeadedTextItem("Sardo Egyptian"),
+ new HeadedTextItem("Sbrinz"), new HeadedTextItem("Scamorza"), new HeadedTextItem("Schabzieger"),
+ new HeadedTextItem("Schloss"), new HeadedTextItem("Selles sur Cher"), new HeadedTextItem("Selva"),
+ new HeadedTextItem("Serat"), new HeadedTextItem("Seriously Strong Cheddar"),
+ new HeadedTextItem("Serra da Estrela"), new HeadedTextItem("Sharpam"),
+ new HeadedTextItem("Shelburne Cheddar"), new HeadedTextItem("Shropshire Blue"),
+ new HeadedTextItem("Siraz"), new HeadedTextItem("Sirene"), new HeadedTextItem("Smoked Gouda"),
+ new HeadedTextItem("Somerset Brie"), new HeadedTextItem("Sonoma Jack"),
+ new HeadedTextItem("Sottocenare al Tartufo"), new HeadedTextItem("Soumaintrain"),
+ new HeadedTextItem("Sourire Lozerien"), new HeadedTextItem("Spenwood"),
+ new HeadedTextItem("Sraffordshire Organic"), new HeadedTextItem("St. Agur Blue Cheese"),
+ new HeadedTextItem("Stilton"), new HeadedTextItem("Stinking Bishop"), new HeadedTextItem("String"),
+ new HeadedTextItem("Sussex Slipcote"), new HeadedTextItem("Sveciaost"), new HeadedTextItem("Swaledale"),
+ new HeadedTextItem("Sweet Style Swiss"), new HeadedTextItem("Swiss"),
+ new HeadedTextItem("Syrian (Armenian String)"), new HeadedTextItem("Tala"), new HeadedTextItem("Taleggio"),
+ new HeadedTextItem("Tamie"), new HeadedTextItem("Tasmania Highland Chevre Log"),
+ new HeadedTextItem("Taupiniere"), new HeadedTextItem("Teifi"), new HeadedTextItem("Telemea"),
+ new HeadedTextItem("Testouri"), new HeadedTextItem("Tete de Moine"), new HeadedTextItem("Tetilla"),
+ new HeadedTextItem("Texas Goat Cheese"), new HeadedTextItem("Tibet"),
+ new HeadedTextItem("Tillamook Cheddar"), new HeadedTextItem("Tilsit"), new HeadedTextItem("Timboon Brie"),
+ new HeadedTextItem("Toma"), new HeadedTextItem("Tomme Brulee"), new HeadedTextItem("Tomme d'Abondance"),
+ new HeadedTextItem("Tomme de Chevre"), new HeadedTextItem("Tomme de Romans"),
+ new HeadedTextItem("Tomme de Savoie"), new HeadedTextItem("Tomme des Chouans"),
+ new HeadedTextItem("Tommes"), new HeadedTextItem("Torta del Casar"), new HeadedTextItem("Toscanello"),
+ new HeadedTextItem("Touree de L'Aubier"), new HeadedTextItem("Tourmalet"),
+ new HeadedTextItem("Trappe (Veritable)"), new HeadedTextItem("Trois Cornes De Vendee"),
+ new HeadedTextItem("Tronchon"), new HeadedTextItem("Trou du Cru"), new HeadedTextItem("Truffe"),
+ new HeadedTextItem("Tupi"), new HeadedTextItem("Turunmaa"), new HeadedTextItem("Tymsboro"),
+ new HeadedTextItem("Tyn Grug"), new HeadedTextItem("Tyning"), new HeadedTextItem("Ubriaco"),
+ new HeadedTextItem("Ulloa"), new HeadedTextItem("Vacherin-Fribourgeois"), new HeadedTextItem("Valencay"),
+ new HeadedTextItem("Vasterbottenost"), new HeadedTextItem("Venaco"), new HeadedTextItem("Vendomois"),
+ new HeadedTextItem("Vieux Corse"), new HeadedTextItem("Vignotte"), new HeadedTextItem("Vulscombe"),
+ new HeadedTextItem("Waimata Farmhouse Blue"), new HeadedTextItem("Washed Rind Cheese (Australian)"),
+ new HeadedTextItem("Waterloo"), new HeadedTextItem("Weichkaese"), new HeadedTextItem("Wellington"),
+ new HeadedTextItem("Wensleydale"), new HeadedTextItem("White Stilton"),
+ new HeadedTextItem("Whitestone Farmhouse"), new HeadedTextItem("Wigmore"),
+ new HeadedTextItem("Woodside Cabecou"), new HeadedTextItem("Xanadu"), new HeadedTextItem("Xynotyro"),
+ new HeadedTextItem("Yarg Cornish"), new HeadedTextItem("Yarra Valley Pyramid"),
+ new HeadedTextItem("Yorkshire Blue"), new HeadedTextItem("Zamorano"),
+ new HeadedTextItem("Zanetti Grana Padano"), new HeadedTextItem("Zanetti Parmigiano Reggiano")
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ItemAdapter adapter = new SectionedItemAdapter(this, CHEESES, SECTIONS);
+ getListView().setFastScrollEnabled(true);
+ setListAdapter(adapter);
+ }
+
+ /**
+ * A SectionedItemAdapter is an extension of an ItemAdapter that implements
+ * SectionIndexer. Thanks to it, the fast scroller will act like the one in
+ * the contact app.
+ *
+ * @author Cyril Mottier
+ */
+ private class SectionedItemAdapter extends ItemAdapter implements SectionIndexer {
+
+ private AlphabetIndexer mIndexer;
+
+ public SectionedItemAdapter(Context context, Item[] items, String sections) {
+ super(context, items);
+ mIndexer = new AlphabetIndexer(new FakeCursor(this), 0, sections);
+ }
+
+ public int getPositionForSection(int sectionIndex) {
+ return mIndexer.getPositionForSection(sectionIndex);
+ }
+
+ public int getSectionForPosition(int position) {
+ return mIndexer.getSectionForPosition(position);
+ }
+
+ public Object[] getSections() {
+ return mIndexer.getSections();
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+
+ final HeadedTextItem item = (HeadedTextItem) getItem(position);
+ final int section = getSectionForPosition(position);
+
+ if (getPositionForSection(section) == position) {
+ String title = mIndexer.getSections()[section].toString().trim();
+ item.headerText = title;
+ } else {
+ item.headerText = null;
+ }
+
+ return super.getView(position, convertView, parent);
+ }
+
+ }
+
+ /**
+ * An implementation of a Cursor that is almost useless. It is simply used
+ * for the SectionIndexer to browse our underlying data.
+ *
+ * @author Cyril Mottier
+ */
+ private class FakeCursor implements Cursor {
+
+ private ListAdapter mAdapter;
+ private int mPosition;
+
+ public FakeCursor(ListAdapter adapter) {
+ mAdapter = adapter;
+ }
+
+ public void close() {
+ }
+
+ public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
+ }
+
+ public void deactivate() {
+ }
+
+ public byte[] getBlob(int columnIndex) {
+ return null;
+ }
+
+ public int getColumnCount() {
+ return 0;
+ }
+
+ public int getColumnIndex(String columnName) {
+ return 0;
+ }
+
+ public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
+ return 0;
+ }
+
+ public String getColumnName(int columnIndex) {
+ return null;
+ }
+
+ public String[] getColumnNames() {
+ return null;
+ }
+
+ public int getCount() {
+ return mAdapter.getCount();
+ }
+
+ public double getDouble(int columnIndex) {
+ return 0;
+ }
+
+ public Bundle getExtras() {
+ return null;
+ }
+
+ public float getFloat(int columnIndex) {
+ return 0;
+ }
+
+ public int getInt(int columnIndex) {
+ return 0;
+ }
+
+ public long getLong(int columnIndex) {
+ return 0;
+ }
+
+ public int getPosition() {
+ return 0;
+ }
+
+ public short getShort(int columnIndex) {
+ return 0;
+ }
+
+ public String getString(int columnIndex) {
+ final HeadedTextItem item = (HeadedTextItem) mAdapter.getItem(mPosition);
+ return (String) item.text.substring(0, 1);
+ }
+
+ public boolean getWantsAllOnMoveCalls() {
+ return false;
+ }
+
+ public boolean isAfterLast() {
+ return false;
+ }
+
+ public boolean isBeforeFirst() {
+ return false;
+ }
+
+ public boolean isClosed() {
+ return false;
+ }
+
+ public boolean isFirst() {
+ return false;
+ }
+
+ public boolean isLast() {
+ return false;
+ }
+
+ public boolean isNull(int columnIndex) {
+ return false;
+ }
+
+ public boolean move(int offset) {
+ return false;
+ }
+
+ public boolean moveToFirst() {
+ return false;
+ }
+
+ public boolean moveToLast() {
+ return false;
+ }
+
+ public boolean moveToNext() {
+ return false;
+ }
+
+ public boolean moveToPosition(int position) {
+ if (position < -1 || position > getCount()) {
+ return false;
+ }
+ mPosition = position;
+ return true;
+ }
+
+ public boolean moveToPrevious() {
+ return false;
+ }
+
+ public void registerContentObserver(ContentObserver observer) {
+ }
+
+ public void registerDataSetObserver(DataSetObserver observer) {
+ }
+
+ public boolean requery() {
+ return false;
+ }
+
+ public Bundle respond(Bundle extras) {
+ return null;
+ }
+
+ public void setNotificationUri(ContentResolver cr, Uri uri) {
+ }
+
+ public void unregisterContentObserver(ContentObserver observer) {
+ }
+
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ }
+ }
+
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/XmlItemActivity.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/XmlItemActivity.java
new file mode 100644
index 000000000..95e047df2
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/XmlItemActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog;
+
+import greendroid.app.GDListActivity;
+import greendroid.widget.ItemAdapter;
+import android.os.Bundle;
+
+public class XmlItemActivity extends GDListActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ItemAdapter adapter;
+ try {
+ adapter = ItemAdapter.createFromXml(this, R.xml.items);
+ setListAdapter(adapter);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/widget/HeadedTextItem.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/widget/HeadedTextItem.java
new file mode 100644
index 000000000..0719bdd67
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/widget/HeadedTextItem.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog.widget;
+
+import greendroid.widget.item.TextItem;
+import greendroid.widget.itemview.ItemView;
+import android.content.Context;
+import android.view.ViewGroup;
+
+import com.cyrilmottier.android.gdcatalog.R;
+
+public class HeadedTextItem extends TextItem {
+
+ public String headerText;
+
+ public HeadedTextItem(String text) {
+ super(text);
+ }
+
+ @Override
+ public ItemView newView(Context context, ViewGroup parent) {
+ return createCellFromXml(context, R.layout.headed_text_item_view, parent);
+ }
+}
diff --git a/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/widget/HeadedTextItemView.java b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/widget/HeadedTextItemView.java
new file mode 100644
index 000000000..835cc3df6
--- /dev/null
+++ b/greendroid/GDCatalog/src/com/cyrilmottier/android/gdcatalog/widget/HeadedTextItemView.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package com.cyrilmottier.android.gdcatalog.widget;
+
+import greendroid.widget.item.Item;
+import greendroid.widget.itemview.ItemView;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.cyrilmottier.android.gdcatalog.R;
+
+public class HeadedTextItemView extends LinearLayout implements ItemView {
+
+ private TextView mHeaderView;
+ private TextView mTextView;
+
+ public HeadedTextItemView(Context context) {
+ this(context, null);
+ }
+
+ public HeadedTextItemView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void prepareItemView() {
+ mHeaderView = (TextView) findViewById(R.id.gd_separator_text);
+ mTextView = (TextView) findViewById(R.id.gd_text);
+ }
+
+ public void setObject(Item object) {
+
+ final HeadedTextItem item = (HeadedTextItem) object;
+ final String headerText = item.headerText;
+
+ if (!TextUtils.isEmpty(headerText)) {
+ mHeaderView.setText(headerText);
+ mHeaderView.setVisibility(View.VISIBLE);
+ } else {
+ mHeaderView.setVisibility(View.GONE);
+ }
+
+ mTextView.setText(item.text);
+ }
+
+}
diff --git a/greendroid/GreenDroid/.classpath b/greendroid/GreenDroid/.classpath
new file mode 100644
index 000000000..609aa00eb
--- /dev/null
+++ b/greendroid/GreenDroid/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/.project b/greendroid/GreenDroid/.project
new file mode 100644
index 000000000..fcb384fde
--- /dev/null
+++ b/greendroid/GreenDroid/.project
@@ -0,0 +1,33 @@
+
+
+ GreenDroid
+
+
+
+
+
+ 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/greendroid/GreenDroid/AndroidManifest.xml b/greendroid/GreenDroid/AndroidManifest.xml
new file mode 100644
index 000000000..e27a36698
--- /dev/null
+++ b/greendroid/GreenDroid/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/default.properties b/greendroid/GreenDroid/default.properties
new file mode 100644
index 000000000..483b7d187
--- /dev/null
+++ b/greendroid/GreenDroid/default.properties
@@ -0,0 +1,14 @@
+# 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,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+android.library=true
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-4
diff --git a/greendroid/GreenDroid/res/anim/gd_grow_from_bottom.xml b/greendroid/GreenDroid/res/anim/gd_grow_from_bottom.xml
new file mode 100644
index 000000000..0ac697564
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_grow_from_bottom.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/anim/gd_grow_from_bottomleft_to_topright.xml b/greendroid/GreenDroid/res/anim/gd_grow_from_bottomleft_to_topright.xml
new file mode 100644
index 000000000..954b7d7a6
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_grow_from_bottomleft_to_topright.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/anim/gd_grow_from_bottomright_to_topleft.xml b/greendroid/GreenDroid/res/anim/gd_grow_from_bottomright_to_topleft.xml
new file mode 100644
index 000000000..19d25b39c
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_grow_from_bottomright_to_topleft.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/anim/gd_grow_from_top.xml b/greendroid/GreenDroid/res/anim/gd_grow_from_top.xml
new file mode 100644
index 000000000..a69a75187
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_grow_from_top.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/anim/gd_grow_from_topleft_to_bottomright.xml b/greendroid/GreenDroid/res/anim/gd_grow_from_topleft_to_bottomright.xml
new file mode 100644
index 000000000..00460f66b
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_grow_from_topleft_to_bottomright.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/anim/gd_grow_from_topright_to_bottomleft.xml b/greendroid/GreenDroid/res/anim/gd_grow_from_topright_to_bottomleft.xml
new file mode 100644
index 000000000..244f28e7c
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_grow_from_topright_to_bottomleft.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/anim/gd_rack.xml b/greendroid/GreenDroid/res/anim/gd_rack.xml
new file mode 100644
index 000000000..850d5d92e
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_rack.xml
@@ -0,0 +1,24 @@
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/anim/gd_shrink_from_bottom.xml b/greendroid/GreenDroid/res/anim/gd_shrink_from_bottom.xml
new file mode 100644
index 000000000..0bdf50fda
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_shrink_from_bottom.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/anim/gd_shrink_from_bottomleft_to_topright.xml b/greendroid/GreenDroid/res/anim/gd_shrink_from_bottomleft_to_topright.xml
new file mode 100644
index 000000000..6c8fe1c47
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_shrink_from_bottomleft_to_topright.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/anim/gd_shrink_from_bottomright_to_topleft.xml b/greendroid/GreenDroid/res/anim/gd_shrink_from_bottomright_to_topleft.xml
new file mode 100644
index 000000000..b115a2324
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_shrink_from_bottomright_to_topleft.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/anim/gd_shrink_from_top.xml b/greendroid/GreenDroid/res/anim/gd_shrink_from_top.xml
new file mode 100644
index 000000000..a6c07d861
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_shrink_from_top.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/anim/gd_shrink_from_topleft_to_bottomright.xml b/greendroid/GreenDroid/res/anim/gd_shrink_from_topleft_to_bottomright.xml
new file mode 100644
index 000000000..3a900abc3
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_shrink_from_topleft_to_bottomright.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/anim/gd_shrink_from_topright_to_bottomleft.xml b/greendroid/GreenDroid/res/anim/gd_shrink_from_topright_to_bottomleft.xml
new file mode 100644
index 000000000..784b6e7ed
--- /dev/null
+++ b/greendroid/GreenDroid/res/anim/gd_shrink_from_topright_to_bottomleft.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_add_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_add_alt.png
new file mode 100644
index 000000000..02928ce42
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_add_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_add_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_add_normal.png
new file mode 100644
index 000000000..646721036
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_add_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_compose_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_compose_alt.png
new file mode 100644
index 000000000..7e796f826
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_compose_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_compose_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_compose_normal.png
new file mode 100644
index 000000000..cdb09e4c6
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_compose_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_edit_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_edit_alt.png
new file mode 100644
index 000000000..69dd7047e
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_edit_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_edit_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_edit_normal.png
new file mode 100644
index 000000000..4f6df07dd
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_edit_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_export_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_export_alt.png
new file mode 100644
index 000000000..0de5f13cf
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_export_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_export_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_export_normal.png
new file mode 100644
index 000000000..b86014d5f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_export_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_home_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_home_alt.png
new file mode 100644
index 000000000..7f2e9aabc
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_home_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_home_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_home_normal.png
new file mode 100644
index 000000000..af72258bb
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_home_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_item_focused.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_item_focused.9.png
new file mode 100644
index 000000000..7c0ec2b20
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_item_focused.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_item_pressed.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_item_pressed.9.png
new file mode 100644
index 000000000..15a0f12d6
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_item_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_alt.png
new file mode 100644
index 000000000..567d9a5d3
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_myself_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_myself_alt.png
new file mode 100644
index 000000000..ff56c1aa2
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_myself_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_myself_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_myself_normal.png
new file mode 100644
index 000000000..12988bbb0
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_myself_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_normal.png
new file mode 100644
index 000000000..21b88856b
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_locate_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_refresh_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_refresh_alt.png
new file mode 100644
index 000000000..deb707572
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_refresh_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_refresh_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_refresh_normal.png
new file mode 100644
index 000000000..08c32e09e
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_refresh_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_search_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_search_alt.png
new file mode 100644
index 000000000..1c66fd61e
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_search_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_search_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_search_normal.png
new file mode 100644
index 000000000..59de344e7
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_search_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_share_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_share_alt.png
new file mode 100644
index 000000000..95739a8f4
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_share_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_share_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_share_normal.png
new file mode 100644
index 000000000..e748c85d2
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_share_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_sort_by_size_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_sort_by_size_alt.png
new file mode 100644
index 000000000..406dd472c
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_sort_by_size_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_sort_by_size_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_sort_by_size_normal.png
new file mode 100644
index 000000000..5704059bd
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_sort_by_size_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_star_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_star_alt.png
new file mode 100644
index 000000000..c5ca051c0
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_star_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_star_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_star_normal.png
new file mode 100644
index 000000000..db9ab8ad4
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_star_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_take_photo_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_take_photo_alt.png
new file mode 100644
index 000000000..e89646496
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_take_photo_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_take_photo_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_take_photo_normal.png
new file mode 100644
index 000000000..59c80954f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_take_photo_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_talk_alt.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_talk_alt.png
new file mode 100644
index 000000000..53e983bab
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_talk_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_talk_normal.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_talk_normal.png
new file mode 100644
index 000000000..cd355b0f7
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_action_bar_talk_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_arrow_up.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_arrow_up.png
new file mode 100644
index 000000000..6daf90ac8
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_arrow_up.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_arrow_down.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_arrow_down.png
new file mode 100644
index 000000000..7eba7567c
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_arrow_down.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_background.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_background.png
new file mode 100644
index 000000000..c9c09ee97
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_background.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_bottom_frame.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_bottom_frame.9.png
new file mode 100644
index 000000000..9fac22558
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_bottom_frame.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_grip_left.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_grip_left.9.png
new file mode 100644
index 000000000..aab0e5832
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_grip_left.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_grip_right.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_grip_right.9.png
new file mode 100644
index 000000000..2d877b7e7
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_grip_right.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_normal.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_normal.9.png
new file mode 100644
index 000000000..9d3d7ad8d
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_normal.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_pressed.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_pressed.9.png
new file mode 100644
index 000000000..d9da59840
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_selected.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_selected.9.png
new file mode 100644
index 000000000..72d053b84
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_bar_item_selected.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_arrow_down.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_arrow_down.png
new file mode 100644
index 000000000..a37c6f5e1
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_arrow_down.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_bg.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_bg.9.png
new file mode 100644
index 000000000..c01210a80
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_bg.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_bottom_frame.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_bottom_frame.9.png
new file mode 100644
index 000000000..b3b6b8a23
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_bottom_frame.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_selector_focused.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_selector_focused.9.png
new file mode 100644
index 000000000..a6add7acc
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_selector_focused.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_selector_pressed.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_selector_pressed.9.png
new file mode 100644
index 000000000..79595a73f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_grid_selector_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_top_frame.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_top_frame.9.png
new file mode 100644
index 000000000..4556bb225
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_quick_action_top_frame.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_checkmark_off.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_checkmark_off.png
new file mode 100644
index 000000000..1581dcc0e
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_checkmark_off.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_checkmark_on.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_checkmark_on.png
new file mode 100644
index 000000000..6b6ffd33b
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_checkmark_on.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_divider.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_divider.png
new file mode 100644
index 000000000..1fa7b7cf0
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_divider.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_focused.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_focused.9.png
new file mode 100644
index 000000000..627eda924
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_focused.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_normal.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_normal.9.png
new file mode 100644
index 000000000..9b4ff043a
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_normal.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_pressed.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_pressed.9.png
new file mode 100644
index 000000000..d0b997e1f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_segment_label_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_shadow_bottom.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_shadow_bottom.9.png
new file mode 100644
index 000000000..91f8313fa
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_shadow_bottom.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_shadow_top.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_shadow_top.9.png
new file mode 100644
index 000000000..0217c677b
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_shadow_top.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_normal.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_normal.9.png
new file mode 100644
index 000000000..ed6014cde
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_normal.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_pressed.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_pressed.9.png
new file mode 100644
index 000000000..c41c0a7cb
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_selected.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_selected.9.png
new file mode 100644
index 000000000..f3f015641
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_selected.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_unselected.9.png b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_unselected.9.png
new file mode 100644
index 000000000..9188fdfd6
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-hdpi/gd_tab_indicator_unselected.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_add_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_add_alt.png
new file mode 100644
index 000000000..f937e2975
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_add_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_add_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_add_normal.png
new file mode 100644
index 000000000..b98becf2f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_add_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_compose_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_compose_alt.png
new file mode 100644
index 000000000..58bd44e05
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_compose_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_compose_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_compose_normal.png
new file mode 100644
index 000000000..15a413053
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_compose_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_edit_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_edit_alt.png
new file mode 100644
index 000000000..3c5df4b98
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_edit_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_edit_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_edit_normal.png
new file mode 100644
index 000000000..1ec583571
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_edit_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_export_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_export_alt.png
new file mode 100644
index 000000000..311993398
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_export_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_export_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_export_normal.png
new file mode 100644
index 000000000..04d3f523e
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_export_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_home_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_home_alt.png
new file mode 100644
index 000000000..d2a39b7e2
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_home_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_home_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_home_normal.png
new file mode 100644
index 000000000..65532b8f3
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_home_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_item_focused.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_item_focused.9.png
new file mode 100644
index 000000000..3286f4a31
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_item_focused.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_item_pressed.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_item_pressed.9.png
new file mode 100644
index 000000000..936b8d5c1
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_item_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_alt.png
new file mode 100644
index 000000000..dff5cfea9
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_myself_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_myself_alt.png
new file mode 100644
index 000000000..106520893
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_myself_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_myself_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_myself_normal.png
new file mode 100644
index 000000000..85c5091e6
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_myself_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_normal.png
new file mode 100644
index 000000000..2e7c2beb9
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_locate_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_refresh_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_refresh_alt.png
new file mode 100644
index 000000000..cf21163e4
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_refresh_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_refresh_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_refresh_normal.png
new file mode 100644
index 000000000..55c43c327
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_refresh_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_search_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_search_alt.png
new file mode 100644
index 000000000..8ab5faeb2
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_search_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_search_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_search_normal.png
new file mode 100644
index 000000000..75339d906
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_search_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_share_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_share_alt.png
new file mode 100644
index 000000000..b6f90f9fa
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_share_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_share_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_share_normal.png
new file mode 100644
index 000000000..cd3261a4f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_share_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_sort_by_size_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_sort_by_size_alt.png
new file mode 100644
index 000000000..2e588d03e
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_sort_by_size_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_sort_by_size_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_sort_by_size_normal.png
new file mode 100644
index 000000000..9ece069ab
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_sort_by_size_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_star_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_star_alt.png
new file mode 100644
index 000000000..a61e21f59
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_star_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_star_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_star_normal.png
new file mode 100644
index 000000000..d5c58050a
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_star_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_take_photo_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_take_photo_alt.png
new file mode 100644
index 000000000..b6bd6e765
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_take_photo_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_take_photo_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_take_photo_normal.png
new file mode 100644
index 000000000..4a745eab5
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_take_photo_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_talk_alt.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_talk_alt.png
new file mode 100644
index 000000000..d8a5d3691
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_talk_alt.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_talk_normal.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_talk_normal.png
new file mode 100644
index 000000000..2bd2f70c2
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_action_bar_talk_normal.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_arrow_up.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_arrow_up.png
new file mode 100644
index 000000000..1a6fa2e8f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_arrow_up.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_arrow_down.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_arrow_down.png
new file mode 100644
index 000000000..3ba6c8cbd
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_arrow_down.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_background.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_background.png
new file mode 100644
index 000000000..b6a9f9182
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_background.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_bottom_frame.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_bottom_frame.9.png
new file mode 100644
index 000000000..6f843065f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_bottom_frame.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_grip_left.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_grip_left.9.png
new file mode 100644
index 000000000..7f26b9919
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_grip_left.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_grip_right.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_grip_right.9.png
new file mode 100644
index 000000000..2bfb75b29
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_grip_right.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_normal.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_normal.9.png
new file mode 100644
index 000000000..cf4f1e4ff
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_normal.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_pressed.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_pressed.9.png
new file mode 100644
index 000000000..d4916f5e1
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_selected.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_selected.9.png
new file mode 100644
index 000000000..b91002890
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_bar_item_selected.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_arrow_down.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_arrow_down.png
new file mode 100644
index 000000000..cc8b41ff5
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_arrow_down.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_bg.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_bg.9.png
new file mode 100644
index 000000000..3e851bf36
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_bg.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_bottom_frame.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_bottom_frame.9.png
new file mode 100644
index 000000000..b6c7a9c16
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_bottom_frame.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_selector_focused.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_selector_focused.9.png
new file mode 100644
index 000000000..1ae99bf4f
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_selector_focused.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_selector_pressed.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_selector_pressed.9.png
new file mode 100644
index 000000000..6f53dddd1
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_grid_selector_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_top_frame.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_top_frame.9.png
new file mode 100644
index 000000000..6d433058d
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_quick_action_top_frame.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_checkmark_off.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_checkmark_off.png
new file mode 100644
index 000000000..60b10e605
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_checkmark_off.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_checkmark_on.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_checkmark_on.png
new file mode 100644
index 000000000..1db1f22b6
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_checkmark_on.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_divider.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_divider.png
new file mode 100644
index 000000000..236f90fa2
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_divider.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_focused.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_focused.9.png
new file mode 100644
index 000000000..56e27bcba
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_focused.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_normal.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_normal.9.png
new file mode 100644
index 000000000..99843930a
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_normal.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_pressed.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_pressed.9.png
new file mode 100644
index 000000000..490bc7372
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_segment_label_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_shadow_bottom.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_shadow_bottom.9.png
new file mode 100644
index 000000000..efd35a5b6
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_shadow_bottom.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_shadow_top.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_shadow_top.9.png
new file mode 100644
index 000000000..63a1a5d45
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_shadow_top.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_normal.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_normal.9.png
new file mode 100644
index 000000000..6358bb8d3
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_normal.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_pressed.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_pressed.9.png
new file mode 100644
index 000000000..f0030f698
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_pressed.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_selected.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_selected.9.png
new file mode 100644
index 000000000..a02efb1db
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_selected.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_unselected.9.png b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_unselected.9.png
new file mode 100644
index 000000000..f47f042b1
Binary files /dev/null and b/greendroid/GreenDroid/res/drawable-mdpi/gd_tab_indicator_unselected.9.png differ
diff --git a/greendroid/GreenDroid/res/drawable/gd_action_bar_home.xml b/greendroid/GreenDroid/res/drawable/gd_action_bar_home.xml
new file mode 100644
index 000000000..e744dd9bb
--- /dev/null
+++ b/greendroid/GreenDroid/res/drawable/gd_action_bar_home.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/drawable/gd_action_bar_item.xml b/greendroid/GreenDroid/res/drawable/gd_action_bar_item.xml
new file mode 100644
index 000000000..9331b1e2e
--- /dev/null
+++ b/greendroid/GreenDroid/res/drawable/gd_action_bar_item.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/drawable/gd_quick_action_bar_item.xml b/greendroid/GreenDroid/res/drawable/gd_quick_action_bar_item.xml
new file mode 100644
index 000000000..4b04f6a4b
--- /dev/null
+++ b/greendroid/GreenDroid/res/drawable/gd_quick_action_bar_item.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/drawable/gd_quick_action_grid_selector.xml b/greendroid/GreenDroid/res/drawable/gd_quick_action_grid_selector.xml
new file mode 100644
index 000000000..1478b924b
--- /dev/null
+++ b/greendroid/GreenDroid/res/drawable/gd_quick_action_grid_selector.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/drawable/gd_segment_checkmark.xml b/greendroid/GreenDroid/res/drawable/gd_segment_checkmark.xml
new file mode 100644
index 000000000..41edb1c6a
--- /dev/null
+++ b/greendroid/GreenDroid/res/drawable/gd_segment_checkmark.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/drawable/gd_segment_label.xml b/greendroid/GreenDroid/res/drawable/gd_segment_label.xml
new file mode 100644
index 000000000..221ab1ea1
--- /dev/null
+++ b/greendroid/GreenDroid/res/drawable/gd_segment_label.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/drawable/gd_tab_indicator.xml b/greendroid/GreenDroid/res/drawable/gd_tab_indicator.xml
new file mode 100644
index 000000000..8aca7cefe
--- /dev/null
+++ b/greendroid/GreenDroid/res/drawable/gd_tab_indicator.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_action_bar_dashboard.xml b/greendroid/GreenDroid/res/layout/gd_action_bar_dashboard.xml
new file mode 100644
index 000000000..309c71e9a
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_action_bar_dashboard.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_action_bar_item_base.xml b/greendroid/GreenDroid/res/layout/gd_action_bar_item_base.xml
new file mode 100644
index 000000000..3edec28f4
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_action_bar_item_base.xml
@@ -0,0 +1,24 @@
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_action_bar_item_loader.xml b/greendroid/GreenDroid/res/layout/gd_action_bar_item_loader.xml
new file mode 100644
index 000000000..0a0a2675d
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_action_bar_item_loader.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_action_bar_normal.xml b/greendroid/GreenDroid/res/layout/gd_action_bar_normal.xml
new file mode 100644
index 000000000..3a4b14d49
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_action_bar_normal.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_content_dashboard.xml b/greendroid/GreenDroid/res/layout/gd_content_dashboard.xml
new file mode 100644
index 000000000..4853fc3e6
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_content_dashboard.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_content_normal.xml b/greendroid/GreenDroid/res/layout/gd_content_normal.xml
new file mode 100644
index 000000000..d9b17b191
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_content_normal.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_description_item_view.xml b/greendroid/GreenDroid/res/layout/gd_description_item_view.xml
new file mode 100644
index 000000000..a8e9d9570
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_description_item_view.xml
@@ -0,0 +1,28 @@
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_drawable_item_view.xml b/greendroid/GreenDroid/res/layout/gd_drawable_item_view.xml
new file mode 100644
index 000000000..90660b74d
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_drawable_item_view.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_list_content.xml b/greendroid/GreenDroid/res/layout/gd_list_content.xml
new file mode 100644
index 000000000..84cc247c0
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_list_content.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_long_text_item_view.xml b/greendroid/GreenDroid/res/layout/gd_long_text_item_view.xml
new file mode 100644
index 000000000..7ba60db02
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_long_text_item_view.xml
@@ -0,0 +1,29 @@
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_progress_item_view.xml b/greendroid/GreenDroid/res/layout/gd_progress_item_view.xml
new file mode 100644
index 000000000..497690c65
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_progress_item_view.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_quick_action_bar.xml b/greendroid/GreenDroid/res/layout/gd_quick_action_bar.xml
new file mode 100644
index 000000000..c34e3c05a
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_quick_action_bar.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_quick_action_bar_item.xml b/greendroid/GreenDroid/res/layout/gd_quick_action_bar_item.xml
new file mode 100644
index 000000000..36754244f
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_quick_action_bar_item.xml
@@ -0,0 +1,27 @@
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_quick_action_grid.xml b/greendroid/GreenDroid/res/layout/gd_quick_action_grid.xml
new file mode 100644
index 000000000..dd62ad3af
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_quick_action_grid.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_quick_action_grid_item.xml b/greendroid/GreenDroid/res/layout/gd_quick_action_grid_item.xml
new file mode 100644
index 000000000..dfafab5a7
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_quick_action_grid_item.xml
@@ -0,0 +1,25 @@
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_segment.xml b/greendroid/GreenDroid/res/layout/gd_segment.xml
new file mode 100644
index 000000000..bcba636b3
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_segment.xml
@@ -0,0 +1,31 @@
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_separator_item_view.xml b/greendroid/GreenDroid/res/layout/gd_separator_item_view.xml
new file mode 100644
index 000000000..e7a73d8c4
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_separator_item_view.xml
@@ -0,0 +1,28 @@
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_subtext_item_view.xml b/greendroid/GreenDroid/res/layout/gd_subtext_item_view.xml
new file mode 100644
index 000000000..b2da26952
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_subtext_item_view.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_subtitle_item_view.xml b/greendroid/GreenDroid/res/layout/gd_subtitle_item_view.xml
new file mode 100644
index 000000000..dc4d646d6
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_subtitle_item_view.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_tab_content.xml b/greendroid/GreenDroid/res/layout/gd_tab_content.xml
new file mode 100644
index 000000000..5e36aca5d
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_tab_content.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/layout/gd_tab_indicator.xml b/greendroid/GreenDroid/res/layout/gd_tab_indicator.xml
new file mode 100644
index 000000000..794fbfe62
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_tab_indicator.xml
@@ -0,0 +1,31 @@
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_text_item_view.xml b/greendroid/GreenDroid/res/layout/gd_text_item_view.xml
new file mode 100644
index 000000000..d4fc2723b
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_text_item_view.xml
@@ -0,0 +1,31 @@
+
+
+
+
diff --git a/greendroid/GreenDroid/res/layout/gd_thumbnail_item_view.xml b/greendroid/GreenDroid/res/layout/gd_thumbnail_item_view.xml
new file mode 100755
index 000000000..33e4d785d
--- /dev/null
+++ b/greendroid/GreenDroid/res/layout/gd_thumbnail_item_view.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/values-fr/gd_strings.xml b/greendroid/GreenDroid/res/values-fr/gd_strings.xml
new file mode 100644
index 000000000..80799df23
--- /dev/null
+++ b/greendroid/GreenDroid/res/values-fr/gd_strings.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ Retourner à l\'accueil
+ Rechercher
+ Discuter
+ Composer
+ Exporter
+ Partager
+ Rafraichir
+ Prendre une photo
+ Choisir une photo
+ Localiser
+ Éditer
+ Ajouter
+ Ajouter aux favoris
+ Trier par taille
+ Me localiser
+
+
diff --git a/greendroid/GreenDroid/res/values-land/gd_styles.xml b/greendroid/GreenDroid/res/values-land/gd_styles.xml
new file mode 100644
index 000000000..39ab02541
--- /dev/null
+++ b/greendroid/GreenDroid/res/values-land/gd_styles.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/values/gd_attrs.xml b/greendroid/GreenDroid/res/values/gd_attrs.xml
new file mode 100644
index 000000000..067aaaf31
--- /dev/null
+++ b/greendroid/GreenDroid/res/values/gd_attrs.xml
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/greendroid/GreenDroid/res/values/gd_colors.xml b/greendroid/GreenDroid/res/values/gd_colors.xml
new file mode 100644
index 000000000..0a7d1fd22
--- /dev/null
+++ b/greendroid/GreenDroid/res/values/gd_colors.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ #a8c24e
+ #7fff
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/values/gd_dimens.xml b/greendroid/GreenDroid/res/values/gd_dimens.xml
new file mode 100644
index 000000000..8514b4081
--- /dev/null
+++ b/greendroid/GreenDroid/res/values/gd_dimens.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+ 25dp
+ 16dp
+
+ 64dp
+ 32dp
+ 6dp
+
+ 50dp
+ 50dp
+ 6dp
+
+ 20dp
+ 20dp
+ 6dp
+
+ 45dp
+
+ 5dp
+
+
diff --git a/greendroid/GreenDroid/res/values/gd_ids.xml b/greendroid/GreenDroid/res/values/gd_ids.xml
new file mode 100644
index 000000000..a277e08fb
--- /dev/null
+++ b/greendroid/GreenDroid/res/values/gd_ids.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/values/gd_strings.xml b/greendroid/GreenDroid/res/values/gd_strings.xml
new file mode 100644
index 000000000..4e166b89d
--- /dev/null
+++ b/greendroid/GreenDroid/res/values/gd_strings.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+ Go home
+ Search
+ Talk
+ Compose
+ Export
+ Share
+ Refresh
+ Take photo
+ Pick photo
+ Locate
+ Edit
+ Add
+ Star
+ Sort by size
+ Locate myself
+
+
diff --git a/greendroid/GreenDroid/res/values/gd_styles.xml b/greendroid/GreenDroid/res/values/gd_styles.xml
new file mode 100644
index 000000000..b33688081
--- /dev/null
+++ b/greendroid/GreenDroid/res/values/gd_styles.xml
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/res/values/gd_themes.xml b/greendroid/GreenDroid/res/values/gd_themes.xml
new file mode 100644
index 000000000..11b7e814b
--- /dev/null
+++ b/greendroid/GreenDroid/res/values/gd_themes.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/greendroid/GreenDroid/src/greendroid/app/ActionBarActivity.java b/greendroid/GreenDroid/src/greendroid/app/ActionBarActivity.java
new file mode 100644
index 000000000..218d8b161
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/app/ActionBarActivity.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.app;
+
+import greendroid.widget.ActionBar;
+import greendroid.widget.ActionBarItem;
+import android.app.Activity;
+import android.app.Application;
+import android.widget.FrameLayout;
+
+/**
+ * Defines all methods related to Activities embedding an {@link ActionBar}
+ *
+ * @author Cyril Mottier
+ */
+public interface ActionBarActivity {
+
+ /**
+ * The key to use to set the title of the launched ActionBarActivity
+ */
+ static final String GD_ACTION_BAR_TITLE = "greendroid.app.ActionBarActivity.GD_ACTION_BAR_TITLE";
+
+ /**
+ * Clients may use this method to listen to {@link ActionBarItem}s clicks.
+ *
+ * @param item The {@link ActionBarItem} that has been clicked
+ * @param position The position of the clicked item. This number is equal or
+ * greater to zero. 0 is the leftmost item.
+ * @return true if the method has handled the click on the
+ * {@link ActionBarItem} at position position. Otherwise it
+ * returns false.
+ */
+ boolean onHandleActionBarItemClick(ActionBarItem item, int position);
+
+ /**
+ * Returns the content view. Please note the content view is not the entire
+ * view but a {@link FrameLayout} that contains everything but the {@link ActionBar}.
+ *
+ * @return The content view
+ */
+ FrameLayout getContentView();
+
+ /**
+ * Returns the {@link ActionBar}. Listening to {@link ActionBar} events
+ * should be done via the
+ * {@link ActionBarActivity#onHandleActionBarItemClick(ActionBarItem, int)}
+ * method. Most of the time, this method don't need to be used directly.
+ *
+ * @see {@link ActionBarActivity#onHandleActionBarItemClick(ActionBarItem, int)}
+ * @see {@link ActionBarActivity#addActionBarItem(ActionBarItem)}
+ * @see {@link ActionBarActivity#addActionBarItem(greendroid.widget.ActionBarItem.Type)}
+ * @return The {@link ActionBar} currently displayed on screen
+ */
+ ActionBar getActionBar();
+
+ /**
+ * A simple utility method that casts the {@link Application} returned by
+ * {@link #getApplication()} into a {@link GDApplication}
+ *
+ * @return The current {@link GDApplication}
+ */
+ GDApplication getGDApplication();
+
+ /**
+ * Add a new item to the {@link ActionBar}.
+ *
+ * @param item The item to add to the {@link ActionBar}
+ */
+ void addActionBarItem(ActionBarItem item);
+
+ /**
+ * Adds a new item of type type to the {@link ActionBar}.
+ *
+ * @param actionBarItemType The item to add to the {@link ActionBar}
+ */
+ void addActionBarItem(ActionBarItem.Type actionBarItemType);
+
+ /**
+ * Returns the identifier of the layout that needs to be created for this
+ * {@link ActionBarActivity}
+ *
+ * @return The layout identifier of the layout to create
+ */
+ int createLayout();
+
+ /**
+ * Called at the beginning of the {@link Activity#onContentChanged()}
+ * method. This may be used to initialize all references on elements.
+ */
+ void onPreContentChanged();
+
+ /**
+ * Called at the end of the {@link Activity#onContentChanged()} method. This
+ * may be use to initialize the content of the layout (titles, etc.)
+ */
+ void onPostContentChanged();
+}
diff --git a/greendroid/GreenDroid/src/greendroid/app/GDActivity.java b/greendroid/GreenDroid/src/greendroid/app/GDActivity.java
new file mode 100644
index 000000000..fba8560c6
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/app/GDActivity.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.app;
+
+import com.cyrilmottier.android.greendroid.R;
+
+import greendroid.util.Config;
+import greendroid.widget.ActionBar;
+import greendroid.widget.ActionBarHost;
+import greendroid.widget.ActionBarItem;
+import greendroid.widget.ActionBar.OnActionBarListener;
+import greendroid.widget.ActionBar.Type;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+
+/**
+ *
+ * An {@link GDActivity} is a regular Activity that always hosts an
+ * {@link ActionBar}. It is extremely simple to use as you have nothing
+ * particular to do. Indeed, the ActionBar is automatically added to your own
+ * layout when using the {@link #getContentView()} method. You can also use one
+ * of the setActionBarContentView utility methods. As a result, a basic
+ * {@link GDActivity} will often be initialized using the following snippet of
+ * code:
+ *
+ * An ActionBar is a widget that may contains actions items and a title. You can
+ * also set the title putting an extra string with the key
+ * {@link GD_ACTION_BAR_TITLE} in your Intent:
+ *
+ * Note: An {@link GDActivity} automatically handle the type of the ActionBar
+ * (Dashboard or Normal) depending on the value returned by the
+ * getHomeActivityClass of your {@link GDApplication}. However you can force the
+ * type of the action bar in your constructor.
+ *
+ * All Activities that inherits from an {@link GDActivity} are notified when an
+ * action button is tapped in the onHandleActionBarItemClick(ActionBarItem, int)
+ * method. By default this method does nothing but return false.
+ *
+ *
+ * @see {@link GDApplication#getHomeActivityClass()}
+ * @see {@link GDActivity#GD_ACTION_BAR_TITLE}
+ * @see {@link GDActivity#setActionBarContentView(int)}
+ * @see {@link GDActivity#setActionBarContentView(View)}
+ * @see {@link GDActivity#setActionBarContentView(View, LayoutParams)}
+ * @author Cyril Mottier
+ */
+public class GDActivity extends Activity implements ActionBarActivity {
+
+ private static final String LOG_TAG = GDActivity.class.getSimpleName();
+
+ private boolean mDefaultConstructorUsed = false;
+
+ private Type mActionBarType;
+ private ActionBarHost mActionBarHost;
+
+ public GDActivity() {
+ this(Type.Normal);
+ mDefaultConstructorUsed = true;
+ }
+
+ public GDActivity(ActionBar.Type actionBarType) {
+ super();
+ mActionBarType = actionBarType;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ ensureLayout();
+ super.onRestoreInstanceState(savedInstanceState);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (mDefaultConstructorUsed) {
+ // HACK cyril: This should have been done is the default
+ // constructor. Unfortunately, the getApplication() method returns
+ // null there. Hence, this has to be done here.
+ if (getClass().equals(getGDApplication().getHomeActivityClass())) {
+ mActionBarType = Type.Dashboard;
+ }
+ }
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ ensureLayout();
+ }
+
+ public ActionBar.Type getActionBarType() {
+ return mActionBarType;
+ }
+
+ public int createLayout() {
+ switch (mActionBarType) {
+ case Dashboard:
+ return R.layout.gd_content_dashboard;
+ case Normal:
+ default:
+ return R.layout.gd_content_normal;
+ }
+ }
+
+ protected void ensureLayout() {
+ if (!verifyLayout()) {
+ setContentView(createLayout());
+ }
+ }
+
+ protected boolean verifyLayout() {
+ return mActionBarHost != null;
+ }
+
+ public GDApplication getGDApplication() {
+ return (GDApplication) getApplication();
+ }
+
+ @Override
+ public void onContentChanged() {
+ super.onContentChanged();
+
+ onPreContentChanged();
+ onPostContentChanged();
+ }
+
+ public void onPreContentChanged() {
+ mActionBarHost = (ActionBarHost) findViewById(R.id.gd_action_bar_host);
+ if (mActionBarHost == null) {
+ throw new RuntimeException(
+ "Your content must have an ActionBarHost whose id attribute is R.id.gd_action_bar_host");
+ }
+ mActionBarHost.getActionBar().setOnActionBarListener(mActionBarListener);
+ }
+
+ public void onPostContentChanged() {
+
+ boolean titleSet = false;
+
+ final Intent intent = getIntent();
+ if (intent != null) {
+ String title = intent.getStringExtra(ActionBarActivity.GD_ACTION_BAR_TITLE);
+ if (title != null) {
+ titleSet = true;
+ setTitle(title);
+ }
+ }
+
+ if (!titleSet) {
+ // No title has been set via the Intent. Let's look in the
+ // ActivityInfo
+ try {
+ final ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), 0);
+ if (activityInfo.labelRes != 0) {
+ setTitle(activityInfo.labelRes);
+ }
+ } catch (NameNotFoundException e) {
+ // Do nothing
+ }
+ }
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ getActionBar().setTitle(title);
+ }
+
+ @Override
+ public void setTitle(int titleId) {
+ setTitle(getString(titleId));
+ }
+
+ public ActionBar getActionBar() {
+ ensureLayout();
+ return mActionBarHost.getActionBar();
+ }
+
+ public void addActionBarItem(ActionBarItem item) {
+ getActionBar().addItem(item);
+ }
+
+ public void addActionBarItem(ActionBarItem.Type actionBarItemType) {
+ getActionBar().addItem(actionBarItemType);
+ }
+
+ public FrameLayout getContentView() {
+ ensureLayout();
+ return mActionBarHost.getContentView();
+ }
+
+ public void setActionBarContentView(int resID) {
+ LayoutInflater.from(this).inflate(resID, getContentView());
+ }
+
+ public void setActionBarContentView(View view, LayoutParams params) {
+ getContentView().addView(view, params);
+ }
+
+ public void setActionBarContentView(View view) {
+ getContentView().addView(view);
+ }
+
+ public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
+ return false;
+ }
+
+ private OnActionBarListener mActionBarListener = new OnActionBarListener() {
+ public void onActionBarItemClicked(int position) {
+ if (position == OnActionBarListener.HOME_ITEM) {
+
+ final GDApplication app = getGDApplication();
+ switch (mActionBarType) {
+ case Normal:
+ final Class> klass = app.getHomeActivityClass();
+ if (klass != null && !klass.equals(GDActivity.this.getClass())) {
+ if (Config.GD_INFO_LOGS_ENABLED) {
+ Log.i(LOG_TAG, "Going back to the home activity");
+ }
+ Intent homeIntent = new Intent(GDActivity.this, klass);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(homeIntent);
+ }
+ break;
+ case Dashboard:
+ final Intent appIntent = app.getMainApplicationIntent();
+ if (appIntent != null) {
+ if (Config.GD_INFO_LOGS_ENABLED) {
+ Log.i(LOG_TAG, "Launching the main application Intent");
+ }
+ startActivity(appIntent);
+ }
+ break;
+ }
+
+ } else {
+ if (!onHandleActionBarItemClick(getActionBar().getItem(position), position)) {
+ if (Config.GD_WARNING_LOGS_ENABLED) {
+ Log.w(LOG_TAG, "Click on item at position " + position + " dropped down to the floor");
+ }
+ }
+ }
+ }
+ };
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/app/GDApplication.java b/greendroid/GreenDroid/src/greendroid/app/GDApplication.java
new file mode 100644
index 000000000..96d9b8b40
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/app/GDApplication.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.app;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.Intent;
+
+/**
+ * Defines various methods that should be overridden in order to style your
+ * application.
+ *
+ * @author Cyril Mottier
+ */
+public class GDApplication extends Application {
+
+ /**
+ * Returns the class of the home {@link Activity}. The home {@link Activity}
+ * is the main entrance point of your application. This is usually where the
+ * dashboard/general menu is displayed.
+ *
+ * @return The Class of the home {@link Activity}
+ */
+ public Class> getHomeActivityClass() {
+ return null;
+ }
+
+ /**
+ * Each application may have an "application intent" which will be used when
+ * the user clicked on the application button.
+ *
+ * @return The main application {@link Intent} (may be null if you don't
+ * want to use the main application {@link Intent} feature)
+ */
+ public Intent getMainApplicationIntent() {
+ return null;
+ }
+}
diff --git a/greendroid/GreenDroid/src/greendroid/app/GDListActivity.java b/greendroid/GreenDroid/src/greendroid/app/GDListActivity.java
new file mode 100644
index 000000000..59de729c1
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/app/GDListActivity.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.app;
+
+import greendroid.util.Config;
+import android.app.ListActivity;
+import android.os.Handler;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+import com.cyrilmottier.android.greendroid.R;
+
+
+/**
+ * An equivalent to {@link ListActivity} that manages a ListView.
+ *
+ * @see {@link ListActivity}
+ * @author Cyril Mottier
+ */
+public class GDListActivity extends GDActivity {
+
+ private static final String LOG_TAG = GDListActivity.class.getSimpleName();
+
+ private ListAdapter mAdapter;
+ private ListView mList;
+ private View mEmptyView;
+
+ private Handler mHandler = new Handler();
+ private boolean mFinishedStart = false;
+
+ private Runnable mRequestFocus = new Runnable() {
+ public void run() {
+ mList.focusableViewAvailable(mList);
+ }
+ };
+
+ /**
+ * This method will be called when an item in the list is selected.
+ * Subclasses should override. Subclasses can call
+ * getListView().getItemAtPosition(position) if they need to access the data
+ * associated with the selected item.
+ *
+ * @param l The ListView where the click happened
+ * @param v The view that was clicked within the ListView
+ * @param position The position of the view in the list
+ * @param id The row id of the item that was clicked
+ */
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ }
+
+ /**
+ * Provide the cursor for the list view.
+ */
+ public void setListAdapter(ListAdapter adapter) {
+ synchronized (this) {
+ ensureLayout();
+ mAdapter = adapter;
+ mList.setAdapter(adapter);
+ }
+ }
+
+ /**
+ * Set the currently selected list item to the specified position with the
+ * adapter's data
+ *
+ * @param position
+ */
+ public void setSelection(int position) {
+ mList.setSelection(position);
+ }
+
+ /**
+ * Get the position of the currently selected list item.
+ */
+ public int getSelectedItemPosition() {
+ return mList.getSelectedItemPosition();
+ }
+
+ /**
+ * Get the cursor row ID of the currently selected list item.
+ */
+ public long getSelectedItemId() {
+ return mList.getSelectedItemId();
+ }
+
+ /**
+ * Get the activity's list view widget.
+ */
+ public ListView getListView() {
+ ensureLayout();
+ return mList;
+ }
+
+ /**
+ * Get the ListAdapter associated with this activity's ListView.
+ */
+ public ListAdapter getListAdapter() {
+ return mAdapter;
+ }
+
+ @Override
+ public int createLayout() {
+ if (Config.GD_INFO_LOGS_ENABLED) {
+ Log.d(LOG_TAG, "No layout specified : creating the default layout");
+ }
+ return R.layout.gd_list_content;
+ }
+
+ @Override
+ protected boolean verifyLayout() {
+ return super.verifyLayout() && mList != null;
+ }
+
+ @Override
+ public void onPreContentChanged() {
+ super.onPreContentChanged();
+
+ mEmptyView = findViewById(android.R.id.empty);
+ mList = (ListView) findViewById(android.R.id.list);
+ if (mList == null) {
+ throw new RuntimeException("Your content must have a ListView whose id attribute is "
+ + "'android.R.id.list'");
+ }
+ }
+
+ @Override
+ public void onPostContentChanged() {
+ super.onPostContentChanged();
+
+ if (mEmptyView != null) {
+ mList.setEmptyView(mEmptyView);
+ }
+ mList.setOnItemClickListener(mOnClickListener);
+ if (mFinishedStart) {
+ setListAdapter(mAdapter);
+ }
+ mHandler.post(mRequestFocus);
+ mFinishedStart = true;
+ }
+
+ private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
+ public void onItemClick(AdapterView> parent, View v, int position, long id) {
+ onListItemClick((ListView) parent, v, position, id);
+ }
+ };
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/app/GDTabActivity.java b/greendroid/GreenDroid/src/greendroid/app/GDTabActivity.java
new file mode 100644
index 000000000..87723aaab
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/app/GDTabActivity.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.app;
+
+import greendroid.util.Config;
+import greendroid.widget.ActionBar;
+import greendroid.widget.ActionBar.OnActionBarListener;
+import greendroid.widget.ActionBarHost;
+import greendroid.widget.ActionBarItem;
+import android.app.TabActivity;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.TabHost;
+import android.widget.TextView;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * An equivalent to a TabActivity that manages fancy tabs and an ActionBar
+ *
+ * @author Cyril Mottier
+ */
+public class GDTabActivity extends TabActivity implements ActionBarActivity {
+
+ private static final String LOG_TAG = GDTabActivity.class.getSimpleName();
+
+ private ActionBarHost mActionBarHost;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(createLayout());
+ }
+
+ public int createLayout() {
+ return R.layout.gd_tab_content;
+ }
+
+ public GDApplication getGDApplication() {
+ return (GDApplication) getApplication();
+ }
+
+ @Override
+ public void onContentChanged() {
+ super.onContentChanged();
+
+ onPreContentChanged();
+ onPostContentChanged();
+ }
+
+ public void onPreContentChanged() {
+ mActionBarHost = (ActionBarHost) findViewById(R.id.gd_action_bar_host);
+ if (mActionBarHost == null) {
+ throw new RuntimeException(
+ "Your content must have an ActionBarHost whose id attribute is R.id.gd_action_bar_host");
+ }
+ mActionBarHost.getActionBar().setOnActionBarListener(mActionBarListener);
+ }
+
+ public void onPostContentChanged() {
+
+ boolean titleSet = false;
+
+ final Intent intent = getIntent();
+ if (intent != null) {
+ String title = intent.getStringExtra(ActionBarActivity.GD_ACTION_BAR_TITLE);
+ if (title != null) {
+ titleSet = true;
+ setTitle(title);
+ }
+ }
+
+ if (!titleSet) {
+ // No title has been set via the Intent. Let's look in the
+ // ActivityInfo
+ try {
+ final ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), 0);
+ if (activityInfo.labelRes != 0) {
+ setTitle(activityInfo.labelRes);
+ }
+ } catch (NameNotFoundException e) {
+ // Do nothing
+ }
+ }
+ }
+
+ // @Override
+ // protected void onTitleChanged(CharSequence title, int color) {
+ // setTitle(title);
+ // }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ getActionBar().setTitle(title);
+ }
+
+ @Override
+ public void setTitle(int titleId) {
+ setTitle(getString(titleId));
+ }
+
+ public ActionBar getActionBar() {
+ return mActionBarHost.getActionBar();
+ }
+
+ public void addActionBarItem(ActionBarItem item) {
+ getActionBar().addItem(item);
+ }
+
+ public void addActionBarItem(ActionBarItem.Type actionBarItemType) {
+ getActionBar().addItem(actionBarItemType);
+ }
+
+ public FrameLayout getContentView() {
+ return mActionBarHost.getContentView();
+ }
+
+ public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
+ return false;
+ }
+
+ private OnActionBarListener mActionBarListener = new OnActionBarListener() {
+ public void onActionBarItemClicked(int position) {
+ if (position == OnActionBarListener.HOME_ITEM) {
+
+ final Class> klass = getGDApplication().getHomeActivityClass();
+ if (klass != null && !klass.equals(getClass())) {
+ if (Config.GD_INFO_LOGS_ENABLED) {
+ Log.i(LOG_TAG, "Going back to the home activity");
+ }
+ Intent homeIntent = new Intent(GDTabActivity.this, klass);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(homeIntent);
+ }
+
+ } else {
+ if (!onHandleActionBarItemClick(getActionBar().getItem(position), position)) {
+ if (Config.GD_WARNING_LOGS_ENABLED) {
+ Log.w(LOG_TAG, "Click on item at position " + position + " dropped down to the floor");
+ }
+ }
+ }
+ }
+ };
+
+ /*
+ * GDTabActivity methods
+ */
+
+ public void addTab(String tag, int labelId, Intent intent) {
+ addTab(tag, getString(labelId), intent);
+ }
+
+ public void addTab(String tag, CharSequence label, Intent intent) {
+ final TabHost host = getTabHost();
+
+ View indicator = createTabIndicator(label);
+ if (indicator == null) {
+ final TextView textIndicator = (TextView) getLayoutInflater().inflate(R.layout.gd_tab_indicator,
+ getTabWidget(), false);
+ textIndicator.setText(label);
+ indicator = textIndicator;
+ }
+
+ host.addTab(host.newTabSpec(tag).setIndicator(indicator).setContent(intent));
+ }
+
+ protected View createTabIndicator(CharSequence label) {
+ return null;
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/util/Config.java b/greendroid/GreenDroid/src/greendroid/util/Config.java
new file mode 100644
index 000000000..a1169e6ef
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/util/Config.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.util;
+
+@SuppressWarnings("all")
+public class Config {
+
+ private Config() {
+ }
+
+ private static final int GD_LOG_LEVEL_INFO = 3;
+ private static final int GD_LOG_LEVEL_WARNING = 2;
+ private static final int GD_LOG_LEVEL_ERROR = 1;
+ private static final int GD_LOG_LEVEL_NONE = 0;
+
+ /**
+ * Set this flag to {@link Config#GD_LOG_LEVEL_NONE} when releasing your
+ * application in order to remove all logs generated by GreenDroid.
+ */
+ private static final int GD_LOG_LEVEL = GD_LOG_LEVEL_NONE;
+
+ public static final boolean GD_INFO_LOGS_ENABLED = (GD_LOG_LEVEL == GD_LOG_LEVEL_INFO);
+ public static final boolean GD_WARNING_LOGS_ENABLED = GD_INFO_LOGS_ENABLED
+ || (GD_LOG_LEVEL == GD_LOG_LEVEL_WARNING);
+ public static final boolean GD_ERROR_LOGS_ENABLED = (GD_LOG_LEVEL == GD_LOG_LEVEL_ERROR) || GD_WARNING_LOGS_ENABLED;
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/ActionBar.java b/greendroid/GreenDroid/src/greendroid/widget/ActionBar.java
new file mode 100644
index 000000000..ad643292f
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/ActionBar.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import greendroid.util.Config;
+
+import java.util.LinkedList;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.cyrilmottier.android.greendroid.R;
+
+public class ActionBar extends LinearLayout {
+
+ private static final String LOG_TAG = ActionBar.class.getSimpleName();
+
+ private static final int MAX_ITEMS_COUNT = 3;
+
+ public enum Type {
+ Normal, Dashboard
+ }
+
+ public interface OnActionBarListener {
+
+ static final int HOME_ITEM = -1;
+
+ /**
+ * Clients may listen to this method in order to be notified the user
+ * has clicked on an item.
+ *
+ * @param position The position of the item in the action bar. -1 means
+ * the user pressed the "Home" button. 0 means the user
+ * clicked the first action bar item (the leftmost item) and
+ * so on.
+ */
+ void onActionBarItemClicked(int position);
+ }
+
+ private TextView mTitleView;
+ private ImageButton mHomeButton;
+
+ private boolean mMerging = false;
+
+ private String mTitle;
+ private ActionBar.Type mType;
+ private OnActionBarListener mOnActionBarListener;
+ private LinkedList mItems;
+
+ private Drawable mDividerDrawable;
+ private Drawable mHomeDrawable;
+ private int mDividerWidth;
+
+ public ActionBar(Context context) {
+ this(context, null);
+ }
+
+ public ActionBar(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.gdActionBarStyle);
+ }
+
+ public ActionBar(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs);
+
+ initActionBar();
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar, defStyle, 0);
+
+ mTitle = a.getString(R.styleable.ActionBar_title);
+
+ mDividerDrawable = a.getDrawable(R.styleable.ActionBar_dividerDrawable);
+ mDividerWidth = a.getDimensionPixelSize(R.styleable.ActionBar_dividerWidth, -1);
+ mHomeDrawable = a.getDrawable(R.styleable.ActionBar_homeDrawable);
+
+ int layoutID;
+ int type = a.getInteger(R.styleable.ActionBar_type, -1);
+ switch (type) {
+ case 1:
+ mType = Type.Dashboard;
+ layoutID = R.layout.gd_action_bar_dashboard;
+ break;
+ case 0:
+ default:
+ mType = Type.Normal;
+ layoutID = R.layout.gd_action_bar_normal;
+ break;
+ }
+
+ // HACK cyril: Without this, the onFinishInflate is called twice !?!
+ // This issue is due to a bug when Android inflates a layout with a
+ // parent - which is compulsory with a tag. I've reported this
+ // bug to Romain Guy who fixed it (patch will probably be available in
+ // the Gingerbread release).
+ mMerging = true;
+ LayoutInflater.from(context).inflate(layoutID, this);
+ mMerging = false;
+
+ a.recycle();
+ }
+
+ private void initActionBar() {
+ mItems = new LinkedList();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ if (!mMerging) {
+
+ if (Config.GD_INFO_LOGS_ENABLED) {
+ Log.i(LOG_TAG, "onFinishInflate() - not merging");
+ }
+
+ // Work done for both Dashboard and Normal type
+ mHomeButton = (ImageButton) findViewById(R.id.gd_action_bar_home_item);
+ mHomeButton.setOnClickListener(mClickHandler);
+
+ switch (mType) {
+ case Normal:
+ mHomeButton.setImageDrawable(mHomeDrawable);
+ mHomeButton.setContentDescription(getContext().getString(R.string.gd_go_home));
+ mTitleView = (TextView) findViewById(R.id.gd_action_bar_title);
+ if (mTitle != null) {
+ setTitle(mTitle);
+ }
+
+ default:
+ //Do nothing
+ break;
+ }
+ }
+
+ }
+
+ public void setOnActionBarListener(OnActionBarListener listener) {
+ mOnActionBarListener = listener;
+ }
+
+ public void setTitle(CharSequence title) {
+ if (mTitleView != null) {
+ mTitleView.setText(title);
+ }
+ }
+
+ public void addItem(ActionBarItem.Type actionBarItemType) {
+ addItem(ActionBarItem.createWithType(this, actionBarItemType));
+ }
+
+ public void addItem(ActionBarItem item) {
+
+ if (mItems.size() >= MAX_ITEMS_COUNT) {
+ /*
+ * An ActionBar must contain as few items as possible. So let's keep
+ * a limit :)
+ */
+ return;
+ }
+
+ if (mDividerDrawable != null) {
+ ImageView divider = new ImageView(getContext());
+ int dividerWidth = (mDividerWidth > 0) ? mDividerWidth : mDividerDrawable.getIntrinsicWidth();
+ final LinearLayout.LayoutParams lp = new LayoutParams(dividerWidth, LayoutParams.FILL_PARENT);
+ divider.setLayoutParams(lp);
+ divider.setBackgroundDrawable(mDividerDrawable);
+ addView(divider);
+ }
+
+ final View itemView = item.getItemView();
+ itemView.findViewById(R.id.gd_action_bar_item).setOnClickListener(mClickHandler);
+
+ final int size = (int) getResources().getDimension(R.dimen.gd_action_bar_height);
+ addView(itemView, new LayoutParams(size, LayoutParams.FILL_PARENT));
+
+ mItems.add(item);
+ }
+
+ public ActionBarItem getItem(int position) {
+ if (position < 0 || position >= mItems.size()) {
+ return null;
+ }
+ return mItems.get(position);
+ }
+
+ public void removeItem(int position) {
+
+ if (position < 0 || position >= mItems.size()) {
+ return;
+ }
+
+ final int viewIndex = indexOfChild(mItems.get(position).getItemView());
+ final int increment = (mDividerDrawable != null) ? 1 : 0;
+ removeViews(viewIndex - increment, 1 + increment);
+ mItems.remove(position);
+ }
+
+ /**
+ * @hide TODO cyril: To be tested.
+ */
+ public void setType(Type type) {
+ if (type != mType) {
+
+ removeAllViews();
+
+ int layoutId = 0;
+ switch (type) {
+ case Dashboard:
+ layoutId = R.layout.gd_action_bar_dashboard;
+ break;
+ case Normal:
+ layoutId = R.layout.gd_action_bar_normal;
+ break;
+ }
+
+ mMerging = true;
+ LayoutInflater.from(getContext()).inflate(layoutId, this);
+ mMerging = false;
+
+ // Reset all items
+ LinkedList itemsCopy = new LinkedList(mItems);
+ mItems.clear();
+ for (ActionBarItem item : itemsCopy) {
+ addItem(item);
+ }
+ }
+ }
+
+ public ActionBarItem newActionBarItem(Class extends ActionBarItem> klass) {
+ try {
+ ActionBarItem item = klass.newInstance();
+ item.setActionBar(this);
+ return item;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("The given klass must have a default constructor");
+ }
+ }
+
+ private OnClickListener mClickHandler = new OnClickListener() {
+
+ public void onClick(View v) {
+ if (mOnActionBarListener != null) {
+
+ if (v == mHomeButton) {
+ mOnActionBarListener.onActionBarItemClicked(OnActionBarListener.HOME_ITEM);
+ return;
+ }
+
+ final int itemCount = mItems.size();
+ for (int i = 0; i < itemCount; i++) {
+ final ActionBarItem item = mItems.get(i);
+ final View itemButton = item.getItemView().findViewById(R.id.gd_action_bar_item);
+ if (v == itemButton) {
+ item.onItemClicked();
+ mOnActionBarListener.onActionBarItemClicked(i);
+ break;
+ }
+ }
+ }
+ }
+
+ };
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/ActionBarHost.java b/greendroid/GreenDroid/src/greendroid/widget/ActionBarHost.java
new file mode 100644
index 000000000..14b533fbb
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/ActionBarHost.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import com.cyrilmottier.android.greendroid.R;
+
+public class ActionBarHost extends LinearLayout {
+
+ private ActionBar mActionBar;
+ private FrameLayout mContentView;
+
+ public ActionBarHost(Context context) {
+ this(context, null);
+ }
+
+ public ActionBarHost(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOrientation(LinearLayout.VERTICAL);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mActionBar = (ActionBar) findViewById(R.id.gd_action_bar);
+ if (mActionBar == null || !(mActionBar instanceof ActionBar)) {
+ throw new IllegalArgumentException("No ActionBar with the id R.id.gd_action_bar found in the layout.");
+ }
+
+ mContentView = (FrameLayout) findViewById(R.id.gd_action_bar_content_view);
+ if (mContentView == null || !(mContentView instanceof FrameLayout)) {
+ throw new IllegalArgumentException("No content view with the id R.id.gd_content_view found in the layout.");
+ }
+ }
+
+ public ActionBar getActionBar() {
+ return mActionBar;
+ }
+
+ public FrameLayout getContentView() {
+ return mContentView;
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/ActionBarItem.java b/greendroid/GreenDroid/src/greendroid/widget/ActionBarItem.java
new file mode 100644
index 000000000..4d5e9ff1b
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/ActionBarItem.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.view.View;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * Base class representing an {@link ActionBarItem} used in {@link ActionBar}s.
+ * The base implementation exposes a single Drawable as well as a
+ * content description.
+ *
+ * @author Cyril Mottier
+ */
+public abstract class ActionBarItem {
+
+ public enum Type {
+ GoHome, // A house
+ Search, // A magnifying glass
+ Talk, // A speech bubble
+ Compose, // A sheet of paper with a pen
+ Export, // A dot with an arrow
+ Share, // A dot with two arrows
+ Refresh, // Two curved arrows
+ TakePhoto, // A camera
+ // PickPhoto, // Two pictures with an arrow
+ Locate, // The traditional GMaps pin
+ Edit, // A pencil
+ Add, // A plus sign
+ Star, // A star
+ SortBySize, // Some bars
+ LocateMyself
+ // A surrounded dot
+ }
+
+ // Why, the hell, are those value protected to View ??? The simplest way to
+ // get those sets here is to copy them. Another way would be to subclass
+ // View just to access those protected fields ... yuck !!!
+ private static final int[] ENABLE_STATE_SET = {
+ android.R.attr.state_enabled
+ };
+
+ private static final int[] ENABLED_PRESSED_STATE_SET = {
+ android.R.attr.state_enabled, android.R.attr.state_pressed
+ };
+
+ private static final int[] ENABLED_FOCUSED_STATE_SET = {
+ android.R.attr.state_enabled, android.R.attr.state_focused
+ };
+
+ protected Drawable mDrawable;
+ protected int mDrawableId;
+
+ protected CharSequence mContentDescription;
+ protected View mItemView;
+
+ protected Context mContext;
+ protected ActionBar mActionBar;
+
+ void setActionBar(ActionBar actionBar) {
+ mContext = actionBar.getContext();
+ mActionBar = actionBar;
+ }
+
+ public Drawable getDrawable() {
+ return mDrawable;
+ }
+
+ public ActionBarItem setDrawable(int drawableId) {
+ return setDrawable(mContext.getResources().getDrawable(drawableId));
+ }
+
+ public ActionBarItem setDrawable(Drawable drawable) {
+ if (drawable != mDrawable) {
+ mDrawable = drawable;
+ if (mItemView != null) {
+ onDrawableChanged();
+ }
+ }
+ return this;
+ }
+
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ public ActionBarItem setContentDescription(int contentDescriptionId) {
+ return setContentDescription(mContext.getString(contentDescriptionId));
+ }
+
+ public ActionBarItem setContentDescription(CharSequence contentDescription) {
+ if (contentDescription != mContentDescription) {
+ mContentDescription = contentDescription;
+ if (mItemView != null) {
+ onContentDescriptionChanged();
+ }
+ }
+ return this;
+ }
+
+ public View getItemView() {
+ if (mItemView == null) {
+ mItemView = createItemView();
+ prepareItemView();
+ }
+ return mItemView;
+ }
+
+ protected abstract View createItemView();
+
+ protected void prepareItemView() {
+ }
+
+ protected void onDrawableChanged() {
+ }
+
+ protected void onContentDescriptionChanged() {
+ }
+
+ protected void onItemClicked() {
+ }
+
+ static ActionBarItem createWithType(ActionBar actionBar, ActionBarItem.Type type) {
+
+ int normalDrawableId;
+ int altDrawableId;
+ int descriptionId;
+
+ switch (type) {
+ case GoHome:
+ normalDrawableId = R.drawable.gd_action_bar_home_normal;
+ altDrawableId = R.drawable.gd_action_bar_home_alt;
+ descriptionId = R.string.gd_go_home;
+ break;
+
+ case Search:
+ normalDrawableId = R.drawable.gd_action_bar_search_normal;
+ altDrawableId = R.drawable.gd_action_bar_search_alt;
+ descriptionId = R.string.gd_search;
+ break;
+
+ case Talk:
+ normalDrawableId = R.drawable.gd_action_bar_talk_normal;
+ altDrawableId = R.drawable.gd_action_bar_talk_alt;
+ descriptionId = R.string.gd_talk;
+ break;
+
+ case Compose:
+ normalDrawableId = R.drawable.gd_action_bar_compose_normal;
+ altDrawableId = R.drawable.gd_action_bar_compose_alt;
+ descriptionId = R.string.gd_compose;
+ break;
+
+ case Export:
+ normalDrawableId = R.drawable.gd_action_bar_export_normal;
+ altDrawableId = R.drawable.gd_action_bar_export_alt;
+ descriptionId = R.string.gd_export;
+ break;
+
+ case Share:
+ normalDrawableId = R.drawable.gd_action_bar_share_normal;
+ altDrawableId = R.drawable.gd_action_bar_share_alt;
+ descriptionId = R.string.gd_share;
+ break;
+
+ case Refresh:
+ return actionBar
+ .newActionBarItem(LoaderActionBarItem.class)
+ .setDrawable(
+ createStateListDrawable(actionBar.getContext(),
+ R.drawable.gd_action_bar_refresh_normal, R.drawable.gd_action_bar_refresh_alt))
+ .setContentDescription(R.string.gd_refresh);
+
+ case TakePhoto:
+ normalDrawableId = R.drawable.gd_action_bar_take_photo_normal;
+ altDrawableId = R.drawable.gd_action_bar_take_photo_alt;
+ descriptionId = R.string.gd_take_photo;
+ break;
+ //
+ // case PickPhoto:
+ // normalDrawableId = R.drawable.gd_action_bar_pick_photo_normal;
+ // altDrawableId = R.drawable.gd_action_bar_pick_photo_alt;
+ // descriptionId = R.string.gd_pick_photo;
+ // break;
+
+ case Locate:
+ normalDrawableId = R.drawable.gd_action_bar_locate_normal;
+ altDrawableId = R.drawable.gd_action_bar_locate_alt;
+ descriptionId = R.string.gd_locate;
+ break;
+
+ case Edit:
+ normalDrawableId = R.drawable.gd_action_bar_edit_normal;
+ altDrawableId = R.drawable.gd_action_bar_edit_alt;
+ descriptionId = R.string.gd_edit;
+ break;
+
+ case Add:
+ normalDrawableId = R.drawable.gd_action_bar_add_normal;
+ altDrawableId = R.drawable.gd_action_bar_add_alt;
+ descriptionId = R.string.gd_add;
+ break;
+
+ case Star:
+ normalDrawableId = R.drawable.gd_action_bar_star_normal;
+ altDrawableId = R.drawable.gd_action_bar_star_alt;
+ descriptionId = R.string.gd_star;
+ break;
+
+ case SortBySize:
+ normalDrawableId = R.drawable.gd_action_bar_sort_by_size_normal;
+ altDrawableId = R.drawable.gd_action_bar_sort_by_size_alt;
+ descriptionId = R.string.gd_sort_by_size;
+ break;
+
+ case LocateMyself:
+ normalDrawableId = R.drawable.gd_action_bar_locate_myself_normal;
+ altDrawableId = R.drawable.gd_action_bar_locate_myself_alt;
+ descriptionId = R.string.gd_locate_myself;
+ break;
+
+ default:
+ // Do nothing but return null
+ return null;
+ }
+
+ final Drawable d = createStateListDrawable(actionBar.getContext(), normalDrawableId, altDrawableId);
+
+ return actionBar.newActionBarItem(NormalActionBarItem.class).setDrawable(d)
+ .setContentDescription(descriptionId);
+ }
+
+ private static Drawable createStateListDrawable(Context context, int normalDrawableId, int altDrawableId) {
+
+ StateListDrawable stateListDrawable = new StateListDrawable();
+ Drawable normalDrawable = context.getResources().getDrawable(normalDrawableId);
+ Drawable altDrawable = context.getResources().getDrawable(altDrawableId);
+
+ stateListDrawable.addState(ENABLED_FOCUSED_STATE_SET, altDrawable);
+ stateListDrawable.addState(ENABLED_PRESSED_STATE_SET, altDrawable);
+ stateListDrawable.addState(ENABLE_STATE_SET, normalDrawable);
+
+ return stateListDrawable;
+ }
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/ItemAdapter.java b/greendroid/GreenDroid/src/greendroid/widget/ItemAdapter.java
new file mode 100644
index 000000000..30a968c49
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/ItemAdapter.java
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import greendroid.widget.item.DescriptionItem;
+import greendroid.widget.item.DrawableItem;
+import greendroid.widget.item.Item;
+import greendroid.widget.item.LongTextItem;
+import greendroid.widget.item.ProgressItem;
+import greendroid.widget.item.SeparatorItem;
+import greendroid.widget.item.SubtextItem;
+import greendroid.widget.item.SubtitleItem;
+import greendroid.widget.item.TextItem;
+import greendroid.widget.item.ThumbnailItem;
+import greendroid.widget.itemview.ItemView;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.util.Xml;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+/**
+ *
+ * A {@link ListAdapter} that acts like an {@link ArrayAdapter}. It manages a
+ * ListView that is backed by an array of {@link Item}s. This is more advanced
+ * than a simple {@link ArrayAdapter} because it handles different types of
+ * cells internally. Adding, removing items from the internal array is also
+ * possible.
+ *
+ *
+ * The {@link ListView} can be notified manually using
+ * {@link notifyDataSetChanged} or automatically using the notifyOnChange flag.
+ *
+ *
+ * Finally, an ItemAdapter can be created via XML code using the createFromXml
+ * method. This is a very powerful feature when you want to display static data
+ * or if you want to prepopulate your ItemAdapter.
+ *
+ *
+ * @author Cyril Mottier
+ */
+public class ItemAdapter extends BaseAdapter {
+
+ private static final int DEFAULT_MAX_VIEW_TYPE_COUNT = 10;
+
+ private static class TypeInfo {
+ int count;
+ int type;
+ }
+
+ private List mItems;
+ private HashMap, TypeInfo> mTypes;
+ private Context mContext;
+
+ private boolean mNotifyOnChange;
+ private int mMaxViewTypeCount;
+
+ /**
+ * Constructs an empty ItemAdapter.
+ *
+ * @param context The context associated with this array adapter.
+ */
+ public ItemAdapter(Context context) {
+ this(context, new ArrayList());
+ }
+
+ /**
+ * Constructs an ItemAdapter using the specified items.
+ *
+ * Note : Using this constructor implies the internal array will be
+ * immutable. As a result, adding or removing items will result in an
+ * exception.
+ *
+ *
+ * @param context The context associated with this array adapter.
+ * @param items The array of Items use as underlying data for this
+ * ItemAdapter
+ */
+ public ItemAdapter(Context context, Item[] items) {
+ this(context, Arrays.asList(items), DEFAULT_MAX_VIEW_TYPE_COUNT);
+ }
+
+ /**
+ * Constructs an ItemAdapter using the specified items.
+ *
+ *
+ * @param context The context associated with this array adapter.
+ * @param items The list of Items used as data for this ItemAdapter
+ */
+ public ItemAdapter(Context context, List items) {
+ this(context, items, DEFAULT_MAX_VIEW_TYPE_COUNT);
+ }
+
+ /**
+ * Constructs an ItemAdapter using the specified items.
+ *
+ * Note : Using this constructor implies the internal array will be
+ * immutable. As a result, adding or removing items will result in an
+ * exception.
+ *
+ *
+ * Note: A ListAdapter doesn't handle variable view type
+ * count (even after a notifyDataSetChanged). An ItemAdapter handles several
+ * types of cell are therefore use a trick to overcome the previous problem.
+ * This trick is to fool the ListView several types exist. If you already
+ * know the number of item types you can have, simply set it using this method
+ *
+ *
+ * @param context The context associated with this array adapter.
+ * @param items The array of Items use as underlying data for this
+ * ItemAdapter
+ * @param maxViewTypeCount The maximum number of view type that may be
+ * generated by this ItemAdapter
+ */
+ public ItemAdapter(Context context, Item[] items, int maxViewTypeCount) {
+ this(context, Arrays.asList(items), maxViewTypeCount);
+ }
+
+ /**
+ * Constructs an ItemAdapter using the specified items.
+ *
+ * Note: A ListAdapter doesn't handle variable view type
+ * count (even after a notifyDataSetChanged). An ItemAdapter handles several
+ * types of cell are therefore use a trick to overcome the previous problem.
+ * This trick is to fool the ListView several types exist. If you already
+ * know the number of item types you can have, simply set it using this method
+ *
+ *
+ * @param context The context associated with this array adapter.
+ * @param items The list of Items used as data for this ItemAdapter
+ * @param maxViewTypeCount The maximum number of view type that may be
+ * generated by this ItemAdapter
+ */
+ public ItemAdapter(Context context, List items, int maxViewTypeCount) {
+ mContext = context;
+ mItems = items;
+ mTypes = new HashMap, TypeInfo>();
+ mMaxViewTypeCount = Integer.MAX_VALUE;
+
+ for (Item item : mItems) {
+ addItem(item);
+ }
+
+ mMaxViewTypeCount = Math.max(1, Math.max(mTypes.size(), maxViewTypeCount));
+ }
+
+ private void addItem(Item item) {
+ final Class extends Item> klass = item.getClass();
+ TypeInfo info = mTypes.get(klass);
+
+ if (info == null) {
+ final int type = mTypes.size();
+ if (type >= mMaxViewTypeCount) {
+ throw new RuntimeException("This ItemAdapter may handle only " + mMaxViewTypeCount
+ + " different view types.");
+ }
+ final TypeInfo newInfo = new TypeInfo();
+ newInfo.count = 1;
+ newInfo.type = type;
+ mTypes.put(klass, newInfo);
+ } else {
+ info.count++;
+ }
+ }
+
+ private void removeItem(Item item) {
+ final Class extends Item> klass = item.getClass();
+ TypeInfo info = mTypes.get(klass);
+
+ if (info != null) {
+ info.count--;
+ if (info.count == 0) {
+ // TODO cyril: Creating a pool to keep all TypeInfo instances
+ // could be a great idea in the future.
+ mTypes.remove(klass);
+ }
+ }
+ }
+
+ /**
+ * Returns the context associated with this array adapter. The context is
+ * used to create views from the resource passed to the constructor.
+ *
+ * @return The Context associated to this ItemAdapter
+ */
+ public Context getContext() {
+ return mContext;
+ }
+
+ /**
+ * Returns the current number of different views types used in this
+ * ItemAdapter. Having a getCurrentViewTypeCount equal to
+ * getViewTypeCount means you won't be able to add a new type of
+ * view in this adapter (The Adapter class doesn't allow variable view type
+ * count).
+ *
+ * @return The current number of different view types
+ */
+ public int getActualViewTypeCount() {
+ return mTypes.size();
+ }
+
+ /**
+ * Adds the specified object at the end of the array.
+ *
+ * @param object The object to add at the end of the array.
+ */
+ public void add(Item item) {
+ mItems.add(item);
+ addItem(item);
+ if (mNotifyOnChange) {
+ notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * Inserts the specified object at the specified index in the array.
+ *
+ * @param item The object to insert into the array.
+ * @param index The index at which the object must be inserted.
+ */
+ public void insert(Item item, int index) {
+ mItems.add(index, item);
+ addItem(item);
+ if (mNotifyOnChange) {
+ notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * Removes the specified object from the array.
+ *
+ * @param object The object to remove.
+ */
+ public void remove(Item item) {
+ if (mItems.remove(item)) {
+ removeItem(item);
+ if (mNotifyOnChange) {
+ notifyDataSetChanged();
+ }
+ }
+ }
+
+ /**
+ * Remove all elements from the list.
+ */
+ public void clear() {
+ mItems.clear();
+ mTypes.clear();
+ if (mNotifyOnChange) {
+ notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * Sorts the content of this adapter using the specified comparator.
+ *
+ * @param comparator The comparator used to sort the objects contained in
+ * this adapter.
+ */
+ public void sort(Comparator super Item> comparator) {
+ Collections.sort(mItems, comparator);
+ if (mNotifyOnChange) {
+ notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * Control whether methods that change the list ({@link #add},
+ * {@link #insert}, {@link #remove}, {@link #clear}) automatically call
+ * {@link #notifyDataSetChanged}. If set to false, caller must manually call
+ * notifyDataSetChanged() to have the changes reflected in the attached
+ * view. The default is true, and calling notifyDataSetChanged() resets the
+ * flag to true.
+ *
+ * @param notifyOnChange if true, modifications to the list will
+ * automatically call {@link #notifyDataSetChanged}
+ */
+ public void setNotifyOnChange(boolean notifyOnChange) {
+ mNotifyOnChange = notifyOnChange;
+ }
+
+ /**
+ * Creates an ItemAdapter from a given resource ID
+ *
+ * @param context The Context in which the ItemAdapter will be used in
+ * @param xmlId The resource ID of an XML file that describes a set of
+ * {@link Item}
+ * @return a new ItemAdapter constructed with the content of the file
+ * pointed by xmlId
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ public static ItemAdapter createFromXml(Context context, int xmlId) throws XmlPullParserException, IOException {
+ return createFromXml(context, context.getResources().getXml(xmlId));
+ }
+
+ /**
+ * Creates an ItemAdapter from a given XML document. Called on a parser
+ * positioned at a tag in an XML document, tries to create an ItemAdapter
+ * from that tag.
+ *
+ * @param context The Context in which the ItemAdapter will be used in
+ * @param xmlId The resource ID of an XML file that describes a set of
+ * {@link Item}
+ * @return a new ItemAdapter constructed with the content of the file
+ * pointed by xmlId
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ public static ItemAdapter createFromXml(Context context, XmlPullParser parser) throws XmlPullParserException,
+ IOException {
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ if (!parser.getName().equals("item-array")) {
+ throw new XmlPullParserException("Unknown start tag. Should be 'item-array'");
+ }
+
+ final List items = new ArrayList();
+ final int innerDepth = parser.getDepth() + 1;
+ final Resources r = context.getResources();
+
+ int depth;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (depth > innerDepth) {
+ continue;
+ }
+
+ String name = parser.getName();
+ Item item;
+ if (name.equals("text-item")) {
+ item = new TextItem();
+ } else if (name.equals("longtext-item")) {
+ item = new LongTextItem();
+ } else if (name.equals("description-item")) {
+ item = new DescriptionItem();
+ } else if (name.equals("separator-item")) {
+ item = new SeparatorItem();
+ } else if (name.equals("progress-item")) {
+ item = new ProgressItem();
+ } else if (name.equals("drawable-item")) {
+ item = new DrawableItem();
+ } else if (name.equals("subtitle-item")) {
+ item = new SubtitleItem();
+ } else if (name.equals("subtext-item")) {
+ item = new SubtextItem();
+ } else if (name.equals("thumbnail-item")) {
+ item = new ThumbnailItem();
+ } else {
+ // TODO cyril: Remove that so that we can extend from
+ // ItemAdapter and creates our own items via XML?
+ throw new XmlPullParserException(parser.getPositionDescription() + ": invalid item tag " + name);
+ }
+
+ // TODO cyril: Here we should call a method that children may
+ // override to be able to create our own Items
+
+ if (item != null) {
+ item.inflate(r, parser, attrs);
+ items.add(item);
+ }
+ }
+
+ return new ItemAdapter(context, items);
+ }
+
+ public int getCount() {
+ return mItems.size();
+ }
+
+ public Object getItem(int position) {
+ return mItems.get(position);
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mTypes.get(getItem(position).getClass()).type;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return ((Item) getItem(position)).enabled;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return mMaxViewTypeCount;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+
+ final Item item = (Item) getItem(position);
+ ItemView cell = (ItemView) convertView;
+
+ if (cell == null) {
+ cell = item.newView(mContext, null);
+ cell.prepareItemView();
+ }
+
+ cell.setObject(item);
+
+ return (View) cell;
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/LoaderActionBarItem.java b/greendroid/GreenDroid/src/greendroid/widget/LoaderActionBarItem.java
new file mode 100644
index 000000000..2f505d665
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/LoaderActionBarItem.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * An extension of a {@link NormalActionBarItem} that supports a loading states.
+ * When in loading state, a {@link LoaderActionBarItem} display an indeterminate
+ * circular {@link ProgressBar}. This item is very handful with application
+ * fetching data from the network or performing long background tasks.
+ *
+ * @author Cyril Mottier
+ */
+public class LoaderActionBarItem extends NormalActionBarItem {
+
+ private boolean mLoading;
+ private View mButton;
+ private View mProgressBar;
+
+ public LoaderActionBarItem() {
+ mLoading = false;
+ }
+
+ @Override
+ protected View createItemView() {
+ return LayoutInflater.from(mContext).inflate(R.layout.gd_action_bar_item_loader, mActionBar, false);
+ }
+
+ @Override
+ protected void prepareItemView() {
+ super.prepareItemView();
+ mButton = mItemView.findViewById(R.id.gd_action_bar_item);
+ mProgressBar = mItemView.findViewById(R.id.gd_action_bar_item_progress_bar);
+ }
+
+ @Override
+ protected void onItemClicked() {
+ super.onItemClicked();
+ setLoading(true);
+ }
+
+ /**
+ * Sets the loading state of this {@link LoaderActionBarItem}.
+ *
+ * @param loading The new loading state. If true, an indeterminate
+ * {@link ProgressBar} is displayed. When false (default value)
+ * the {@link ActionBarItem} behaves exactly like a regular
+ * {@link NormalActionBarItem}.
+ */
+ public void setLoading(boolean loading) {
+ if (loading != mLoading) {
+ mProgressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
+ mButton.setVisibility(loading ? View.GONE : View.VISIBLE);
+ mLoading = loading;
+ }
+ }
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/NormalActionBarItem.java b/greendroid/GreenDroid/src/greendroid/widget/NormalActionBarItem.java
new file mode 100644
index 000000000..03d43665e
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/NormalActionBarItem.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * Default implementation of an {@link ActionBarItem}. A
+ * {@link NormalActionBarItem} is a simple {@link ActionBarItem} containing a
+ * single icon.
+ *
+ * @author Cyril Mottier
+ */
+public class NormalActionBarItem extends ActionBarItem {
+
+ @Override
+ protected View createItemView() {
+ return LayoutInflater.from(mContext).inflate(R.layout.gd_action_bar_item_base, mActionBar, false);
+ }
+
+ @Override
+ protected void prepareItemView() {
+ super.prepareItemView();
+ final ImageButton imageButton = (ImageButton) mItemView.findViewById(R.id.gd_action_bar_item);
+ imageButton.setImageDrawable(mDrawable);
+ imageButton.setContentDescription(mContentDescription);
+ }
+
+ @Override
+ protected void onContentDescriptionChanged() {
+ super.onContentDescriptionChanged();
+ mItemView.findViewById(R.id.gd_action_bar_item).setContentDescription(mContentDescription);
+ }
+
+ @Override
+ protected void onDrawableChanged() {
+ super.onDrawableChanged();
+ ImageButton imageButton = (ImageButton) mItemView.findViewById(R.id.gd_action_bar_item);
+ imageButton.setImageDrawable(mDrawable);
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/QuickAction.java b/greendroid/GreenDroid/src/greendroid/widget/QuickAction.java
new file mode 100644
index 000000000..9249056b2
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/QuickAction.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import java.lang.ref.WeakReference;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+/**
+ * A QuickAction implements an item in a {@link QuickActionWidget}. A
+ * QuickAction represents a single action and may contain a text and an icon.
+ *
+ * @author Benjamin Fellous
+ * @author Cyril Mottier
+ */
+public class QuickAction {
+
+ public Drawable mDrawable;
+ public CharSequence mTitle;
+
+ /* package */WeakReference mView;
+
+ public QuickAction(Drawable d, CharSequence title) {
+ mDrawable = d;
+ mTitle = title;
+ }
+
+ public QuickAction(Context ctx, int drawableId, CharSequence title) {
+ mDrawable = ctx.getResources().getDrawable(drawableId);
+ mTitle = title;
+ }
+
+ public QuickAction(Context ctx, Drawable d, int titleId) {
+ mDrawable = d;
+ mTitle = ctx.getResources().getString(titleId);
+ }
+
+ public QuickAction(Context ctx, int drawableId, int titleId) {
+ mDrawable = ctx.getResources().getDrawable(drawableId);
+ mTitle = ctx.getResources().getString(titleId);
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/QuickActionBar.java b/greendroid/GreenDroid/src/greendroid/widget/QuickActionBar.java
new file mode 100644
index 000000000..0980e1737
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/QuickActionBar.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.LinearLayout;
+
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * A QuickActionBar displays a set of {@link QuickAction} on a single row. In
+ * case too many items are added to the QuickActionBar, the user can
+ * horizontally scroll QuickActions. Using a QuickActionBar is a great
+ * replacement for the long click UI pattern. For instance,
+ * {@link QuickActionBar} adds secondary actions to an item of a
+ * {@link ListView}.
+ *
+ * @author Benjamin Fellous
+ * @author Cyril Mottier
+ */
+public class QuickActionBar extends QuickActionWidget {
+
+ private HorizontalScrollView mScrollView;
+ private Animation mRackAnimation;
+ private ViewGroup mRack;
+ private ViewGroup mQuickActionItems;
+
+ private List mQuickActions;
+
+ public QuickActionBar(Context context) {
+ super(context);
+
+ mRackAnimation = AnimationUtils.loadAnimation(context, R.anim.gd_rack);
+
+ mRackAnimation.setInterpolator(new Interpolator() {
+ public float getInterpolation(float t) {
+ final float inner = (t * 1.55f) - 1.1f;
+ return 1.2f - inner * inner;
+ }
+ });
+
+ setContentView(R.layout.gd_quick_action_bar);
+
+ final View v = getContentView();
+ mRack = (ViewGroup) v.findViewById(R.id.gdi_rack);
+ mQuickActionItems = (ViewGroup) v.findViewById(R.id.gdi_quick_action_items);
+ mScrollView = (HorizontalScrollView) v.findViewById(R.id.gdi_scroll);
+ }
+
+ @Override
+ public void show(View anchor) {
+ super.show(anchor);
+ mScrollView.scrollTo(0, 0);
+ }
+
+ @Override
+ protected void onMeasureAndLayout(Rect anchorRect, View contentView) {
+
+ contentView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ contentView.measure(MeasureSpec.makeMeasureSpec(getScreenWidth(), MeasureSpec.EXACTLY),
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ int rootHeight = contentView.getMeasuredHeight();
+
+ int offsetY = getArrowOffsetY();
+ int dyTop = anchorRect.top;
+ int dyBottom = getScreenHeight() - anchorRect.bottom;
+
+ boolean onTop = (dyTop > dyBottom);
+ int popupY = (onTop) ? anchorRect.top - rootHeight + offsetY : anchorRect.bottom - offsetY;
+
+ setWidgetSpecs(popupY, onTop);
+ }
+
+ @Override
+ protected void populateQuickActions(List quickActions) {
+
+ mQuickActions = quickActions;
+
+ final LayoutInflater inflater = LayoutInflater.from(getContext());
+
+ for (QuickAction action : quickActions) {
+ TextView view = (TextView) inflater.inflate(R.layout.gd_quick_action_bar_item, mQuickActionItems, false);
+ view.setText(action.mTitle);
+
+ view.setCompoundDrawablesWithIntrinsicBounds(null, action.mDrawable, null, null);
+ view.setOnClickListener(mClickHandlerInternal);
+ mQuickActionItems.addView(view);
+ action.mView = new WeakReference(view);
+ }
+ }
+
+ @Override
+ protected void onClearQuickActions() {
+ super.onClearQuickActions();
+ mQuickActionItems.removeAllViews();
+ }
+
+ private OnClickListener mClickHandlerInternal = new OnClickListener() {
+
+ public void onClick(View view) {
+
+ final OnQuickActionClickListener listener = getOnQuickActionClickListener();
+
+ if (listener != null) {
+ final int itemCount = mQuickActions.size();
+ for (int i = 0; i < itemCount; i++) {
+ if (view == mQuickActions.get(i).mView.get()) {
+ listener.onQuickActionClicked(QuickActionBar.this, i);
+ break;
+ }
+ }
+ }
+
+ if (getDismissOnClick()) {
+ dismiss();
+ }
+ }
+
+ };
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/QuickActionGrid.java b/greendroid/GreenDroid/src/greendroid/widget/QuickActionGrid.java
new file mode 100644
index 000000000..9692f7b45
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/QuickActionGrid.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import java.util.List;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * A {@link QuickActionGrid} is an implementation of a {@link QuickActionWidget}
+ * that displays {@link QuickAction}s in a grid manner. This is usually used to create
+ * a shortcut to jump between different type of information on screen.
+ *
+ * @author Benjamin Fellous
+ * @author Cyril Mottier
+ */
+public class QuickActionGrid extends QuickActionWidget {
+
+ private GridView mGridView;
+
+ public QuickActionGrid(Context context) {
+ super(context);
+
+ setContentView(R.layout.gd_quick_action_grid);
+
+ final View v = getContentView();
+ mGridView = (GridView) v.findViewById(R.id.gdi_grid);
+ }
+
+ @Override
+ protected void populateQuickActions(final List quickActions) {
+
+ mGridView.setAdapter(new BaseAdapter() {
+
+ public View getView(int position, View view, ViewGroup parent) {
+
+ TextView textView = (TextView) view;
+
+ if (view == null) {
+ final LayoutInflater inflater = LayoutInflater.from(getContext());
+ textView = (TextView) inflater.inflate(R.layout.gd_quick_action_grid_item, mGridView, false);
+ }
+
+ QuickAction quickAction = quickActions.get(position);
+ textView.setText(quickAction.mTitle);
+ textView.setCompoundDrawablesWithIntrinsicBounds(null, quickAction.mDrawable, null, null);
+
+ return textView;
+
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public Object getItem(int position) {
+ return null;
+ }
+
+ public int getCount() {
+ return quickActions.size();
+ }
+ });
+
+ mGridView.setOnItemClickListener(mInternalItemClickListener);
+ }
+
+ @Override
+ protected void onMeasureAndLayout(Rect anchorRect, View contentView) {
+
+ contentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ contentView.measure(MeasureSpec.makeMeasureSpec(getScreenWidth(), MeasureSpec.EXACTLY),
+ LayoutParams.WRAP_CONTENT);
+
+ int rootHeight = contentView.getMeasuredHeight();
+
+ int offsetY = getArrowOffsetY();
+ int dyTop = anchorRect.top;
+ int dyBottom = getScreenHeight() - anchorRect.bottom;
+
+ boolean onTop = (dyTop > dyBottom);
+ int popupY = (onTop) ? anchorRect.top - rootHeight + offsetY : anchorRect.bottom - offsetY;
+
+ setWidgetSpecs(popupY, onTop);
+ }
+
+ private OnItemClickListener mInternalItemClickListener = new OnItemClickListener() {
+ public void onItemClick(AdapterView> adapterView, View view, int position, long id) {
+ getOnQuickActionClickListener().onQuickActionClicked(QuickActionGrid.this, position);
+ if (getDismissOnClick()) {
+ dismiss();
+ }
+ }
+ };
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/QuickActionWidget.java b/greendroid/GreenDroid/src/greendroid/widget/QuickActionWidget.java
new file mode 100644
index 000000000..febc4d91d
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/QuickActionWidget.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.PopupWindow;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * Abstraction of a {@link QuickAction} wrapper. A QuickActionWidget is
+ * displayed on top of the user interface (it overlaps all UI elements but the
+ * notification bar). Clients may listen to user actions using a
+ * {@link OnQuickActionClickListener} .
+ *
+ * @author Benjamin Fellous
+ * @author Cyril Mottier
+ */
+public abstract class QuickActionWidget extends PopupWindow {
+
+ private static final int MEASURE_AND_LAYOUT_DONE = 1 << 1;
+
+ private final int[] mLocation = new int[2];
+ private final Rect mRect = new Rect();
+
+ private int mPrivateFlags;
+
+ private Context mContext;
+
+ private boolean mDismissOnClick;
+ private int mArrowOffsetY;
+
+ private int mPopupY;
+ private boolean mIsOnTop;
+
+ private int mScreenHeight;
+ private int mScreenWidth;
+ private boolean mIsDirty;
+
+ private OnQuickActionClickListener mOnQuickActionClickListener;
+ private ArrayList mQuickActions = new ArrayList();
+
+ /**
+ * Interface that may be used to listen to clicks on quick actions.
+ *
+ * @author Benjamin Fellous
+ * @author Cyril Mottier
+ */
+ public static interface OnQuickActionClickListener {
+ /**
+ * Clients may implement this method to be notified of a click on a
+ * particular quick action.
+ *
+ * @param position Position of the quick action that have been clicked.
+ */
+ void onQuickActionClicked(QuickActionWidget widget, int position);
+ }
+
+ /**
+ * Creates a new QuickActionWidget for the given context.
+ *
+ * @param context The context in which the QuickActionWidget is running in
+ */
+ public QuickActionWidget(Context context) {
+ super(context);
+
+ mContext = context;
+
+ initializeDefault();
+
+ setFocusable(true);
+ setTouchable(true);
+ setOutsideTouchable(true);
+ setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
+ setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
+
+ final WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ mScreenWidth = windowManager.getDefaultDisplay().getWidth();
+ mScreenHeight = windowManager.getDefaultDisplay().getHeight();
+ }
+
+ /**
+ * Equivalent to {@link PopupWindow#setContentView(View)} but with a layout
+ * identifier.
+ *
+ * @param layoutId The layout identifier of the view to use.
+ */
+ public void setContentView(int layoutId) {
+ setContentView(LayoutInflater.from(mContext).inflate(layoutId, null));
+ }
+
+ private void initializeDefault() {
+ mDismissOnClick = true;
+ mArrowOffsetY = mContext.getResources().getDimensionPixelSize(R.dimen.gd_arrow_offset);
+ }
+
+ /**
+ * Returns the arrow offset for the Y axis.
+ *
+ * @see {@link #setArrowOffsetY(int)}
+ * @return The arrow offset.
+ */
+ public int getArrowOffsetY() {
+ return mArrowOffsetY;
+ }
+
+ /**
+ * Sets the arrow offset to a new value. Setting an arrow offset may be
+ * particular useful to warn which view the QuickActionWidget is related to.
+ * By setting a positive offset, the arrow will overlap the view given by
+ * {@link #show(View)}. The default value is 5dp.
+ *
+ * @param offsetY The offset for the Y axis
+ */
+ public void setArrowOffsetY(int offsetY) {
+ mArrowOffsetY = offsetY;
+ }
+
+ /**
+ * Returns the width of the screen.
+ *
+ * @return The width of the screen
+ */
+ protected int getScreenWidth() {
+ return mScreenWidth;
+ }
+
+ /**
+ * Returns the height of the screen.
+ *
+ * @return The height of the screen
+ */
+ protected int getScreenHeight() {
+ return mScreenHeight;
+ }
+
+ /**
+ * By default, a {@link QuickActionWidget} is dismissed once the user
+ * clicked on a {@link QuickAction}. This behavior can be changed using this
+ * method.
+ *
+ * @param dismissOnClick True if you want the {@link QuickActionWidget} to
+ * be dismissed on click else false.
+ */
+ public void setDismissOnClick(boolean dismissOnClick) {
+ mDismissOnClick = dismissOnClick;
+ }
+
+ public boolean getDismissOnClick() {
+ return mDismissOnClick;
+ }
+
+ /**
+ * @param listener
+ */
+ public void setOnQuickActionClickListener(OnQuickActionClickListener listener) {
+ mOnQuickActionClickListener = listener;
+ }
+
+ /**
+ * Add a new QuickAction to this {@link QuickActionWidget}. Adding a new
+ * {@link QuickAction} while the {@link QuickActionWidget} is currently
+ * being shown does nothing. The new {@link QuickAction} will be displayed
+ * on the next call to {@link #show(View)}.
+ *
+ * @param action The new {@link QuickAction} to add
+ */
+ public void addQuickAction(QuickAction action) {
+ if (action != null) {
+ mQuickActions.add(action);
+ mIsDirty = true;
+ }
+ }
+
+ /**
+ * Removes all {@link QuickAction} from this {@link QuickActionWidget}.
+ */
+ public void clearAllQuickActions() {
+ if (!mQuickActions.isEmpty()) {
+ mQuickActions.clear();
+ mIsDirty = true;
+ }
+ }
+
+ /**
+ * Call that method to display the {@link QuickActionWidget} anchored to the
+ * given view.
+ *
+ * @param anchor The view the {@link QuickActionWidget} will be anchored to.
+ */
+ public void show(View anchor) {
+
+ final View contentView = getContentView();
+
+ if (contentView == null) {
+ throw new IllegalStateException("You need to set the content view using the setContentView method");
+ }
+
+ // Replaces the background of the popup with a cleared background
+ setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+
+ final int[] loc = mLocation;
+ anchor.getLocationOnScreen(loc);
+ mRect.set(loc[0], loc[1], loc[0] + anchor.getWidth(), loc[1] + anchor.getHeight());
+
+ if (mIsDirty) {
+ clearQuickActions();
+ populateQuickActions(mQuickActions);
+ }
+
+ onMeasureAndLayout(mRect, contentView);
+
+ if ((mPrivateFlags & MEASURE_AND_LAYOUT_DONE) != MEASURE_AND_LAYOUT_DONE) {
+ throw new IllegalStateException("onMeasureAndLayout() did not set the widget specification by calling"
+ + " setWidgetSpecs()");
+ }
+
+ showArrow();
+ prepareAnimationStyle();
+ showAtLocation(anchor, Gravity.NO_GRAVITY, 0, mPopupY);
+ }
+
+ protected void clearQuickActions() {
+ if (!mQuickActions.isEmpty()) {
+ onClearQuickActions();
+ }
+ }
+
+ protected void onClearQuickActions() {
+ }
+
+ protected abstract void populateQuickActions(List quickActions);
+
+ protected abstract void onMeasureAndLayout(Rect anchorRect, View contentView);
+
+ protected void setWidgetSpecs(int popupY, boolean isOnTop) {
+ mPopupY = popupY;
+ mIsOnTop = isOnTop;
+
+ mPrivateFlags |= MEASURE_AND_LAYOUT_DONE;
+ }
+
+ private void showArrow() {
+
+ final View contentView = getContentView();
+ final int arrowId = mIsOnTop ? R.id.gdi_arrow_down : R.id.gdi_arrow_up;
+ final View arrow = contentView.findViewById(arrowId);
+ final View arrowUp = contentView.findViewById(R.id.gdi_arrow_up);
+ final View arrowDown = contentView.findViewById(R.id.gdi_arrow_down);
+
+ if (arrowId == R.id.gdi_arrow_up) {
+ arrowUp.setVisibility(View.VISIBLE);
+ arrowDown.setVisibility(View.INVISIBLE);
+ } else if (arrowId == R.id.gdi_arrow_down) {
+ arrowUp.setVisibility(View.INVISIBLE);
+ arrowDown.setVisibility(View.VISIBLE);
+ }
+
+ ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams) arrow.getLayoutParams();
+ param.leftMargin = mRect.centerX() - (arrow.getMeasuredWidth()) / 2;
+ }
+
+ private void prepareAnimationStyle() {
+
+ final int screenWidth = mScreenWidth;
+ final boolean onTop = mIsOnTop;
+ final int arrowPointX = mRect.centerX();
+
+ if (arrowPointX <= screenWidth / 4) {
+ setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Left
+ : R.style.GreenDroid_Animation_PopDown_Left);
+ } else if (arrowPointX >= 3 * screenWidth / 4) {
+ setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Right
+ : R.style.GreenDroid_Animation_PopDown_Right);
+ } else {
+ setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Center
+ : R.style.GreenDroid_Animation_PopDown_Center);
+ }
+ }
+
+ protected Context getContext() {
+ return mContext;
+ }
+
+ protected OnQuickActionClickListener getOnQuickActionClickListener() {
+ return mOnQuickActionClickListener;
+ }
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/SegmentedAdapter.java b/greendroid/GreenDroid/src/greendroid/widget/SegmentedAdapter.java
new file mode 100644
index 000000000..9e3f01e60
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/SegmentedAdapter.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import android.database.DataSetObservable;
+import android.database.DataSetObserver;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A SegmentedAdapter is a data source of a SegmentedHost/SegmentedHost.
+ *
+ * @author Cyril Mottier
+ */
+public abstract class SegmentedAdapter {
+
+ private final DataSetObservable mDataSetObservable = new DataSetObservable();
+
+ /**
+ * How many segments have to be displayed
+ *
+ * @return The number of segment displayed by the underlying SegmentedBar
+ */
+ public abstract int getCount();
+
+ /**
+ * Get the View associated to the segment at position position
+ *
+ * @param position The position of the item in the SegmentedAdapter
+ * @param parent The parent that this view will eventually be attached to
+ * @return A View corresponding to the segment at the given position
+ */
+ public abstract View getView(int position, ViewGroup parent);
+
+ /**
+ * Get the title for the segment at position position
+ *
+ * @param position The position of the segment in the SegmentedBar
+ * @return A title for the segment at the given position.
+ */
+ public abstract String getSegmentTitle(int position);
+
+ /**
+ * Register an observer that is called when changes happen to the data used
+ * by this adapter.
+ *
+ * @param observer The object that gets notified when the data set changes.
+ */
+ public void registerDataSetObserver(DataSetObserver observer) {
+ mDataSetObservable.registerObserver(observer);
+ }
+
+ /**
+ * Unregister an observer that has previously been registered with this
+ * adapter via {@link #unregisterDataSetObserver(DataSetObserver)}
+ *
+ * @param observer The object to unregister
+ */
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ mDataSetObservable.unregisterObserver(observer);
+ }
+
+ /**
+ * Notifies the attached View that the underlying data has changed and
+ * should refresh itself.
+ */
+ public void notifyDataSetChanged() {
+ mDataSetObservable.notifyChanged();
+ }
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/SegmentedBar.java b/greendroid/GreenDroid/src/greendroid/widget/SegmentedBar.java
new file mode 100644
index 000000000..1b8a34936
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/SegmentedBar.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * A SegmentedBar displays a set of Buttons. Only one segment in a SegmentedBar
+ * can be selected at a time. A SegmentedBar is very close to a TabWidget in
+ * term of functionalities.
+ *
+ * @author Cyril Mottier
+ */
+public class SegmentedBar extends LinearLayout implements OnFocusChangeListener {
+
+ /**
+ * Clients may use this listener to be notified of any changes that occurs
+ * on the SegmentBar
+ *
+ * @author Cyril Mottier
+ */
+ public static interface OnSegmentChangeListener {
+ /**
+ * Notification that the current segment has changed.
+ *
+ * @param index The index of the new selected segment.
+ * @param clicked Whether the segment has been selected via a user
+ * click.
+ */
+ public void onSegmentChange(int index, boolean clicked);
+ }
+
+ private OnSegmentChangeListener mOnSegmentChangeListener;
+ private int mCheckedSegment;
+ private Drawable mDividerDrawable;
+ private int mDividerWidth;
+
+ public SegmentedBar(Context context) {
+ this(context, null);
+ }
+
+ public SegmentedBar(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.gdSegmentedBarStyle);
+ }
+
+ public SegmentedBar(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs);
+ initSegmentedBar();
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SegmentedBar, defStyle, 0);
+
+ mDividerDrawable = a.getDrawable(R.styleable.SegmentedBar_dividerDrawable);
+ mDividerWidth = a.getDimensionPixelSize(R.styleable.SegmentedBar_dividerWidth, 0);
+
+ a.recycle();
+ }
+
+ private void initSegmentedBar() {
+ mCheckedSegment = 0;
+ setOrientation(LinearLayout.HORIZONTAL);
+
+ // Register ourselves so that we can handle focus on internal segments
+ setFocusable(true);
+ setOnFocusChangeListener(this);
+ }
+
+ /**
+ * Sets the drawable that is used as divider between each segment.
+ *
+ * @param dividerDrawable The drawable to used as a divider. Note : using a
+ * ColorDrawable will not work properly as the intrinsic width of
+ * a ColorDrawable is -1.
+ */
+ public void setDividerDrawable(Drawable dividerDrawable) {
+ mDividerDrawable = dividerDrawable;
+ }
+
+ /**
+ * Sets the drawable that is used as divider between each segment.
+ *
+ * @param resId The identifier of the Drawable to use.
+ */
+ public void setDividerDrawable(int resId) {
+ mDividerDrawable = getContext().getResources().getDrawable(resId);
+ }
+
+ /**
+ * Sets the width of the divider that will be used as segment divider. If
+ * the dividerWidth has not been set, the intrinsic width of the divider
+ * drawable is used.
+ *
+ * @param width Width of the divider
+ */
+ public void setDividerWidth(int width) {
+ mDividerWidth = width;
+ }
+
+ /**
+ * Returns the current number of segment in this SegmentBar
+ *
+ * @return The number of segments in this SegmentBar
+ */
+ public int getSegmentCount() {
+ int segmentCount = getChildCount();
+ // If we have divider we'll have an odd number of child
+ if (mDividerDrawable != null) {
+ segmentCount = (segmentCount + 1) / 2;
+ }
+ return segmentCount;
+ }
+
+ /**
+ * Use this method to register an OnSegmentChangeListener and listen to
+ * changes that occur on this SegmentBar
+ *
+ * @param listener The listener to use
+ */
+ public void setOnSegmentChangeListener(OnSegmentChangeListener listener) {
+ mOnSegmentChangeListener = listener;
+ }
+
+ /**
+ * Sets the current segment to the index index
+ *
+ * @param index The index of the segment to set. Client will be notified
+ * using this method of the segment change.
+ */
+ public void setCurrentSegment(int index) {
+ if (index < 0 || index >= getSegmentCount()) {
+ return;
+ }
+
+ ((CheckBox) getChildSegmentAt(mCheckedSegment)).setChecked(false);
+ mCheckedSegment = index;
+ ((CheckBox) getChildSegmentAt(mCheckedSegment)).setChecked(true);
+ }
+
+ /**
+ * Returns the view representing the segment at the index index
+ *
+ * @param index The index of the segment to retrieve
+ * @return The view that represents the segment at index index
+ */
+ public View getChildSegmentAt(int index) {
+ /*
+ * If we are using dividers, then instead of segments at 0, 1, 2, ... we
+ * have segments at 0, 2, 4, ...
+ */
+ if (mDividerDrawable != null) {
+ index *= 2;
+ }
+ return getChildAt(index);
+ }
+
+ /**
+ * Adds a segment to the SegmentBar. This method automatically adds a
+ * divider if needed.
+ *
+ * @param title The title of the segment to add.
+ */
+ public void addSegment(String title) {
+
+ final Context context = getContext();
+ final LayoutInflater inflater = LayoutInflater.from(context);
+
+ /*
+ * First of all, we have to check whether or not we need to add a
+ * divider. A divider is added when there is at least one segment
+ */
+ if (mDividerDrawable != null && getSegmentCount() > 0) {
+ ImageView divider = new ImageView(context);
+ final int width = (mDividerWidth > 0) ? mDividerWidth : mDividerDrawable.getIntrinsicWidth();
+ final LinearLayout.LayoutParams lp = new LayoutParams(width, LayoutParams.FILL_PARENT);
+ lp.setMargins(0, 0, 0, 0);
+ divider.setLayoutParams(lp);
+ divider.setBackgroundDrawable(mDividerDrawable);
+ addView(divider);
+ }
+
+ CheckBox segment = (CheckBox) inflater.inflate(R.layout.gd_segment, this, false);
+ segment.setText(title);
+
+ segment.setClickable(true);
+ segment.setFocusable(true);
+ segment.setOnFocusChangeListener(this);
+ segment.setOnCheckedChangeListener(new SegmentCheckedListener(getSegmentCount()));
+ segment.setOnClickListener(new SegmentClickedListener(getSegmentCount()));
+
+ addView(segment);
+ }
+
+ public void onFocusChange(View v, boolean hasFocus) {
+
+ if (!hasFocus) {
+ return;
+ }
+
+ if (v == this) {
+ final View segment = getChildSegmentAt(mCheckedSegment);
+ if (segment != null) {
+ segment.requestFocus();
+ }
+ }
+
+ else {
+ final int segmentCounts = getSegmentCount();
+ for (int i = 0; i < segmentCounts; i++) {
+ if (getChildSegmentAt(i) == v) {
+ setCurrentSegment(i);
+ notifyListener(i, false);
+ break;
+ }
+ }
+ }
+ }
+
+ private class SegmentClickedListener implements OnClickListener {
+
+ private final int mSegmentIndex;
+
+ private SegmentClickedListener(int segmentIndex) {
+ mSegmentIndex = segmentIndex;
+ }
+
+ public void onClick(View v) {
+ final CheckBox segment = (CheckBox) getChildSegmentAt(mCheckedSegment);
+ if (mSegmentIndex == mCheckedSegment && !segment.isChecked()) {
+ segment.setChecked(true);
+ } else {
+ notifyListener(mSegmentIndex, true);
+ }
+ }
+
+ }
+
+ private class SegmentCheckedListener implements OnCheckedChangeListener {
+
+ private final int mSegmentIndex;
+
+ private SegmentCheckedListener(int segmentIndex) {
+ mSegmentIndex = segmentIndex;
+ }
+
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ setCurrentSegment(mSegmentIndex);
+ }
+ }
+ }
+
+ private void notifyListener(int index, boolean clicked) {
+ if (mOnSegmentChangeListener != null) {
+ mOnSegmentChangeListener.onSegmentChange(index, clicked);
+ }
+ }
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/SegmentedHost.java b/greendroid/GreenDroid/src/greendroid/widget/SegmentedHost.java
new file mode 100644
index 000000000..e6c52aade
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/SegmentedHost.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget;
+
+import greendroid.util.Config;
+import greendroid.widget.SegmentedBar.OnSegmentChangeListener;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * A SegmentedHost is a wrapper view that handle a SegmentedBar and a
+ * FrameLayout that hold the content. Data (titles, and content Views) are
+ * provided to the SegmentedHost via a {@link SegmentedAdapter}.
+ *
+ * @author Cyril Mottier
+ */
+public class SegmentedHost extends LinearLayout {
+
+ private final static String LOG_TAG = SegmentedHost.class.getSimpleName();
+
+ private int mSegmentedBarId;
+ private SegmentedBar mSegmentedBar;
+ private int mSegmentedHostId;
+ private FrameLayout mContentView;
+ private int mSelectedSegment;
+
+ private SegmentedAdapter mAdapter;
+ private View[] mViews;
+ private DataSetObserver mSegmentObserver = new DataSetObserver() {
+
+ public void onChanged() {
+ setupSegmentedHost(mSelectedSegment);
+ }
+
+ public void onInvalidated() {
+ // Do nothing - method never called
+ }
+ };
+
+ public SegmentedHost(Context context) {
+ this(context, null);
+ }
+
+ public SegmentedHost(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.gdSegmentedHostStyle);
+ }
+
+ public SegmentedHost(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs);
+ initSegmentedView();
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SegmentedHost, defStyle, 0);
+
+ mSegmentedBarId = a.getResourceId(R.styleable.SegmentedHost_segmentedBar, -1);
+ if (mSegmentedBarId <= 0) {
+ throw new IllegalArgumentException("The segmentedBar attribute is required and must refer "
+ + "to a valid child.");
+ }
+
+ mSegmentedHostId = a.getResourceId(R.styleable.SegmentedHost_segmentedContentView, -1);
+ if (mSegmentedHostId <= 0) {
+ throw new IllegalArgumentException("The segmentedHost attribute is required and must refer "
+ + "to a valid child.");
+ }
+ }
+
+ private void initSegmentedView() {
+ setOrientation(LinearLayout.VERTICAL);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mSegmentedBar = (SegmentedBar) findViewById(mSegmentedBarId);
+ if (mSegmentedBar == null) {
+ throw new IllegalArgumentException("The segmentedBar attribute must refer to an existing child.");
+ }
+ mSegmentedBar.setOnSegmentChangeListener(new SegmentSwitcher());
+
+ mContentView = (FrameLayout) findViewById(mSegmentedHostId);
+ if (mContentView == null) {
+ throw new IllegalArgumentException("The segmentedHost attribute must refer to an existing child.");
+ } else if (!(mContentView instanceof FrameLayout)) {
+ throw new RuntimeException("The segmentedHost attribute must refer to a FrameLayout");
+
+ }
+ }
+
+ public SegmentedBar getSegmentedBar() {
+ return mSegmentedBar;
+ }
+
+ public FrameLayout getContentView() {
+ return mContentView;
+ }
+
+ public void setAdapter(SegmentedAdapter adapter) {
+
+ if (mAdapter != null) {
+ mAdapter.unregisterDataSetObserver(mSegmentObserver);
+ }
+ mAdapter = adapter;
+
+ if (adapter != null) {
+ mAdapter.registerDataSetObserver(mSegmentObserver);
+ }
+ setupSegmentedHost(0);
+ }
+
+ private void setupSegmentedHost(int selectedSegment) {
+
+ if (Config.GD_INFO_LOGS_ENABLED) {
+ Log.i(LOG_TAG, "Preparing the SegmentedHost with the segment " + selectedSegment);
+ }
+
+ mSegmentedBar.removeAllViews();
+ mContentView.removeAllViews();
+ mViews = null;
+
+ if (mAdapter != null) {
+ // Add all segments to the Segmentedbar
+ final int count = mAdapter.getCount();
+ for (int i = 0; i < count; i++) {
+ mSegmentedBar.addSegment(mAdapter.getSegmentTitle(i));
+ }
+
+ if (selectedSegment < 0) {
+ selectedSegment = 0;
+ } else if (selectedSegment > count) {
+ selectedSegment = count;
+ }
+
+ if (count > 0) {
+ // Prepare the SegmentBar
+ mViews = new View[count];
+ mSegmentedBar.setCurrentSegment(selectedSegment);
+
+ // And displays the first view
+ setContentView(selectedSegment);
+ }
+ }
+ }
+
+ private class SegmentSwitcher implements OnSegmentChangeListener {
+ public void onSegmentChange(int index, boolean clicked) {
+ setContentView(index);
+ }
+ }
+
+ private void setContentView(int index) {
+ mSelectedSegment = index;
+ mContentView.removeAllViews();
+ if (mViews[index] == null) {
+ mViews[index] = mAdapter.getView(index, SegmentedHost.this);
+ }
+ mContentView.addView(mViews[index]);
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/item/DescriptionItem.java b/greendroid/GreenDroid/src/greendroid/widget/item/DescriptionItem.java
new file mode 100644
index 000000000..0c3e504da
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/item/DescriptionItem.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget.item;
+
+import greendroid.widget.itemview.ItemView;
+import android.content.Context;
+import android.view.ViewGroup;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * A description item displays a text on several lines. The default
+ * implementation makes it disabled.
+ *
+ * @author Cyril Mottier
+ */
+public class DescriptionItem extends TextItem {
+
+ /**
+ * @hide
+ */
+ public DescriptionItem() {
+ this(null);
+ }
+
+ /**
+ * Creates a new DescriptionItem with the given description.
+ *
+ * @param description The description for the current item.
+ */
+ public DescriptionItem(String description) {
+ super(description);
+ enabled = false;
+ }
+
+ @Override
+ public ItemView newView(Context context, ViewGroup parent) {
+ return createCellFromXml(context, R.layout.gd_description_item_view, parent);
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/item/DrawableItem.java b/greendroid/GreenDroid/src/greendroid/widget/item/DrawableItem.java
new file mode 100644
index 000000000..3635529ec
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/item/DrawableItem.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget.item;
+
+import greendroid.widget.itemview.ItemView;
+
+import java.io.IOException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * A DrawableItem displays a single Drawable on the left of the item cell and a
+ * description text on the right. A DrawableItem takes care of adapting itself
+ * depending on the presence of its Drawable.
+ *
+ * @author Cyril Mottier
+ */
+public class DrawableItem extends TextItem {
+
+ /**
+ * The resource identifier for the drawable.
+ */
+ public int drawableId;
+
+ /**
+ * @hide
+ */
+ public DrawableItem() {
+ this(null);
+ }
+
+ /**
+ * Constructs a new DrawableItem that has no Drawable and displays the given
+ * text. Used as it, a DrawableItem is very similar to a TextItem
+ *
+ * @param text The text of this DrawableItem
+ */
+ public DrawableItem(String text) {
+ this(text, 0);
+ }
+
+ /**
+ * Constructs a new DrawableItem that has no Drawable and displays the given
+ * text. Used as it, a DrawableItem is very similar to a TextItem
+ *
+ * @param text The text of this DrawableItem
+ * @param drawableId The resource identifier of the Drawable
+ */
+ public DrawableItem(String text, int drawableId) {
+ super(text);
+ this.drawableId = drawableId;
+ }
+
+ @Override
+ public ItemView newView(Context context, ViewGroup parent) {
+ return createCellFromXml(context, R.layout.gd_drawable_item_view, parent);
+ }
+
+ @Override
+ public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
+ IOException {
+ super.inflate(r, parser, attrs);
+
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.DrawableItem);
+ drawableId = a.getResourceId(R.styleable.DrawableItem_drawable, 0);
+ a.recycle();
+ }
+
+}
diff --git a/greendroid/GreenDroid/src/greendroid/widget/item/Item.java b/greendroid/GreenDroid/src/greendroid/widget/item/Item.java
new file mode 100644
index 000000000..3fc17b179
--- /dev/null
+++ b/greendroid/GreenDroid/src/greendroid/widget/item/Item.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
+ *
+ * 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.
+ */
+package greendroid.widget.item;
+
+import greendroid.widget.itemview.ItemView;
+
+import java.io.IOException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import com.cyrilmottier.android.greendroid.R;
+
+/**
+ * Base class for all items used in GreenDroid. An item represents a wrapper of
+ * data. Each item contains at least all the information needed to display a
+ * single row in a {@link ListView}.
+ *
+ * @author Cyril Mottier
+ */
+public abstract class Item {
+
+ private SparseArray